如何在Android中为Vpn断开连接添加额外的处理?

dzi*_*bry 2 vpn android

我有一个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 的内部逻辑设置(自动设置,而不是由我们的代码手动设置)。