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

核心变化概览
Android 6.0 的网络相关改动主要围绕以下三个核心主题:
- 运行时权限:这是最重大的变化,用户现在可以在安装后,按权限组(如“存储”、“通讯录”、“网络”)授予或撤销应用的权限。
- Doze 模式:一种全新的、深度的设备省电模式,会显著限制应用的后台网络活动。
- App Standby 机制:当用户长时间未与应用交互时,系统会将该应用置于“备用”状态,限制其网络活动。
运行时网络权限
这是开发者必须重点关注的改动,在 Android 6.0 之前,应用在安装时会一次性授予所有声明的权限,从 6.0 开始,敏感权限需要在运行时动态请求。
涉及的网络权限
在网络相关的权限中,以下两个属于“正常”权限组,默认授予,无需请求:
INTERNET:允许应用打开网络套接字,这是进行网络通信最基础的权限。
而以下权限属于“危险”权限组,必须在运行时请求:

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 模式。

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标记为“忽略备用状态”。 - 使用白名单:系统允许用户将应用添加到“不受限制”的白名单中(通常在电池设置中)。
其他网络相关改进
-
HTTP/Client (OkHttp) 支持:Android 6.0 的
HttpURLConnection实现现在更高效,并且对 HTTP/2 协议有更好的支持,虽然这不是系统级的默认实现,但它为基于 OkHttp 等库的现代网络请求提供了良好的基础。 -
VPN 应用增强:系统对 VPN 应用的支持得到加强,允许 VPN 应用更精细地控制网络流量。
给开发者的建议与总结
针对 Android 6.0,网络开发应遵循以下原则:
- 立即适配运行时权限:这是强制性的,对于
ACCESS_WIFI_STATE等危险权限,必须实现运行时请求逻辑,并提供优雅的降级处理。 - 拥抱
JobScheduler:彻底抛弃不稳定的AlarmManager定时任务,将所有后台网络同步、数据处理等任务都交给JobScheduler来管理,让系统帮你优化电量消耗。 - 重新设计后台网络策略:如果你的应用依赖后台网络,必须重新评估其在 Doze 模式和 App Standby 下的行为,考虑使用 FCM 进行服务器推送,而不是让客户端轮询。
- 进行电量测试:使用 Android Studio 的 Battery Historian 工具来分析你的应用在设备空闲时的电量消耗情况,确保它没有在后台进行不必要的网络活动。
- 用户教育:当权限被拒绝时,不要只是简单地提示“权限被拒绝”,向用户清晰地解释“为什么你需要这个权限”以及“开启后能为你带来什么好处”,这能显著提高用户的授权意愿。
Android 6.0 标志着一个重要的转折点:从“开发者优先”转向“用户和电池续航优先”,开发者必须适应这种变化,采用更现代、更省电的网络架构,才能为用户提供流畅且不耗电的体验。
