简体   繁体   English

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

[英]VpnService always-on “not supported by this app”

I'm trying to write a VPN application for android, and no matter what I do it seems that the "Always On" setting for my application is grayed out. 我正在尝试为Android编写一个VPN应用程序,无论我做什么,似乎我的应用程序的“始终打开”设置都是灰色的。

I cannot find any documentation anywhere in the android docs that states WHY a VpnService might not be allowed to use the "Always On" feature. 我在android docs的任何地方都找不到任何文档,指出为什么不允许VpnService使用“ Always On”功能。

Just to make sure I'm clear, my VpnService works just fine if i manually enable it. 为了确保我很清楚,如果我手动启用它,我的VpnService也可以正常工作。 I'm able to connect, use it, etc without any issues. 我能够连接,使用它,而不会出现任何问题。 I'm just confused as to why in the Android settings it's showing as "not supported for this device" under the "Always-On" toggle for my Vpn Service. 我只是感到困惑,为什么在Android设置中,我的Vpn服务的“始终在线”开关下显示为“不支持此设备”。

Note: I am using a custom protocol, and on some forum somewhere I did see once that "Google doesn't allow Always-On for VPNs that don't use protocols that have been whitelisted by google", however no where have I found documentation to support this claim, so I'm doubtful that it is the cause. 注意:我使用的是自定义协议,在某个论坛上的某个地方,我确实看到过“ Google不允许不使用Google列入白名单的协议的VPN永远在线”,但是我没有找到文档来支持此主张,因此我怀疑这是原因。

What I have found from reading the Android Documentation : 通过阅读Android文档,我发现了什么:

  1. If you explicitly supply the SERVICE_META_DATA_SUPPORTS_ALWAYS_ON flag to the <service> definition in your Android Manafest with a value of false it will tell the system that your application does not support the Always On feature. 如果您为Android Manafest中的<service>定义显式提供SERVICE_META_DATA_SUPPORTS_ALWAYS_ON标志,且其值为false ,它将告知系统您的应用程序不支持Always On功能。 However, if you leave it out, it defaults to true . 但是,如果将其省略,则默认为true So there should be no need to supply this. 因此,无需提供此功能。

  2. According to the Android Souce in AppManagementFragment.java#updateRestrictedViews , it uses a function mConnectivityManager.isAlwaysOnVpnPackageSupportedForUser(mUserId, mPackageName) , however I'm having difficulty following the logic of this function. 根据AppManagementFragment.java#updateRestrictedViews中的Android Souce,它使用了一个函数mConnectivityManager.isAlwaysOnVpnPackageSupportedForUser(mUserId, mPackageName) ,但是我很难遵循此函数的逻辑。 When looking at ConnectivityManager.java#isAlwaysOnVpnPackageSupportedForUser , it seems to end up in ConnectivityService.java#isAlwaysOnVpnPackageSupported and ultimately points to Vpn.java#isAlwaysOnPackageSupported which can result in your VPN being considered to NOT support always on if one of the following is met: 当查看ConnectivityManager.java#isAlwaysOnVpnPackageSupportedForUser时 ,它似乎最终出现在ConnectivityService.java#isAlwaysOnVpnPackageSupported中,最终指向Vpn.java#isAlwaysOnPackageSupported ,如果满足以下条件之一 ,则可能会导致您的VPN被认为不支持始终开启:

    1. The package name passed to the function is null. 传递给该函数的程序包名称为null。
    2. The system is unable to locate the package using PackageManager. getApplicationInfoAsUser() 系统无法使用PackageManager. getApplicationInfoAsUser()查找软件包PackageManager. getApplicationInfoAsUser() PackageManager. getApplicationInfoAsUser() . PackageManager. getApplicationInfoAsUser()
    3. The target for the application is less than VERSION_CODES.N 该应用程序的目标小于VERSION_CODES.N
    4. The package does not contain any Vpn Services in its AndroidManifest.xml . 该软件包的AndroidManifest.xml中不包含任何Vpn服务。
    5. The package defines ANY VpnServices with the SERVICE_META_DATA_SUPPORTS_ALWAYS_ON meta data set to false . 包定义了将SERVICE_META_DATA_SUPPORTS_ALWAYS_ON元数据设置为false任何VpnServices。

Note: My application targets API 29. 注意:我的应用程序以API 29为目标。

And that's about it. 就是这样。

Since my application meets all of the requirements stated in Vpn.java#isAlwaysOnPackageSupported , i'm left very confused as to why it will not work. 由于我的应用程序满足Vpn.java#isAlwaysOnPackageSupported规定的所有要求,所以我对为什么它不起作用感到非常困惑。

I've created an android studio project that demonstrates this happening on my Samsung Galaxy S10. 我创建了一个android studio项目,演示了在三星Galaxy S10上发生的这种情况。 You can find it here on github . 您可以在github上找到它

My code for reference: 我的代码供参考:

My service is configured as is documented in the Android Documentation. 我的服务已按照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>

In my Dashboard activity, I use this to handle the Connect button being tapped. 在“仪表板”活动中,我使用它来处理被点击的“ 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;
    }
}

I then handle the result using the following: 然后,我使用以下方法处理结果:

@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) {}
        }
    }
}

My VpnProvider class extends VpnService and has the following for Building the interface: 我的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();

I've found the problem. 我发现了问题。

In my AndroidManifest.xml when I declared the intent-filters for my service I had a typo. 在我的AndroidManifest.xml当我声明服务的意图过滤器时,我有一个错字。

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

instead of 代替

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

This made my application not inform the operating system that my application had a VpnService as documented in the android documentation here . 这使我的申请没有告知操作系统,我的应用程序有一个VpnService为Android文档中记录在这里

This typo took three days of my life that I will never get back. 这种错字花了我生命中的三天时间,我再也回不来了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM