我有一个VpnService的自定义实现,需要在断开连接时执行一些额外的清理.当我使用服务绑定从我的应用程序停止VpnService时,一切正常,但是当客户端使用系统对话框断开与Vpn的连接时,我需要执行该清理.
那么,我怎样才能找到断开连接并添加一些处理呢?
在Android上获取VPN连接状态 - 这可能是解决方案,但它不适用于Android 4+.
从日志的角度来看,只有两个条目:
03-20 03:27:09.478: INFO/Vpn(504): Switched from org.my.package to [Legacy VPN]
03-20 03:27:09.478: DEBUG/Vpn(504): setting state=IDLE, reason=prepare
小智 10
我刚遇到同样的问题.不调用VpnService.onRevoke().
事实证明这是因为我使用通过AIDL定义的自定义IBinder,我从onBind()返回.VpnService也实现onBind()并返回VpnService.Callback的实例.这是以这种方式实现的:
private class Callback extends Binder {
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
if (code == IBinder.LAST_CALL_TRANSACTION) {
onRevoke();
return true;
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
VpnService.Callback不使用AIDL,只检查函数代码IBinder.LAST_CALL_TRANSACTION是否已发送.如果是这样,它执行onRevoke().
我将此代码片段集成到我的自定义IBinder实现中,现在我收到了onRevoke()消息.请参阅以下示例:
private final IBinder mBinder = new ServiceBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public final class ServiceBinder extends ICustomVpnService.Stub
{
... implement methods defined in ICustomVpnService.Stub ....
/**
* Intercept remote method calls and check for "onRevoke" code which
* is represented by IBinder.LAST_CALL_TRANSACTION. If onRevoke message
* was received, call onRevoke() otherwise delegate to super implementation.
*/
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException
{
// see Implementation of android.net.VpnService.Callback.onTransact()
if ( code == IBinder.LAST_CALL_TRANSACTION )
{
onRevoke();
return true;
}
return super.onTransact( code, data, reply, flags );
}
private void onRevoke()
{
// shutdown VpnService, e.g. call VpnService.stopSelf()
}
}
Run Code Online (Sandbox Code Playgroud)
我是怎么想出来的?我在android源代码中搜索了实际调用onRevoke()的位置.为此,我发现grepcode(android)非常有帮助.我经常阅读android源代码来了解它是如何工作的.
小智 6
如果我们使用通过 AIDL 定义的自定义IBinder
(我从 onBind() 返回),就会发生这种情况。
VpnService
也实现并返回私有类onBind()
的实例。VpnService.Callback
@Override
public IBinder onBind(Intent intent) {
String action = intent != null ? intent.getAction() : null;
if (action != null && action.equals(VpnService.SERVICE_INTERFACE)) {
return super.onBind(intent);
}
return yourBinder;
}
Run Code Online (Sandbox Code Playgroud)
请注意,只要您从未
VpnService.SERVICE_INTERFACE
手动设置为操作,上述方法就有效。该操作只能由 Android 的内部逻辑设置(自动设置,而不是由我们的代码手动设置)。
归档时间: |
|
查看次数: |
1998 次 |
最近记录: |