Android VpnService.Builder.establish() 偶尔返回 null。

6
当我尝试为我的VpnService创建隧道接口时,我遇到了以下错误:
Attempt to invoke virtual method 'java.lang.String android.os.ParcelFileDescriptor.toString()' on a null object reference

目前我唯一的解决方法是在发生这种情况时重新启动设备。如果不这样做,我将无法创建隧道。

我的创建隧道代码:

// This is inside my VpnService implementation 

private ParcelFileDescriptor configureTunnelWithPushOpts(PushOpts popts)
{
    VpnService.Builder builder = this.new Builder();

    builder.setMtu       ( currentServerPrefs.SERVER_MTU );
    builder.addAddress   ( popts.ip, 32                  );
    builder.addDnsServer ( popts.dns1                    );
    builder.addDnsServer ( popts.dns2                    );
    builder.addRoute     ( "0.0.0.0", 0                  );


    // Note: Blocking mode is now enabled in native
    // code under the setFileDescriptor function.
    // builder.setBlocking(true);

    builder.setConfigureIntent(
            PendingIntent.getActivity(
                    this,
                    0,
                    new Intent(
                            this,
                            MainActivity.class
                    ),
            PendingIntent.FLAG_UPDATE_CURRENT)
    );

    final ParcelFileDescriptor vpnInterface;

    synchronized (this) {
        builder.setSession(currentServerPrefs.SERVER_ADDRESS);
        vpnInterface = builder.establish();
    }

    Logger.info("New interface: " + vpnInterface.toString(), this);
    return vpnInterface;
}

编辑:

根据文档,如果VpnService未准备好,establish函数将返回null,但我在上面的函数运行之前使用它来进行准备。

// This is inside my MainActivity class

Intent intent = VpnService.prepare(getApplicationContext());
if (intent != null) {
    startActivityForResult(intent, 0);
} else {
    onActivityResult(0, RESULT_OK, null);
}

. . . 

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        Intent intent = new Intent(this, MyVpnService.class);
        startService(intent);
    }
}

用于调试的手机

Google Nexus 5,运行 Android 5.0.1

编辑

我已经找到了如何复制这个问题,使其不再是零星发生的。基本上,如果我在 VPN 连接时卸载应用程序,然后重新安装并尝试启动它,当我运行 builder.establish() 时会收到一个空响应。我担心当该应用程序通过 Google Play 商店更新时,这可能会引起潜在问题。

除此之外,请不要将此问题标记为重复。在这个问题上的每一个其他问题都被给出了答案,即在建立构建器之前需要准备服务,然而在我的情况下我正在进行准备,并且有不同的原因导致我的问题。任何帮助都将不胜感激。


你看过OnRevoke方法了吗?可能有其他东西正在使用VPN。 - Hugo sama
1
我知道这是一个老问题,但你找到解决方案了吗?我也遇到了同样的问题(在5.0.1 Android,三星Galaxy S5上)。提前致谢。 - CyberMJ
@CyberMJ 还没有找到解决办法 :/. - Nathan F.
1个回答

3
非常感谢您提供的提示,它帮助我找到了解决方法!我在Android 5.0.2中也遇到了同样的问题:一切都很正常,然后我安装了我正在开发的vpn应用程序。然而,第二天,突然出现了一个无法解决的NullPointerException异常,尽管prepare已经被正确调用。
在我的环境中,以下步骤可以解决这个问题:
卸载该应用程序。无论该应用程序是否仍具有工作VPN功能都没有关系。
重新启动您的手机。确保完全关闭。
重新启动后,请确保该应用程序不再安装(在重新启动手机后,我遇到了一些奇怪的开发问题,其中应用程序重新安装)。
再次安装您的VPN应用程序。现在应该会收到一个VPN接口,而不是null。

这个问题在于最终用户可能会做同样的事情,卸载应用然后重新安装,从而遇到相同的空指针异常。我不想让最终用户为了使用应用程序而被告知重新启动手机。 - Nathan F.
也许可以通过事件监听器捕获卸载操作,然后优雅地停用/关闭 VPN?这个问题只在开发环境中出现(也可能与 adb 相关),还是您已经在生产应用中进行了测试? - Martin Bories
@MartinBories 这个答案对我非常有帮助 :) 并且在我的情况下确实有效。 - Jarvis__-_-__

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接