diff --git a/V2rayNG/app/src/main/AndroidManifest.xml b/V2rayNG/app/src/main/AndroidManifest.xml
index 000f3d95..ae32e2cb 100644
--- a/V2rayNG/app/src/main/AndroidManifest.xml
+++ b/V2rayNG/app/src/main/AndroidManifest.xml
@@ -211,6 +211,16 @@
+
+
+
+
+
+
+
? = null
set(value) {
@@ -49,6 +50,7 @@ object V2RayServiceManager {
context.toast(R.string.app_tile_first_use)
return false
}
+ isIntentionalStop = false
startContextService(context)
return true
}
@@ -74,6 +76,7 @@ object V2RayServiceManager {
MmkvManager.setSelectServer(guid)
}
+ isIntentionalStop = false
startContextService(context)
} finally {
synchronized(operationLock) {
@@ -87,8 +90,16 @@ object V2RayServiceManager {
* @param context The context from which the service is stopped.
*/
fun stopVService(context: Context) {
- Log.i(AppConfig.TAG, "StartCore-Manager: stopVService called, serviceControl=${serviceControl?.get()}")
- MessageUtil.sendMsg2Service(context, AppConfig.MSG_STATE_STOP, "")
+ Log.i(AppConfig.TAG, "StartCore-Manager: stopVService called")
+ isIntentionalStop = true
+ val svc = serviceControl?.get()
+ if (svc != null) {
+ svc.stopService()
+ return
+ }
+ val intent = Intent(AppConfig.BROADCAST_ACTION_SERVICE_STOP)
+ intent.setPackage(AppConfig.ANG_PACKAGE)
+ context.sendBroadcast(intent)
}
/**
@@ -356,6 +367,10 @@ object V2RayServiceManager {
Log.w(AppConfig.TAG, "StartCore-Manager: Core shutdown callback, attempting restart")
val service = serviceControl.getService()
MessageUtil.sendMsg2UI(service, AppConfig.MSG_STATE_NOT_RUNNING, "")
+ if (isIntentionalStop) {
+ Log.i(AppConfig.TAG, "StartCore-Manager: Intentional stop, skipping restart")
+ return 0
+ }
CoroutineScope(Dispatchers.IO).launch {
kotlinx.coroutines.delay(1000L)
val ctx = service.applicationContext
diff --git a/V2rayNG/app/src/main/java/xyz/zarazaex/olc/receiver/ServiceControlReceiver.kt b/V2rayNG/app/src/main/java/xyz/zarazaex/olc/receiver/ServiceControlReceiver.kt
new file mode 100644
index 00000000..cfa5588e
--- /dev/null
+++ b/V2rayNG/app/src/main/java/xyz/zarazaex/olc/receiver/ServiceControlReceiver.kt
@@ -0,0 +1,19 @@
+package xyz.zarazaex.olc.receiver
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import xyz.zarazaex.olc.AppConfig
+import xyz.zarazaex.olc.handler.V2RayServiceManager
+
+class ServiceControlReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ when (intent.action) {
+ AppConfig.BROADCAST_ACTION_SERVICE_STOP -> {
+ V2RayServiceManager.isIntentionalStop = true
+ V2RayServiceManager.stopVService(context)
+ }
+ AppConfig.BROADCAST_ACTION_SERVICE_START -> V2RayServiceManager.startVServiceFromToggle(context)
+ }
+ }
+}
diff --git a/V2rayNG/app/src/main/java/xyz/zarazaex/olc/service/V2RayProxyOnlyService.kt b/V2rayNG/app/src/main/java/xyz/zarazaex/olc/service/V2RayProxyOnlyService.kt
index 6dd718c8..3dee1d9d 100644
--- a/V2rayNG/app/src/main/java/xyz/zarazaex/olc/service/V2RayProxyOnlyService.kt
+++ b/V2rayNG/app/src/main/java/xyz/zarazaex/olc/service/V2RayProxyOnlyService.kt
@@ -32,7 +32,7 @@ class V2RayProxyOnlyService : Service(), ServiceControl {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i(AppConfig.TAG, "StartCore-Proxy: Service command received")
V2RayServiceManager.startCoreLoop(null)
- return START_STICKY
+ return START_NOT_STICKY
}
/**
diff --git a/V2rayNG/app/src/main/java/xyz/zarazaex/olc/service/V2RayVpnService.kt b/V2rayNG/app/src/main/java/xyz/zarazaex/olc/service/V2RayVpnService.kt
index 8906e755..ec05edad 100644
--- a/V2rayNG/app/src/main/java/xyz/zarazaex/olc/service/V2RayVpnService.kt
+++ b/V2rayNG/app/src/main/java/xyz/zarazaex/olc/service/V2RayVpnService.kt
@@ -99,18 +99,16 @@ class V2RayVpnService : VpnService(), ServiceControl {
override fun onDestroy() {
super.onDestroy()
Log.i(AppConfig.TAG, "StartCore-VPN: Service destroyed")
+ stopAllService(false)
wakeLock?.let { if (it.isHeld) it.release() }
wakeLock = null
- NotificationManager.cancelNotification()
- MessageUtil.sendMsg2UI(this, AppConfig.MSG_STATE_STOP_SUCCESS, "")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i(AppConfig.TAG, "StartCore-VPN: Service command received")
setupVpnService()
startService()
- return START_STICKY
- //return super.onStartCommand(intent, flags, startId)
+ return START_NOT_STICKY
}
override fun getService(): Service {
diff --git a/V2rayNG/app/src/main/java/xyz/zarazaex/olc/ui/MainActivity.kt b/V2rayNG/app/src/main/java/xyz/zarazaex/olc/ui/MainActivity.kt
index d2a0d0dc..56a097be 100644
--- a/V2rayNG/app/src/main/java/xyz/zarazaex/olc/ui/MainActivity.kt
+++ b/V2rayNG/app/src/main/java/xyz/zarazaex/olc/ui/MainActivity.kt
@@ -208,19 +208,13 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
}
isFabOperationInProgress = true
- val actuallyRunning = V2RayServiceManager.isRunning()
- if (mainViewModel.isRunning.value != actuallyRunning) {
- Log.w(AppConfig.TAG, "FAB: UI state mismatch, syncing: vm=${mainViewModel.isRunning.value}, actual=$actuallyRunning")
- mainViewModel.isRunning.value = actuallyRunning
- isFabOperationInProgress = false
- return
- }
+ val isRunning = mainViewModel.isRunning.value == true
applyRunningState(isLoading = true, isRunning = false)
lifecycleScope.launch {
try {
- if (actuallyRunning) {
+ if (isRunning) {
Log.d(AppConfig.TAG, "FAB: stopping service")
V2RayServiceManager.stopVService(this@MainActivity)
} else {
@@ -229,7 +223,7 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
}
} catch (e: Exception) {
Log.e(AppConfig.TAG, "FAB: error", e)
- applyRunningState(isLoading = false, isRunning = V2RayServiceManager.isRunning())
+ applyRunningState(isLoading = false, isRunning = mainViewModel.isRunning.value == true)
} finally {
isFabOperationInProgress = false
}
@@ -378,11 +372,6 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
override fun onResume() {
super.onResume()
- val actuallyRunning = V2RayServiceManager.isRunning()
- if (mainViewModel.isRunning.value != actuallyRunning) {
- Log.w(AppConfig.TAG, "onResume: syncing state vm=${mainViewModel.isRunning.value}, actual=$actuallyRunning")
- mainViewModel.isRunning.value = actuallyRunning
- }
MessageUtil.sendMsg2Service(this, AppConfig.MSG_REGISTER_CLIENT, "")
}