睿诚科技协会

Android 6.0网络权限如何适配?

Android 6.0 是一个非常重要的版本,因为它对网络权限进行了革命性的改动,引入了运行时权限,它还引入了更节省流量的 Doze 模式和 App Standby 机制,这些都深刻地影响到了应用的网络行为。

Android 6.0网络权限如何适配?-图1
(图片来源网络,侵删)

核心变化概览

Android 6.0 的网络相关改动主要围绕以下三个核心主题:

  1. 运行时权限:这是最重大的变化,用户现在可以在安装后,按权限组(如“存储”、“通讯录”、“网络”)授予或撤销应用的权限。
  2. Doze 模式:一种全新的、深度的设备省电模式,会显著限制应用的后台网络活动。
  3. App Standby 机制:当用户长时间未与应用交互时,系统会将该应用置于“备用”状态,限制其网络活动。

运行时网络权限

这是开发者必须重点关注的改动,在 Android 6.0 之前,应用在安装时会一次性授予所有声明的权限,从 6.0 开始,敏感权限需要在运行时动态请求。

涉及的网络权限

在网络相关的权限中,以下两个属于“正常”权限组,默认授予,无需请求:

  • INTERNET:允许应用打开网络套接字,这是进行网络通信最基础的权限。

而以下权限属于“危险”权限组,必须在运行时请求

Android 6.0网络权限如何适配?-图2
(图片来源网络,侵删)
  • ACCESS_NETWORK_STATE:允许应用访问有关网络状态的信息(如连接类型、是否活跃等)。
  • ACCESS_WIFI_STATE:允许应用访问 Wi-Fi 网络状态信息(如 Wi-Fi 名称、IP 地址等)。
  • CHANGE_NETWORK_STATE:允许应用改变网络连接状态(如开启/关闭移动数据)。
  • CHANGE_WIFI_STATE:允许应用改变 Wi-Fi 连接状态(如开启/关闭 Wi-Fi,连接到指定网络)。

如何请求权限(代码示例)

对于 ACCESS_WIFI_STATE 这样的危险权限,你不能只在 AndroidManifest.xml 中声明,还需要在代码中动态请求。

// 1. 检查是否已拥有权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE) 
        != PackageManager.PERMISSION_GRANTED) {
    // 2. 如果没有权限,则请求权限
    // 第二个参数是权限请求码,用于在回调中识别
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.ACCESS_WIFI_STATE},
            MY_PERMISSIONS_REQUEST_ACCESS_WIFI_STATE);
} else {
    // 已经有权限,直接执行你的操作
    getWifiInfo();
}
// 3. 处理权限请求的回调结果
@Override
public void onRequestPermissionsResult(int requestCode,
        String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == MY_PERMISSIONS_REQUEST_ACCESS_WIFI_STATE) {
        // 如果请求被取消,结果数组为空
        if (grantResults.length > 0 
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 用户授予了权限
            getWifiInfo();
        } else {
            // 用户拒绝了权限
            // 你可以在这里向用户解释为什么这个权限是必要的
            // 并引导用户到设置页面手动开启
            Toast.makeText(this, "需要Wi-Fi状态权限才能使用此功能", Toast.LENGTH_SHORT).show();
        }
    }
}
private void getWifiInfo() {
    // 获取Wi-Fi信息的代码
    WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    if (wifiManager != null) {
        WifiInfo info = wifiManager.getConnectionInfo();
        Log.d("WiFiInfo", "SSID: " + info.getSSID());
    }
}

最佳实践

  • 解释为什么需要权限:在请求权限前,最好向用户展示一个对话框(使用 shouldShowRequestPermissionRationale() 判断),解释你的应用为什么需要这个权限,提升用户授权的可能性。
  • 优雅地处理拒绝:如果用户拒绝了权限,不要频繁地再次请求,可以引导用户到应用的设置页面手动开启。

Doze 模式 和 App Standby

为了延长设备电池续航,Android 6.0 引入了这两个机制,它们对后台网络行为有严格的限制。

