Add android proxy service
This commit is contained in:
@@ -8,7 +8,6 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.hiddify.hiddify.bg.ServiceConnection
|
||||
import com.hiddify.hiddify.bg.ServiceNotification
|
||||
import com.hiddify.hiddify.bg.VPNService
|
||||
import com.hiddify.hiddify.constant.Alert
|
||||
import com.hiddify.hiddify.constant.Status
|
||||
import io.flutter.embedding.android.FlutterFragmentActivity
|
||||
@@ -56,15 +55,15 @@ class MainActivity : FlutterFragmentActivity(), ServiceConnection.Callback {
|
||||
return
|
||||
}
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
// if (Settings.rebuildServiceMode()) {
|
||||
// reconnect()
|
||||
// }
|
||||
if (Settings.rebuildServiceMode()) {
|
||||
reconnect()
|
||||
}
|
||||
if (prepare()) {
|
||||
Log.d(TAG, "VPN permission required")
|
||||
return@launch
|
||||
}
|
||||
|
||||
val intent = Intent(Application.application, VPNService::class.java)
|
||||
val intent = Intent(Application.application, Settings.serviceClass())
|
||||
withContext(Dispatchers.Main) {
|
||||
ContextCompat.startForegroundService(Application.application, intent)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package com.hiddify.hiddify
|
||||
|
||||
import android.content.Context
|
||||
import com.hiddify.hiddify.bg.ProxyService
|
||||
import com.hiddify.hiddify.bg.VPNService
|
||||
import com.hiddify.hiddify.constant.ServiceMode
|
||||
import com.hiddify.hiddify.constant.SettingsKey
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
|
||||
object Settings {
|
||||
|
||||
@@ -24,6 +29,11 @@ object Settings {
|
||||
get() = preferences.getString(SettingsKey.ACTIVE_CONFIG_PATH, "") ?: ""
|
||||
set(value) = preferences.edit().putString(SettingsKey.ACTIVE_CONFIG_PATH, value).apply()
|
||||
|
||||
var serviceMode: String
|
||||
get() = preferences.getString(SettingsKey.SERVICE_MODE, ServiceMode.NORMAL)
|
||||
?: ServiceMode.NORMAL
|
||||
set(value) = preferences.edit().putString(SettingsKey.SERVICE_MODE, value).apply()
|
||||
|
||||
var configOptions: String
|
||||
get() = preferences.getString(SettingsKey.CONFIG_OPTIONS, "") ?: ""
|
||||
set(value) = preferences.edit().putString(SettingsKey.CONFIG_OPTIONS, value).apply()
|
||||
@@ -39,5 +49,41 @@ object Settings {
|
||||
var startedByUser: Boolean
|
||||
get() = preferences.getBoolean(SettingsKey.STARTED_BY_USER, false)
|
||||
set(value) = preferences.edit().putBoolean(SettingsKey.STARTED_BY_USER, value).apply()
|
||||
|
||||
fun serviceClass(): Class<*> {
|
||||
return when (serviceMode) {
|
||||
ServiceMode.VPN -> VPNService::class.java
|
||||
else -> ProxyService::class.java
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun rebuildServiceMode(): Boolean {
|
||||
var newMode = ServiceMode.NORMAL
|
||||
try {
|
||||
if (needVPNService()) {
|
||||
newMode = ServiceMode.VPN
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
if (serviceMode == newMode) {
|
||||
return false
|
||||
}
|
||||
serviceMode = newMode
|
||||
return true
|
||||
}
|
||||
|
||||
private suspend fun needVPNService(): Boolean {
|
||||
val filePath = activeConfigPath
|
||||
if (filePath.isBlank()) return false
|
||||
val content = JSONObject(File(filePath).readText())
|
||||
val inbounds = content.getJSONArray("inbounds")
|
||||
for (index in 0 until inbounds.length()) {
|
||||
val inbound = inbounds.getJSONObject(index)
|
||||
if (inbound.getString("type") == "tun") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@ interface PlatformInterfaceWrapper : PlatformInterface {
|
||||
error("invalid argument")
|
||||
}
|
||||
|
||||
override fun closeTun() {
|
||||
error("invalid argument")
|
||||
}
|
||||
|
||||
override fun useProcFS(): Boolean {
|
||||
return Build.VERSION.SDK_INT < Build.VERSION_CODES.Q
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.hiddify.hiddify.bg
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
|
||||
class ProxyService : Service(), PlatformInterfaceWrapper {
|
||||
|
||||
private val service = BoxService(this, this)
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int) =
|
||||
service.onStartCommand(intent, flags, startId)
|
||||
|
||||
override fun onBind(intent: Intent) = service.onBind(intent)
|
||||
override fun onDestroy() = service.onDestroy()
|
||||
|
||||
override fun writeLog(message: String) = service.writeLog(message)
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class ServiceConnection(
|
||||
fun connect() {
|
||||
val intent = runBlocking {
|
||||
withContext(Dispatchers.IO) {
|
||||
Intent(context, VPNService::class.java).setAction(Action.SERVICE)
|
||||
Intent(context, Settings.serviceClass()).setAction(Action.SERVICE)
|
||||
}
|
||||
}
|
||||
context.bindService(intent, this, AppCompatActivity.BIND_AUTO_CREATE)
|
||||
@@ -56,7 +56,7 @@ class ServiceConnection(
|
||||
}
|
||||
val intent = runBlocking {
|
||||
withContext(Dispatchers.IO) {
|
||||
Intent(context, VPNService::class.java).setAction(Action.SERVICE)
|
||||
Intent(context, Settings.serviceClass()).setAction(Action.SERVICE)
|
||||
}
|
||||
}
|
||||
context.bindService(intent, this, AppCompatActivity.BIND_AUTO_CREATE)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.hiddify.hiddify.constant
|
||||
|
||||
object ServiceMode {
|
||||
const val NORMAL = "normal"
|
||||
const val VPN = "vpn"
|
||||
}
|
||||
@@ -4,6 +4,7 @@ object SettingsKey {
|
||||
private const val KEY_PREFIX = "flutter."
|
||||
|
||||
const val ACTIVE_CONFIG_PATH = "${KEY_PREFIX}active_config_path"
|
||||
const val SERVICE_MODE = "${KEY_PREFIX}service_mode"
|
||||
|
||||
const val CONFIG_OPTIONS = "config_options_json"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user