android: tile/control activity - no bind leaks, no callbacks after destroy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f2e4ffe860
commit
01c398f2f7
2 files changed
+24
-7
No files matched your search
+16
-4
@@ -79,6 +79,7 @@ public class VpnProfileControlActivity extends AppCompatActivity implements VpnD
|
|||||||
private Bundle mProfileInfo;
|
private Bundle mProfileInfo;
|
||||||
private boolean mWaitingForResult;
|
private boolean mWaitingForResult;
|
||||||
private VpnStateService mService;
|
private VpnStateService mService;
|
||||||
|
private boolean mBound;
|
||||||
/* profile lookups are SQLite queries and must not block the main thread */
|
/* profile lookups are SQLite queries and must not block the main thread */
|
||||||
private final ExecutorService mProfileExecutor = Executors.newSingleThreadExecutor();
|
private final ExecutorService mProfileExecutor = Executors.newSingleThreadExecutor();
|
||||||
private final ServiceConnection mServiceConnection = new ServiceConnection()
|
private final ServiceConnection mServiceConnection = new ServiceConnection()
|
||||||
@@ -140,8 +141,8 @@ public class VpnProfileControlActivity extends AppCompatActivity implements VpnD
|
|||||||
{
|
{
|
||||||
mWaitingForResult = savedInstanceState.getBoolean(WAITING_FOR_RESULT, false);
|
mWaitingForResult = savedInstanceState.getBoolean(WAITING_FOR_RESULT, false);
|
||||||
}
|
}
|
||||||
this.bindService(new Intent(this, VpnStateService.class),
|
mBound = this.bindService(new Intent(this, VpnStateService.class),
|
||||||
mServiceConnection, Service.BIND_AUTO_CREATE);
|
mServiceConnection, Service.BIND_AUTO_CREATE);
|
||||||
VpnDialogBus.INSTANCE.setListener(this);
|
VpnDialogBus.INSTANCE.setListener(this);
|
||||||
VpnDialogsKt.installVpnDialogHost(this);
|
VpnDialogsKt.installVpnDialogHost(this);
|
||||||
}
|
}
|
||||||
@@ -159,10 +160,12 @@ public class VpnProfileControlActivity extends AppCompatActivity implements VpnD
|
|||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
VpnDialogBus.INSTANCE.setListener(null);
|
VpnDialogBus.INSTANCE.setListener(null);
|
||||||
mProfileExecutor.shutdown();
|
mProfileExecutor.shutdown();
|
||||||
if (mService != null)
|
if (mBound)
|
||||||
{
|
{
|
||||||
this.unbindService(mServiceConnection);
|
this.unbindService(mServiceConnection);
|
||||||
|
mBound = false;
|
||||||
}
|
}
|
||||||
|
mService = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -429,6 +432,10 @@ public class VpnProfileControlActivity extends AppCompatActivity implements VpnD
|
|||||||
mProfileExecutor.execute(() -> {
|
mProfileExecutor.execute(() -> {
|
||||||
VpnProfile profile = loadProfile(uuid);
|
VpnProfile profile = loadProfile(uuid);
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
|
if (isFinishing() || isDestroyed())
|
||||||
|
{ /* rotated or finished while the query ran */
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (profile != null)
|
if (profile != null)
|
||||||
{
|
{
|
||||||
startVpnProfile(profile);
|
startVpnProfile(profile);
|
||||||
@@ -479,7 +486,12 @@ public class VpnProfileControlActivity extends AppCompatActivity implements VpnD
|
|||||||
final Intent startIntent = intent;
|
final Intent startIntent = intent;
|
||||||
mProfileExecutor.execute(() -> {
|
mProfileExecutor.execute(() -> {
|
||||||
VpnProfile profile = loadProfile(uuid);
|
VpnProfile profile = loadProfile(uuid);
|
||||||
runOnUiThread(() -> handleDisconnect(startIntent, profile));
|
runOnUiThread(() -> {
|
||||||
|
if (!isFinishing() && !isDestroyed())
|
||||||
|
{
|
||||||
|
handleDisconnect(startIntent, profile);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-3
@@ -45,6 +45,7 @@ public class VpnTileService extends TileService implements VpnStateService.VpnSt
|
|||||||
private boolean mListening;
|
private boolean mListening;
|
||||||
private VpnProfileDataSource mDataSource;
|
private VpnProfileDataSource mDataSource;
|
||||||
private VpnStateService mService;
|
private VpnStateService mService;
|
||||||
|
private boolean mBound;
|
||||||
private final ServiceConnection mServiceConnection = new ServiceConnection()
|
private final ServiceConnection mServiceConnection = new ServiceConnection()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
@@ -71,8 +72,8 @@ public class VpnTileService extends TileService implements VpnStateService.VpnSt
|
|||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
Context context = getApplicationContext();
|
Context context = getApplicationContext();
|
||||||
context.bindService(new Intent(context, VpnStateService.class),
|
mBound = context.bindService(new Intent(context, VpnStateService.class),
|
||||||
mServiceConnection, Service.BIND_AUTO_CREATE);
|
mServiceConnection, Service.BIND_AUTO_CREATE);
|
||||||
|
|
||||||
mDataSource = new VpnProfileSource(this);
|
mDataSource = new VpnProfileSource(this);
|
||||||
mDataSource.open();
|
mDataSource.open();
|
||||||
@@ -83,10 +84,14 @@ public class VpnTileService extends TileService implements VpnStateService.VpnSt
|
|||||||
{
|
{
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
|
||||||
if (mService != null)
|
/* the binding lives on the application context: unbind even if the
|
||||||
|
* service never connected, or it leaks for the life of the process */
|
||||||
|
if (mBound)
|
||||||
{
|
{
|
||||||
getApplicationContext().unbindService(mServiceConnection);
|
getApplicationContext().unbindService(mServiceConnection);
|
||||||
|
mBound = false;
|
||||||
}
|
}
|
||||||
|
mService = null;
|
||||||
mDataSource.close();
|
mDataSource.close();
|
||||||
mDataSource = null;
|
mDataSource = null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user