Android 的数据保护程序关闭时获取 "BLOCKED" 网络状态

Getting "BLOCKED" network state when Android's data saver is off

我正在开发要在特定平板电脑上使用的应用程序 运行ning Android 7.0。我正在使用 Service 定期发送 DatagramPacket我只能使用移动网络。我使用 ConnectivityManagerNetworkInfoDetailedState 检查连接状态。我使用此代码获取网络状态:

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
DetailedState networkState = activeNetwork.getDetailedState();

我的平板电脑中的流量节省程序已关闭。为了以防万一,我有运行测试来验证在屏幕关闭时没有限制,cm.getRestrictBackgroundStatus()总是returns 1,即RESTRICT_BACKGROUND_STATUS_DISABLED,即使网络是已屏蔽。

那么,为什么网络被封锁了?我的应用程序需要特殊权限吗?我的平板电脑需要特殊配置吗?

这是正常行为。当您的屏幕被锁定时,它会使用打瞌睡模式。打瞌睡模式会关闭互联网通信和所有后台服务。您需要唤醒您的设备,然后才能通过互联网进行所有操作。 Documentations

为了给出完整的解决方案,我将回答我的问题。

why is the network blocked?

正如 Stanislav Kireev 提供的文档所指出的,这种 BLOCKED 网络状态的发生是因为设备处于打瞌睡状态。此设备状态不允许从 Android 6.0(API 级别 23)开始访问互联网。

但是文档还说“系统提供了一个可配置的应用程序白名单,这些应用程序可以部分免除 Doze 和 App Standby 优化”。有关更详细的说明,您可以阅读 Support for other use cases 部分。您可以通过代码或配置系统将您的应用程序添加到白名单。

Do my app need special permissions?

如果您需要通过代码将您的应用添加到白名单,您需要在清单文件中添加权限:

<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>

并将此代码添加到您的 activity:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    String packageName = getPackageName();
    PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
    if (!pm.isIgnoringBatteryOptimizations(packageName)) {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + packageName));
        startActivity(intent);
    }
}

我从 this answer 得到了这个解决方案。

Do my tablet need special configuration?

如果需要,您可以通过设置 > 电池 > 3 点 > 电池优化 添加您的应用。在选择列表中选择所有应用,select您的应用并选择不优化选项。

我从那里得到了这个解决方案(它有更详细的解释)。