我刚刚遇到了同样的问题。不调用 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;
}
}
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()
}
}
我是怎么想出来的?我在 android 源代码中搜索了实际调用 onRevoke() 的位置。为此,我发现grepcode (android)非常有用。我经常阅读 android 源代码以了解事情是如何工作的。