[TOC]
# Android 10重要变更
## 1、对不可重置的设备标识符实施了限制
> 自 Android 10(API 级别 29)起,您的应用必须是[设备或个人资料所有者应用](https://source.android.com/devices/tech/admin/managed-profiles?hl=zh-cn#device_administration),具有[特殊运营商许可](https://source.android.com/devices/tech/config/uicc?hl=zh-cn),或具有`READ_PRIVILEGED_PHONE_STATE`特权,才能访问不可重置的设备标识符(包含 IMEI 和序列号)。
> 受影响的方法包括:
> * `Build`
* [`getSerial()`](https://developer.android.com/reference/android/os/Build#getSerial())
> * `TelephonyManager`
* [`getImei()`](https://developer.android.com/reference/android/telephony/TelephonyManager#getImei(int))
* [`getDeviceId()`](https://developer.android.com/reference/android/telephony/TelephonyManager#getDeviceId(int))
* [`getMeid()`](https://developer.android.com/reference/android/telephony/TelephonyManager#getMeid(int))
* [`getSimSerialNumber()`](https://developer.android.com/reference/android/telephony/TelephonyManager#getSimSerialNumber())
* [`getSubscriberId()`](https://developer.android.com/reference/android/telephony/TelephonyManager#getSubscriberId())
**即:** Android 10开始,普通应用无法再获取到设备的IMEI。
> 如果您的应用没有该权限,但您仍尝试查询不可重置标识符的相关信息,则平台的响应会因目标 SDK 版本而异:
> * 如果应用以 Android 10 或更高版本为目标平台,则会发生[`SecurityException`](https://developer.android.com/reference/java/lang/SecurityException)。
> * 如果应用以 Android 9(API 级别 28)或更低版本为目标平台,则相应方法会返回`null`或占位符数据(如果应用具有[`READ_PHONE_STATE`](https://developer.android.com/reference/android/Manifest.permission#READ_PHONE_STATE)权限)。否则,会发生`SecurityException`。
**即:** targetSdkVersion<=28时,获取IMEI为空;targetSdkVersion>=29时,会发生SecurityException异常
## 2、在后台运行时访问设备位置信息需要权限
> 为了让用户更好地控制应用对位置信息的访问权限,Android 10 引入了 ACCESS_BACKGROUND_LOCATION 权限。与 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 权限不同,ACCESS_BACKGROUND_LOCATION 权限仅会影响应用在后台运行时对位置信息的访问权限。
当targetSdkVersion<=28时,应用请求了`ACCESS_FINE_LOCATION`或`ACCESS_COARSE_LOCATION`权限时,系统会自动将`ACCESS_BACKGROUND_LOCATION`添加到请求中。
## 3、外部存储访问权限范围限定为应用文件和媒体(target 29+)
> 默认情况下,对于以 Android 10 及更高版本为目标平台的应用,其[访问权限范围限定为外部存储](https://developer.android.com/training/data-storage/files/external-scoped),即分区存储。此类应用可以查看外部存储设备内以下类型的文件,无需请求任何与存储相关的用户权限:
* 特定于应用的目录中的文件(使用[`getExternalFilesDir()`](https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String))访问)。
* 应用创建的照片、视频和音频片段(通过[媒体库](https://developer.android.com/training/data-storage/files/media)访问)。
**即:** 当targetSdkVersion>=29时,应用不需要请求权限,就可以访问本应用目录中的文件(getExternalFilesDir())和本应用创建的照片、视频、音频片段(通过媒体库访问)。
## 4、对启用和停用 WLAN 实施了限制(target 29+)
> 以 Android 10 或更高版本为目标平台的应用无法启用或停用 WLAN。[`WifiManager.setWifiEnabled()`](https://developer.android.com/reference/android/net/wifi/WifiManager#setWifiEnabled(boolean))方法始终返回`false`。
> 如果您需要提示用户启用或停用 WLAN,请使用[设置面板](https://developer.android.com/about/versions/10/features#settings-panels)。
# Android 9重要变更
## 1、强制执行 FLAG_ACTIVITY_NEW_TASK 要求
> 在 Android 9 中,您不能从非 Activity 环境中启动 Activity,除非您传递 Intent 标志[`FLAG_ACTIVITY_NEW_TASK`](https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_NEW_TASK)。 如果您尝试在不传递此标志的情况下启动 Activity,则该 Activity 不会启动,系统会在日志中输出一则消息。
## 2、构建序列号弃用(target 28+)
> 在 Android 9 中,[`Build.SERIAL`](https://developer.android.com/reference/android/os/Build#SERIAL)始终设为`"UNKNOWN"`,以保护用户隐私。
> 如果您的应用需要访问设备的硬件序列号,您应改为请求[`READ_PHONE_STATE`](https://developer.android.com/reference/android/Manifest.permission#READ_PHONE_STATE)权限,然后调用[`getSerial()`](https://developer.android.com/reference/android/os/Build#getSerial())。
## 3、默认启用网络传输层安全协议 (TLS)
> 如果您的应用以 Android 9 或更高版本为目标平台,则[`isCleartextTrafficPermitted()`](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#isCleartextTrafficPermitted())方法默认返回`false`。如果您的应用需要针对特定网域启用明文,则您必须在应用的[网络安全配置](https://developer.android.com/training/articles/security-config)中,针对这些网域明确将`cleartextTrafficPermitted`设置为`true`。
## 4、异形屏适配
参考:[https://blog.csdn.net/guolin\_blog/article/details/103112795](https://blog.csdn.net/guolin_blog/article/details/103112795)
# Android 8重要变更
## 1、Android ID
> 对于安装在运行 Android 8.0 的设备上的应用,ANDROID_ID的值现在将根据应用签署密钥和用户确定作用域。应用签署密钥、用户和设备的每个组合都具有唯一的ANDROID_ID值。因此,在相同设备上运行但具有不同签署密钥的应用将不会再看到相同的 Android ID(即使对于同一用户来说,也是如此)。
**即:** 在一台手机上,对于不同的应用来说,获取到的Android ID值是不一样的。
> 只要签署密钥相同,`ANDROID_ID`的值在软件包卸载或重新安装时就不会发生变化。
## 2、权限组问题
> 在 Android 8.0 之前,如果应用在运行时请求权限并且被授予该权限,系统会错误地将属于同一权限组并且在清单中注册的其他权限也一起授予应用。
> 对于针对 Android 8.0 的应用,此行为已被纠正。系统只会授予应用明确请求的权限。然而,一旦用户为应用授予某个权限,则所有后续对该权限组中权限的请求都将被自动批准。
> 例如,假设某个应用在其清单中列出 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE。应用请求 READ_EXTERNAL_STORAGE,并且用户授予了该权限。如果该应用针对的是 API 级别 24 或更低级别,系统还会同时授予 WRITE_EXTERNAL_STORAGE,因为该权限也属于同一 STORAGE 权限组并且也在清单中注册过。如果该应用针对的是 Android 8.0,则系统此时仅会授予 READ_EXTERNAL_STORAGE;不过,如果该应用后来又请求 WRITE_EXTERNAL_STORAGE,则系统会立即授予该权限,而不会提示用户。
**即:** targetSdkVersion<=24时,用户申请一个权限,系统会同时授予用户该权限组的其他权限。targetSdkVersion>=26时,用户申请一个权限,系统会仅仅授予其该权限,后面再请求该权限组其他权限时,系统会自动授予,而不再提示用户。
## 3、通知渠道
参考[http://www.androidwiki.site/1569138](http://www.androidwiki.site/1569138)
## 4、应用图标
参考[http://www.androidwiki.site/1569138](http://www.androidwiki.site/1569138)
## 5、允许安装未知来源应用(target 26+)
针对 8.0 的应用需要在 AndroidManifest.xml 中声明 REQUEST\_INSTALL\_PACKAGES 权限,否则将无法进行应用内升级。
# 参考
Android 10 中的隐私权变更:[https://developer.android.com/about/versions/10/privacy/changes](https://developer.android.com/about/versions/10/privacy/changes)
Android Q 适配指南 让你少走一堆弯路:[https://juejin.im/post/5cad5b7ce51d456e5a0728b0#comment](https://juejin.im/post/5cad5b7ce51d456e5a0728b0#comment)
Android O 适配详细指南:[https://juejin.im/post/5baa1c606fb9a05d396f16ea](https://juejin.im/post/5baa1c606fb9a05d396f16ea)
- 导读
- Java知识
- Java基本程序设计结构
- 【基础知识】Java基础
- 【源码分析】Okio
- 【源码分析】深入理解i++和++i
- 【专题分析】JVM与GC
- 【面试清单】Java基本程序设计结构
- 对象与类
- 【基础知识】对象与类
- 【专题分析】Java类加载过程
- 【面试清单】对象与类
- 泛型
- 【基础知识】泛型
- 【面试清单】泛型
- 集合
- 【基础知识】集合
- 【源码分析】SparseArray
- 【面试清单】集合
- 多线程
- 【基础知识】多线程
- 【源码分析】ThreadPoolExecutor源码分析
- 【专题分析】volatile关键字
- 【面试清单】多线程
- Java新特性
- 【专题分析】Lambda表达式
- 【专题分析】注解
- 【面试清单】Java新特性
- Effective Java笔记
- Android知识
- Activity
- 【基础知识】Activity
- 【专题分析】运行时权限
- 【专题分析】使用Intent打开三方应用
- 【源码分析】Activity的工作过程
- 【面试清单】Activity
- 架构组件
- 【专题分析】MVC、MVP与MVVM
- 【专题分析】数据绑定
- 【面试清单】架构组件
- 界面
- 【专题分析】自定义View
- 【专题分析】ImageView的ScaleType属性
- 【专题分析】ConstraintLayout 使用
- 【专题分析】搞懂点九图
- 【专题分析】Adapter
- 【源码分析】LayoutInflater
- 【源码分析】ViewStub
- 【源码分析】View三大流程
- 【源码分析】触摸事件分发机制
- 【源码分析】按键事件分发机制
- 【源码分析】Android窗口机制
- 【面试清单】界面
- 动画和过渡
- 【基础知识】动画和过渡
- 【面试清单】动画和过渡
- 图片和图形
- 【专题分析】图片加载
- 【面试清单】图片和图形
- 后台任务
- 应用数据和文件
- 基于网络的内容
- 多线程与多进程
- 【基础知识】多线程与多进程
- 【源码分析】Handler
- 【源码分析】AsyncTask
- 【专题分析】Service
- 【源码分析】Parcelable
- 【专题分析】Binder
- 【源码分析】Messenger
- 【面试清单】多线程与多进程
- 应用优化
- 【专题分析】布局优化
- 【专题分析】绘制优化
- 【专题分析】内存优化
- 【专题分析】启动优化
- 【专题分析】电池优化
- 【专题分析】包大小优化
- 【面试清单】应用优化
- Android新特性
- 【专题分析】状态栏、ActionBar和导航栏
- 【专题分析】应用图标、通知栏适配
- 【专题分析】Android新版本重要变更
- 【专题分析】唯一标识符的最佳做法
- 开源库源码分析
- 【源码分析】BaseRecyclerViewAdapterHelper
- 【源码分析】ButterKnife
- 【源码分析】Dagger2
- 【源码分析】EventBus3(一)
- 【源码分析】EventBus3(二)
- 【源码分析】Glide
- 【源码分析】OkHttp
- 【源码分析】Retrofit
- 其他知识
- Flutter
- 原生开发与跨平台开发
- 整体归纳
- 状态及状态管理
- 零碎知识点
- 添加Flutter到现有应用
- Git知识
- Git命令
- .gitignore文件
- 设计模式
- 创建型模式
- 结构型模式
- 行为型模式
- RxJava
- 基础
- Linux知识
- 环境变量
- Linux命令
- ADB命令
- 算法
- 常见数据结构及实现
- 数组
- 排序算法
- 链表
- 二叉树
- 栈和队列
- 算法时间复杂度
- 常见算法思想
- 其他技术
- 正则表达式
- 编码格式
- HTTP与HTTPS
- 【面试清单】其他知识
- 开发归纳
- Android零碎问题
- 其他零碎问题
- 开发思路