Doze 模式

当设备未插电、屏幕关闭并静止一段时间后(默认约 30 分钟),系统会进入 Doze 模式。

Android 6.0网络权限如何适配?-图3
(图片来源网络,侵删)

Doze 模式下的网络限制

  • 网络完全被挂起:应用无法在后台进行网络连接或收发数据。
  • 限制后台工作AlarmManager 的常规 set()setRepeating() 调用会被延迟。
  • 白名单机制:应用可以通过 AlarmManager.setAndAllowWhileIdle()setExactAndAllowWhileIdle() 来设置闹钟,但每天只能有限次数(约 9 次)在 Doze 模式下唤醒设备,系统也会将高优先级的 FCM (Firebase Cloud Messaging) 推送消息加入白名单。

对开发者的影响

  • 不要依赖后台任务:如果你的应用依赖定期的后台网络同步(如检查新邮件),Doze 模式会打断这个行为。
  • 使用 JobScheduler:对于后台工作,应优先使用 JobScheduler,系统会智能地聚合和调度这些任务,在设备充电、连接 Wi-Fi 或非 Doze 状态下执行,从而更高效地使用电量。

App Standby 机制

即使设备没有进入 Doze 模式,如果用户长时间(例如数天)没有直接启动或与应用交互,系统会将该应用置于“备用”状态。

App Standby 下的网络限制

  • 限制后台网络:处于备用状态的应用,其后台网络活动会受到限制,系统可能会延迟或阻止其后台网络请求。
  • 限制启动:当应用处于备用状态时,如果它尝试从后台启动(如通过 BroadcastReceiver),系统可能会延迟其启动,直到用户与设备交互。

如何避免进入备用状态

  • 保持用户活跃:最好的方式是让用户经常使用你的应用。
  • 设置高优先级:如果某个应用对用户至关重要(如即时通讯应用),可以通过 setComponentEnabledSetting() 将其 BroadcastReceiver 标记为“忽略备用状态”。
  • 使用白名单:系统允许用户将应用添加到“不受限制”的白名单中(通常在电池设置中)。

其他网络相关改进

  1. HTTP/Client (OkHttp) 支持:Android 6.0 的 HttpURLConnection 实现现在更高效,并且对 HTTP/2 协议有更好的支持,虽然这不是系统级的默认实现,但它为基于 OkHttp 等库的现代网络请求提供了良好的基础。

  2. VPN 应用增强:系统对 VPN 应用的支持得到加强,允许 VPN 应用更精细地控制网络流量。


给开发者的建议与总结

针对 Android 6.0,网络开发应遵循以下原则:

  1. 立即适配运行时权限:这是强制性的,对于 ACCESS_WIFI_STATE 等危险权限,必须实现运行时请求逻辑,并提供优雅的降级处理。
  2. 拥抱 JobScheduler:彻底抛弃不稳定的 AlarmManager 定时任务,将所有后台网络同步、数据处理等任务都交给 JobScheduler 来管理,让系统帮你优化电量消耗。
  3. 重新设计后台网络策略:如果你的应用依赖后台网络,必须重新评估其在 Doze 模式和 App Standby 下的行为,考虑使用 FCM 进行服务器推送,而不是让客户端轮询。
  4. 进行电量测试:使用 Android Studio 的 Battery Historian 工具来分析你的应用在设备空闲时的电量消耗情况,确保它没有在后台进行不必要的网络活动。
  5. 用户教育:当权限被拒绝时,不要只是简单地提示“权限被拒绝”,向用户清晰地解释“为什么你需要这个权限”以及“开启后能为你带来什么好处”,这能显著提高用户的授权意愿。

Android 6.0 标志着一个重要的转折点:从“开发者优先”转向“用户和电池续航优先”,开发者必须适应这种变化,采用更现代、更省电的网络架构,才能为用户提供流畅且不耗电的体验。

分享:
扫描分享到社交APP
上一篇
下一篇