@@ -91,18 +91,26 @@ object V2RayServiceManager {
9191 * @param context The context from which the service is started.
9292 */
9393 private fun startContextService (context : Context ) {
94- if (coreController.isRunning) {
94+ // Не делаем ранний выход при coreController.isRunning — startCoreLoop сам разберётся.
95+ // Ранний выход здесь был причиной бага: сервис стартовал, но startCoreLoop видел
96+ // isRunning==true и возвращал false, что вызывало мгновенную остановку VPN.
97+ Log .d(AppConfig .TAG , " startContextService: coreController.isRunning=${coreController.isRunning} " )
98+ val guid = MmkvManager .getSelectServer() ? : run {
99+ Log .w(AppConfig .TAG , " startContextService: no selected server, aborting" )
100+ return
101+ }
102+ val config = MmkvManager .decodeServerConfig(guid) ? : run {
103+ Log .w(AppConfig .TAG , " startContextService: failed to decode server config for guid=$guid " )
95104 return
96105 }
97- val guid = MmkvManager .getSelectServer() ? : return
98- val config = MmkvManager .decodeServerConfig(guid) ? : return
99106 if (config.configType != EConfigType .CUSTOM
100107 && config.configType != EConfigType .POLICYGROUP
101108 && ! Utils .isValidUrl(config.server)
102109 && ! Utils .isPureIpAddress(config.server.orEmpty())
103- ) return
104- // val result = V2rayConfigUtil.getV2rayConfig(context, guid)
105- // if (!result.status) return
110+ ) {
111+ Log .w(AppConfig .TAG , " startContextService: invalid server address '${config.server} ', aborting" )
112+ return
113+ }
106114
107115 GlobalScope .launch(Dispatchers .Main ) {
108116 if (MmkvManager .decodeSettingsBool(AppConfig .PREF_PROXY_SHARING )) {
@@ -116,6 +124,7 @@ object V2RayServiceManager {
116124 } else {
117125 Intent (context.applicationContext, V2RayProxyOnlyService ::class .java)
118126 }
127+ Log .i(AppConfig .TAG , " startContextService: launching foreground service for guid=$guid " )
119128 ContextCompat .startForegroundService(context, intent)
120129 }
121130
@@ -125,16 +134,41 @@ object V2RayServiceManager {
125134 * Starts the V2Ray core service.
126135 */
127136 fun startCoreLoop (vpnInterface : ParcelFileDescriptor ? ): Boolean {
137+ Log .i(AppConfig .TAG , " startCoreLoop: called, coreController.isRunning=${coreController.isRunning} " )
138+
139+ // Исправление бага: если ядро считает себя запущенным — принудительно останавливаем его
140+ // перед новым стартом. Раньше здесь был `return false`, что вызывало мгновенную остановку
141+ // VPN т.к. startService() → stopAllService() при false.
128142 if (coreController.isRunning) {
129- return false
143+ Log .w(AppConfig .TAG , " startCoreLoop: core is already running, stopping it first..." )
144+ try {
145+ coreController.stopLoop()
146+ Thread .sleep(300L )
147+ Log .i(AppConfig .TAG , " startCoreLoop: old core stopped successfully" )
148+ } catch (e: Exception ) {
149+ Log .e(AppConfig .TAG , " startCoreLoop: failed to stop existing core" , e)
150+ // Продолжаем попытку запуска даже если не смогли остановить
151+ }
130152 }
131153
132- val service = getService() ? : return false
133- val guid = MmkvManager .getSelectServer() ? : return false
134- val config = MmkvManager .decodeServerConfig(guid) ? : return false
154+ val service = getService() ? : run {
155+ Log .e(AppConfig .TAG , " startCoreLoop: service is null, aborting" )
156+ return false
157+ }
158+ val guid = MmkvManager .getSelectServer() ? : run {
159+ Log .e(AppConfig .TAG , " startCoreLoop: no selected server, aborting" )
160+ return false
161+ }
162+ val config = MmkvManager .decodeServerConfig(guid) ? : run {
163+ Log .e(AppConfig .TAG , " startCoreLoop: failed to decode config for guid=$guid " )
164+ return false
165+ }
166+ Log .d(AppConfig .TAG , " startCoreLoop: building config for '${config.remarks} ' (guid=$guid )" )
135167 val result = V2rayConfigManager .getV2rayConfig(service, guid)
136- if (! result.status)
168+ if (! result.status) {
169+ Log .e(AppConfig .TAG , " startCoreLoop: V2rayConfigManager returned invalid config for guid=$guid " )
137170 return false
171+ }
138172
139173 try {
140174 val mFilter = IntentFilter (AppConfig .BROADCAST_ACTION_SERVICE )
@@ -143,37 +177,39 @@ object V2RayServiceManager {
143177 mFilter.addAction(Intent .ACTION_USER_PRESENT )
144178 ContextCompat .registerReceiver(service, mMsgReceive, mFilter, Utils .receiverFlags())
145179 } catch (e: Exception ) {
146- Log .d(AppConfig .TAG , " Failed to register broadcast receiver" , e)
147- return false
180+ Log .d(AppConfig .TAG , " startCoreLoop: Failed to register broadcast receiver (may already be registered) " , e)
181+ // Не возвращаем false — ресивер мог уже быть зарегистрирован (при switch server)
148182 }
149183
150184 currentConfig = config
151185 var tunFd = vpnInterface?.fd ? : 0
186+ Log .d(AppConfig .TAG , " startCoreLoop: tunFd=$tunFd , isUsingHevTun=${SettingsManager .isUsingHevTun()} " )
152187 if (SettingsManager .isUsingHevTun()) {
153188 tunFd = 0
154189 }
155190
156191 try {
192+ Log .i(AppConfig .TAG , " startCoreLoop: calling coreController.startLoop()" )
157193 NotificationManager .showNotification(currentConfig)
158194 coreController.startLoop(result.content, tunFd)
159195 } catch (e: Exception ) {
160- Log .e(AppConfig .TAG , " Failed to start Core loop" , e)
196+ Log .e(AppConfig .TAG , " startCoreLoop: Failed to start Core loop" , e)
161197 return false
162198 }
163199
164200 if (coreController.isRunning == false ) {
201+ Log .e(AppConfig .TAG , " startCoreLoop: core did not start (isRunning=false after startLoop)" )
165202 MessageUtil .sendMsg2UI(service, AppConfig .MSG_STATE_START_FAILURE , " " )
166203 NotificationManager .cancelNotification()
167204 return false
168205 }
169206
207+ Log .i(AppConfig .TAG , " startCoreLoop: core started successfully for '${config.remarks} '" )
170208 try {
171209 MessageUtil .sendMsg2UI(service, AppConfig .MSG_STATE_START_SUCCESS , " " )
172- // NotificationManager.showNotification(currentConfig)
173210 NotificationManager .startSpeedNotification(currentConfig)
174-
175211 } catch (e: Exception ) {
176- Log .e(AppConfig .TAG , " Failed to startup service " , e)
212+ Log .e(AppConfig .TAG , " startCoreLoop: Failed to send startup notifications " , e)
177213 return false
178214 }
179215 return true
@@ -185,16 +221,24 @@ object V2RayServiceManager {
185221 * @return True if the core was stopped successfully, false otherwise.
186222 */
187223 fun stopCoreLoop (): Boolean {
188- val service = getService() ? : return false
224+ Log .i(AppConfig .TAG , " stopCoreLoop: called, coreController.isRunning=${coreController.isRunning} " )
225+ val service = getService() ? : run {
226+ Log .w(AppConfig .TAG , " stopCoreLoop: service is null" )
227+ return false
228+ }
189229
190230 if (coreController.isRunning) {
231+ Log .i(AppConfig .TAG , " stopCoreLoop: stopping V2Ray core loop..." )
191232 CoroutineScope (Dispatchers .IO ).launch {
192233 try {
193234 coreController.stopLoop()
235+ Log .i(AppConfig .TAG , " stopCoreLoop: core stopped successfully" )
194236 } catch (e: Exception ) {
195- Log .e(AppConfig .TAG , " Failed to stop V2Ray loop" , e)
237+ Log .e(AppConfig .TAG , " stopCoreLoop: Failed to stop V2Ray loop" , e)
196238 }
197239 }
240+ } else {
241+ Log .d(AppConfig .TAG , " stopCoreLoop: core was not running, skipping stopLoop" )
198242 }
199243
200244 MessageUtil .sendMsg2UI(service, AppConfig .MSG_STATE_STOP_SUCCESS , " " )
@@ -203,7 +247,7 @@ object V2RayServiceManager {
203247 try {
204248 service.unregisterReceiver(mMsgReceive)
205249 } catch (e: Exception ) {
206- Log .d(AppConfig .TAG , " Failed to unregister broadcast receiver" , e)
250+ Log .d(AppConfig .TAG , " stopCoreLoop: Failed to unregister broadcast receiver (may already be unregistered) " , e)
207251 }
208252
209253 return true
@@ -355,11 +399,16 @@ object V2RayServiceManager {
355399 }
356400
357401 AppConfig .MSG_STATE_SWITCH_SERVER -> {
358- Log .i(AppConfig .TAG , " Switching Server inside Service " )
402+ Log .i(AppConfig .TAG , " MSG_STATE_SWITCH_SERVER: switching server, coreRunning= ${coreController.isRunning} " )
359403 val vpnInterface = serviceControl.getVpnInterface()
404+ Log .d(AppConfig .TAG , " MSG_STATE_SWITCH_SERVER: vpnInterface=${vpnInterface?.fd} " )
405+ val guid = MmkvManager .getSelectServer()
406+ Log .i(AppConfig .TAG , " MSG_STATE_SWITCH_SERVER: target guid=$guid " )
360407 stopCoreLoop()
361408 Thread .sleep(1000L ) // Wait for core to fully release resources
362- startCoreLoop(vpnInterface)
409+ Log .i(AppConfig .TAG , " MSG_STATE_SWITCH_SERVER: starting core loop after switch" )
410+ val success = startCoreLoop(vpnInterface)
411+ Log .i(AppConfig .TAG , " MSG_STATE_SWITCH_SERVER: startCoreLoop result=$success " )
363412 }
364413
365414 AppConfig .MSG_MEASURE_DELAY -> {
0 commit comments