我正在尝试为Android编写一个VPN应用程序,无论我做什么,似乎我的应用程序的“始终在线”设置都是灰色的。
我在android docs的任何地方都找不到任何文档,指出为什么不允许VpnService使用“ Always On”功能。
请确保我清楚,如果我手动启用它,我的VpnService也可以正常工作。我能够连接,使用它,而不会出现任何问题。我只是感到困惑,为什么在Android设置中,我的Vpn服务的“始终在线”开关下显示为“不支持此设备”。
注意:我使用的是自定义协议,在某个论坛上的某个地方,我确实看到过“ Google不允许不使用Google列入白名单的协议的VPN永远在线”,但是在哪里我是否找到了支持该说法的文档,所以我怀疑是否是这个原因。
通过阅读Android Documentation我发现了什么:
如果您在Android Manafest中的<service>
定义中为false
定义显式提供SERVICE_META_DATA_SUPPORTS_ALWAYS_ON标志,它将告诉系统您的应用程序不支持始终在线功能。但是,如果将其省略,则默认为true
。因此,没有必要提供它。
根据AppManagementFragment.java#updateRestrictedViews中的Android Souce,它使用函数mConnectivityManager.isAlwaysOnVpnPackageSupportedForUser(mUserId, mPackageName)
,但是我很难遵循该函数的逻辑。当查看ConnectivityManager.java#isAlwaysOnVpnPackageSupportedForUser时,它似乎以ConnectivityService.java#isAlwaysOnVpnPackageSupported结尾,并且最终指向Vpn.java#isAlwaysOnPackageSupported,这可能导致您的VPN被认为不支持始终开启满足以下一个:
PackageManager. getApplicationInfoAsUser()
找到包裹。VERSION_CODES.N
AndroidManifest.xml
中不包含任何Vpn服务。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();
答案 0 :(得分:0)
我找到了问题。
在我的AndroidManifest.xml
中,当我声明服务的意图过滤器时,我有一个错字。
<action android:name="android.net.VpnSerivce" />
代替
<action android:name="android.net.VpnService" />
这使我的应用程序无法通知操作系统我的应用程序具有android文档here中记录的VpnService。
这种错字花了我三天的时间,我再也回不来了。