diff --git a/android/app/src/main/kotlin/com/hiddify/hiddify/MainActivity.kt b/android/app/src/main/kotlin/com/hiddify/hiddify/MainActivity.kt index 3c3a6a33..fb5b8583 100644 --- a/android/app/src/main/kotlin/com/hiddify/hiddify/MainActivity.kt +++ b/android/app/src/main/kotlin/com/hiddify/hiddify/MainActivity.kt @@ -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) } diff --git a/android/app/src/main/kotlin/com/hiddify/hiddify/Settings.kt b/android/app/src/main/kotlin/com/hiddify/hiddify/Settings.kt index 0be52e5f..61c61d48 100644 --- a/android/app/src/main/kotlin/com/hiddify/hiddify/Settings.kt +++ b/android/app/src/main/kotlin/com/hiddify/hiddify/Settings.kt @@ -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 + } } diff --git a/android/app/src/main/kotlin/com/hiddify/hiddify/bg/PlatformInterfaceWrapper.kt b/android/app/src/main/kotlin/com/hiddify/hiddify/bg/PlatformInterfaceWrapper.kt index 9345bef7..8fc3f181 100644 --- a/android/app/src/main/kotlin/com/hiddify/hiddify/bg/PlatformInterfaceWrapper.kt +++ b/android/app/src/main/kotlin/com/hiddify/hiddify/bg/PlatformInterfaceWrapper.kt @@ -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 } diff --git a/android/app/src/main/kotlin/com/hiddify/hiddify/bg/ProxyService.kt b/android/app/src/main/kotlin/com/hiddify/hiddify/bg/ProxyService.kt new file mode 100644 index 00000000..ea30c2cd --- /dev/null +++ b/android/app/src/main/kotlin/com/hiddify/hiddify/bg/ProxyService.kt @@ -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) +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/hiddify/hiddify/bg/ServiceConnection.kt b/android/app/src/main/kotlin/com/hiddify/hiddify/bg/ServiceConnection.kt index 4ce74e55..8d215962 100644 --- a/android/app/src/main/kotlin/com/hiddify/hiddify/bg/ServiceConnection.kt +++ b/android/app/src/main/kotlin/com/hiddify/hiddify/bg/ServiceConnection.kt @@ -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) diff --git a/android/app/src/main/kotlin/com/hiddify/hiddify/constant/ServiceMode.kt b/android/app/src/main/kotlin/com/hiddify/hiddify/constant/ServiceMode.kt new file mode 100644 index 00000000..3a0fc487 --- /dev/null +++ b/android/app/src/main/kotlin/com/hiddify/hiddify/constant/ServiceMode.kt @@ -0,0 +1,6 @@ +package com.hiddify.hiddify.constant + +object ServiceMode { + const val NORMAL = "normal" + const val VPN = "vpn" +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/hiddify/hiddify/constant/SettingsKey.kt b/android/app/src/main/kotlin/com/hiddify/hiddify/constant/SettingsKey.kt index 8eb1491b..405d15cc 100644 --- a/android/app/src/main/kotlin/com/hiddify/hiddify/constant/SettingsKey.kt +++ b/android/app/src/main/kotlin/com/hiddify/hiddify/constant/SettingsKey.kt @@ -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"