VpnService永远在线“不受此应用程序支持”

时间:2019-08-16 22:44:33

标签: android android-vpn-service

我正在尝试为Android编写一个VPN应用程序,无论我做什么,似乎我的应用程序的“始终在线”设置都是灰色的。

我在android docs的任何地方都找不到任何文档,指出为什么不允许VpnService使用“ Always On”功能。

请确保我清楚,如果我手动启用它,我的VpnService也可以正常工作。我能够连接,使用它,而不会出现任何问题。我只是感到困惑,为什么在Android设置中,我的Vpn服务的“始终在线”开关下显示为“不支持此设备”。

  

注意:我使用的是自定义协议,在某个论坛上的某个地方,我确实看到过“ Google不允许不使用Google列入白名单的协议的VPN永远在线”,但是在哪里我是否找到了支持该说法的文档,所以我怀疑是否是这个原因。

通过阅读Android Documentation我发现了什么:

  1. 如果您在Android Manafest中的<service>定义中为false定义显式提供SERVICE_META_DATA_SUPPORTS_ALWAYS_ON标志,它将告诉系统您的应用程序不支持始终在线功能。但是,如果将其省略,则默认为true。因此,没有必要提供它。

  2. 根据AppManagementFragment.java#updateRestrictedViews中的Android Souce,它使用函数mConnectivityManager.isAlwaysOnVpnPackageSupportedForUser(mUserId, mPackageName),但是我很难遵循该函数的逻辑。当查看ConnectivityManager.java#isAlwaysOnVpnPackageSupportedForUser时,它似乎以ConnectivityService.java#isAlwaysOnVpnPackageSupported结尾,并且最终指向Vpn.java#isAlwaysOnPackageSupported,这可能导致您的VPN被认为不支持始终开启满足以下一个

    1. 传递给该函数的程序包名称为空。
    2. 系统无法使用PackageManager. getApplicationInfoAsUser()找到包裹。
    3. 该应用程序的目标小于VERSION_CODES.N
    4. 该程序包的AndroidManifest.xml中不包含任何Vpn服务。
    5. 该软件包定义了SERVICE_META_DATA_SUPPORTS_ALWAYS_ON元数据设置为false的ANY VpnServices。
  

注意:我的应用程序以API 29为目标。

就是这样。

由于我的应用程序满足Vpn.java#isAlwaysOnPackageSupported中所述的所有要求,所以我对为什么它不起作用感到非常困惑。

  

我创建了一个android studio项目,演示了在我的Samsung Galaxy S10上发生的这种情况。您可以find it here on github

我的参考代码:

我的服务已按照Android文档中的说明进行配置。

<service
    android:name=".provider.VpnProvider"
    android:enabled="true"
    android:permission="android.permission.BIND_VPN_SERVICE"
    android:description="@string/service_description"
    android:exported="false">
    <intent-filter>
        <action android:name="android.net.VpnSerivce" />
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</service>

在“信息中心”活动中,我用它来处理被点击的Connect按钮。

public static final int REQ_START_VPN = 40;

public boolean connect() {
    Intent intent;

    try {
        intent = VpnProvider.prepare(this.getApplicationContext());
    } catch (IllegalStateException e) {
        return false;
    }

    if (intent != null) {
        try {
            this.startActivityForResult(intent, REQ_START_VPN);
            return true;
        } catch (ActivityNotFoundException e) {
            new BasicDialog(
                this, R.string.not_supported,
                R.string.not_supported_message
            ).show();
        }
    } else {
        this.onActivityResult(REQ_START_VPN, AppCompatActivity.RESULT_OK, null);
        return true;
    }
}

然后我使用以下方法处理结果:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == AppCompatActivity.RESULT_OK) {
        if (requestCode == REQ_START_VPN) {
            try {
                this.startService(new Intent(this, VpnProvider.class));
            } catch (IllegalStateException ignored) {}
        }
    }
}

我的VpnProvider类扩展了VpnService,并具有用于构建接口的以下内容:

VpnService.Builder builder = this.new Builder();
builder.setMtu(mtu);
builder.addAddress("1.2.3.4", 32);
builder.addDnsServer("8.8.8.8");
builder.addDnsServer("8.8.4.4");
builder.addRoute("0.0.0.0", 0);
vpnInterface = builder.establish();

1 个答案:

答案 0 :(得分:0)

我找到了问题。

在我的AndroidManifest.xml中,当我声明服务的意图过滤器时,我有一个错字。

<action android:name="android.net.VpnSerivce" />

代替

<action android:name="android.net.VpnService" />

这使我的应用程序无法通知操作系统我的应用程序具有android文档here中记录的VpnService。

这种错字花了我三天的时间,我再也回不来了。