一 简介
1.1 Android 目前最新版已更新到了Android14,google市场每次更新都要求必须同步更新项目API,否则会有下架风险。
1.2 Android 每一个版本更新都对电量优化,通知的使用,隐私权限方面做了修改,所以重点适配方面也是在这几个方面
二 各版本更新变化
2.1 Android 1.0 (API Level 1) - 2008年9月发布,首次发布的Android版本,提供了基本功能。
2.2 Android 1.1 (API Level 2) - 2009年2月发布,增加了一些功能改进,如支持地图和小部件。
2.3 Android 1.5 (Cupcake, API Level 3) - 2009年4月发布,首次引入了虚拟键盘和小部件。
2.4 Android 1.6 (Donut, API Level 4) - 2009年9月发布,增强了搜索功能,支持不同屏幕尺寸。
2.5 Android 2.0 (Eclair, API Level 5) - 2009年10月发布,引入了多帐户支持、图像和音频增强。
2.6 Android 2.2 (Froyo, API Level 8) - 2010年5月发布,增加了对Flash的支持,提升了性能和安全性。
2.7 Android 2.3 (Gingerbread, API Level 9) - 2010年12月发布,优化了用户界面和游戏性能,增加了对NFC的支持。
2.8 Android 3.0 (Honeycomb, API Level 11) - 2011年2月发布,专为平板电脑设计,改进了界面和多任务功能。
2.9 Android 4.0 (Ice Cream Sandwich, API Level 14) - 2011年10月发布,统一了智能手机和平板电脑的用户界面,增加了面部解锁。
2.10 Android 4.1 (Jelly Bean, API Level 16) - 2012年7月发布,增强了流畅度和通知功能。
2.11 Android 4.4 (KitKat, API Level 19) - 2013年10月发布,优化了性能,提高了在低内存设备上的运行效果。
2.12 Android 5.0 (Lollipop, API Level 21) - 2014年11月发布,彻底改进了用户界面,增加了Material Design。
2.13 Android 6.0 (Marshmallow, API Level 23) - 2015年10月发布,增强了权限管理和Doze模式以延长电池使用。
2.14 Android 7.0 (Nougat, API Level 24) - 2016年8月发布,支持分屏模式和增强的通知功能。
2.15 Android 8.0 (Oreo, API Level 26) - 2017年8月发布,引入了画中画、多窗口和通知渠道。
2.16 Android 9.0 (Pie, API Level 28) - 2018年8月发布,改进了用户界面,增加了手势导航和数字健康功能。
2.17 Android 10 (API Level 29) - 2019年9月发布,全面改进隐私权和位置控制,并引入黑暗模式。
2.18 Android 11 (API Level 30) - 2020年9月发布,增强了通讯管理和多媒体功能。
2.19 Android 12 (API Level 31) - 2021年10月发布,改进了隐私和新的用户自定义界面。
2.20 Android 13 (API Level 33) - 2022年8月发布,进行了小幅改进,包括新的个性化选项和隐私特性。
2.21 Android 14 (API Level 34) - 2023年预期发布,预计将继续增强隐私和用户体验。
三 版本,名字,和api对比表
Android Version | Name | API Level |
Android 15 | V | 35 |
Android 14 | U | 34 |
Android 13 | T | 33 |
Android 12L | S | 31 |
Android 12.0 | S | 30 |
Android 11.0 | R | 29 |
Android 10.0 | Q | 28 |
Android 9.0 | Pie | 27 |
Android 8.1 | Orea | 26 |
Android 8.0 | Orea | 25 |
Android 7.1.1 | Nougat | 24 |
Android 6.0 | MarshMallow | 23 |
Android 5.1 | Lollipop | 22 |
Android 5.0 | Lollipop | 21 |
Android 4.4W | KitKat Wera | 20 |
Android 4.4 | KitKat | 19 |
四 各版本适配
4.1 Android4.4到android5(API19-22)
权限比较低,不需要太多权限就能访问,不再多介绍,现在android5以下手机已经非常少了(开发板RK系列除外)
4.2 Android6(API23)
运行时权限
- android6.0 之前,我们把app需要用到的权限全部罗列在Manifest清单文件中。安装app时android系统会询问用户是否授予这些权限,拒绝后则无法安装app。如果授予,则安装app,之后无法修改授予状态。
- android6.0 将权限分为普通权限(不涉及用户隐私和安全)和危险权限(设计用户隐私和安全)。普通权限和andorid6.0之前一样,在Manifest清单文件中申请即可。危险权限需要在使用时动态申请,由用户决定是否授予
HttpClient的移除
自Android6.0起,HttpClient系列代码从SDK中剔除,推荐使用HttpURLConnection。
4.3 Android7(API24)
应用间共享文件
- 对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI 。如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常。
- 要在应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用 FileProvider 类。
- 在AndroidManifest.xml清单文件中注册provider
authorities 是标记我们这个ContentProvider的唯一标识,是一个用于认证的暗号,我们一般默认使用包名+fileprovider来定义。(能不能使用别的,可以,abcd都行,但是没必要)name 是具体的FileProvider类,如果是系统的,就用上面的这种,如果是自定义的,就写自定义FileProvider的全类名。exported 是否限制其他应用获取此FileProvider。grantUriPermissions 是否授权其他应用获取访问Uri权限,一般为true。meta-data 和下面的 name 都是固定的写法,重点是 resource 需要自己实现规则,定义哪些私有文件会被提供访问。
<manifest>...<application>...<providerandroid:name="androidx.core.content.FileProvider"android:authorities="com.demo.fileprovider" <!--替换为自己的包名-->android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/paths" /></provider>...</application> </manifest>
- res/xml中定义对外暴露的文件夹路径:
root-path 从SD卡开始找 例如 storage/emulated/0/Android/data/com.guadou.kt_demo/cache/pos/naixiao-1122.jpg external-path 从外置SD卡开始 例如 Android/data/com.guadou.kt_demo/cache/pos/naixiao-1122.jpg external-files-path 外置沙盒file目录 例如 pos/naixiao-1122.jpg (真实目录在 Android/data/com.guadou.kt_demo/cache/pos/) external-cache-path 外置沙盒cache目录 例如 naixiao-1122.jpg (真实目录在 Android/data/com.guadou.kt_demo/cache/) files-path 和上面的同理,只是在内置的data/data目录下面 cache-path 和上面的同理,只是在内置的data/data目录下面
<?xml version="1.0" encoding="utf-8"?> <paths><external-pathname="external_storage_root"path="." /><files-pathname="files-path"path="." /><cache-pathname="cache-path"path="." /><external-files-pathname="external_file_path"path="." /><external-cache-pathname="external_cache_path"path="." /><root-pathname="root-path"path="" /> </paths>
广播
- 面向 Android 7.0 开发的应用不会收到 CONNECTIVITY_ACTION 广播,即使它们已有清单条目来请求接受这些事件的通知。
- 在主线程中通过Context.registerReceiver()动态注册了CONNECTIVITY_ACTION广播,该应用程序仍然可以接收到该广播。
- 应用无法发送或接收 ACTION_NEW_PICTURE 或 ACTION_NEW_VIDEO 广播。此项优化会影响所有应用,而不仅仅是面向 Android 7.0 的应用。
4.4 Android 8.0
通知渠道id
Android 8.0 引入了通知渠道,其允许您为要显示的每种通知类型创建用户可自定义的渠道。用户界面将通知渠道称之为通知类别。targeSdk升级到26之后,所有的通知的实现都需要提供通知渠道,如果不提供通知渠道的话,所有通知在8.0系统上面都不能正常展示。
//通知渠道idval channelId = "channelId"val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManagerif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//通知渠道名称val channelName = "channelName"//通知渠道重要程度val importance = NotificationManager.IMPORTANCE_HIGH//构建通知渠道val channel = NotificationChannel(channelId, channelName, importance)//设置通知渠道描述channel.description = ""//向系统注册通知渠道,注册后则不能修改重要性以及其他通知行为,但可以删除notificationManager.createNotificationChannel(channel)}val notification = NotificationCompat.Builder(this, "channelId").setContentTitle("标题").setContentText("消息内容").setSmallIcon(R.drawable.ic_launcher_background).setAutoCancel(true)//点击自动消失.build()//通知id,每个通知都应该不同否则会覆盖val notifyId = 1notificationManager.notify(notifyId, notification)
后台执行限制
- 如果针对 Android 8.0 的应用尝试在不允许其创建后台服务的情况下使用 startService() 函数,则该函数将引发一个 IllegalStateException。
- 新的 Context.startForegroundService() 函数将启动一个前台服务。现在,即使应用在后台运行,系统也允许其调用 Context.startForegroundService()。不过,应用必须在创建服务后的五秒内调用该服务的 startForeground() 函数。
允许安装未知来源应用
8.0 的应用需要在 AndroidManifest.xml 中声明 REQUEST_INSTALL_PACKAGES 权限,否则将无法进行应用内升级。
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
隐式广播的限制
我们自己定义的广播隐式调用不能接收,显式Intent可以接收。或者动态注册,然后隐式调用可以接收。如果要接收系统广播只能动态注册。
权限
之前对于隐私权限只要申请一个就会将其在的权限组全部通过,android 8.0以后申请单个只给单个
4.5 Android9(API27)
限制非 Activity 环境中启动 Activity
在 Android 9 中,不能从非 Activity 环境中启动 Activity,除非您传递 Intent 标志 FLAG_ACTIVITY_NEW_TASK。 如果您尝试在不传递此标志的情况下启动 Activity,则该 Activity 不会启动,系统会在日志中输出一则消息。
前台服务
针对 Android 9 或更高版本并使用前台服务的应用必须请求 FOREGROUND_SERVICE 权限。 这是普通权限,因此,系统会自动为请求权限的应用授予此权限。
默认情况下启用网络传输层安全协议 (TLS)
- 如果应用以 Android 9 或更高版本为目标平台,则默认情况下 isCleartextTrafficPermitted() 函数返回 false。 如果您的应用需要为特定域名启用明文,您必须在应用的网络安全性配置中针对这些域名将 cleartextTrafficPermitted 显式设置为 true。
- 在 res 目录下新建xml文件夹,添加network_security_config.xml文件:
<?xml version="1.0" encoding="utf-8"?> <network-security-config><base-config cleartextTrafficPermitted="true"><trust-anchors><certificates src="system" /><certificates src="user" /></trust-anchors></base-config> </network-security-config>
- AndroidManifest.xml中的application添加
<?xml version="1.0" encoding="utf-8"?> <manifest ... ><application android:networkSecurityConfig="@xml/network_security_config">...</application> </manifest>
硬件序列号
- 在 Android 9 中,Build.SERIAL 始终设置为 “UNKNOWN” 以保护用户的隐私。
- 如果您的应用需要访问设备的硬件序列号,您应改为请求 READ_PHONE_STATE 权限,然后调用 getSerial()。
4.6 Android10(API28)
分区存储:分区存储将外部存储分成两部分
- App-specific directory (沙盒目录)
- APP只能在Context.getExternalFilesDir()目录下通过File的方式创建文件,APP卸载的时候,这个目录下的文件会被删除;无法通过File的方式在其他路径创建文件。
- Public Directory 公共目录
- 公共目录包括:多媒体公共目录(Photos, Images, Videos, Audio)和下载文件目录(Downloads)。
- APP可以通过MediaStore 或者 SAF(System Access Framework)的方式访问其中的文件。APP卸载后,文件不会被删除。
- Android Q以上移除了WRITE_EXTERNAL_STORAGE权限,应用不需要这个权限就可以向沙盒内存储文件,也可以通过媒体数据库的方式保存媒体数据至特定位置。
- App卸载后,对应的沙盒目录也会被删除,如果APP想要在卸载时保留沙盒目录下的数据,要在 AndroidManifest.xml 中声明 android:hasFragileUserData=“true”,这样在 APP卸载时就会有弹出框提示用户是否保留应用数据
后台运行时访问设备位置信息需要权限
- Android 10 引入了 ACCESS_BACKGROUND_LOCATION 权限(危险权限)。
- 该权限允许应用程序在后台访问位置。如果请求此权限,则还必须请求ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION权限。只请求此权限无效果。
- Android 10中必须具有 ACCESS_FINE_LOCATION 权限才能使用的类和方法:
- 电话(TelephonyManager),wifi(WifiManager),蓝牙(BluetoothAdapter)
后台启动 Activity 的限制
应用处于后台时,无法启动Activity。
深色主题
- 手动适配—资源替换
- res 下新建 values-night目录,创建对应的colors.xml文件。
- 自动适配—Force Dark
- 应用必须选择启用 Force Dark,方法是在其主题背景中设置 android:forceDarkAllowed=“true”。此属性会在所有系统及 AndroidX 提供的浅色主题背景(例如 Theme.Material.Light)上设置。
- Force Dark需要注意几点:
- 如果使用的是 DayNight 或 Dark Theme 主题,则设置forceDarkAllowed 不生效。
- 如果有需要排除适配的部分,可以在对应的View上设置forceDarkAllowed为false。
标识符和数据
- Build
- getSerial()
- TelephonyManager
- getImei()
- getDeviceId()
- getMeid()
- getSimSerialNumber()
- getSubscriberId()
- 从 Android 10 开始,应用必须具有 READ_PRIVILEGED_PHONE_STATE 特许权限才能正常使用以上这些方法。
- 如果你的应用没有该权限,却仍然使用了以上的方法,则返回的结果会因目标 SDK 版本而异:
- 如果应用以 Android 10 或更高版本为目标平台,则会发生 SecurityException。
- 如果应用以 Android 9(API 级别 28)或更低版本为目标平台,则相应方法会返回 null 或占位符数据(如果应用具有 READ_PHONE_STATE 权限)。否则,会发生 SecurityException。
- 这项改动表示第三方应用无法获取Device ID这类唯一标识。
对启用和停用 WLAN 实施了限制
以 Android 10 或更高版本为目标平台的应用无法启用或停用 WLAN。WifiManager.setWifiEnabled() 方法始终返回 false。
4.7 Android11(API29)
分区存储强制执行
- Android 11在分区存储基础上限制了应用访问其他应用的文件。
- 分区存储将存储空间分为两部分:
- 公共目录:Downloads、Documents、Pictures 、DCIM、Movies、Music、Ringtones等
- 公共目录的文件在App卸载后,不会删除
- 可以通过SAF、MediaStore接口访问
- 拥有权限,也能通过路径直接访问
- 应用专属目录
- 应用专属目录只能自己直接访问
- App卸载,数据会清除。
- 将应用更新为以 Android 11 为目标平台后,您将无法使用requestLegacyExternalStorage,而且也没有其他标记可以提供停用分区存储。
- 所有文件访问权限 MANAGE_EXTERNAL_STORAGE,用来获取所有文件的管理权限。
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />val intent = Intent() intent.action= Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION startActivity(intent)//判断是否获取MANAGE_EXTERNAL_STORAGE权限: val isHasStoragePermission= Environment.isExternalStorageManager()
电话号码相关权限
- Android 11 更改了应用在读取电话号码时使用的与电话相关的权限。
- 如果应用以 Android 11 或更高版本为目标平台,并且需要访问以下列表中显示的电话号码 API,则必须请求 READ_PHONE_NUMBERS 权限,而不是 READ_PHONE_STATE 权限。
- TelephonyManager 类和 TelecomManager 类中的 getLine1Number() 方法。
- TelephonyManager 类中不受支持的 getMsisdn() 方法。
- 如果应用声明 READ_PHONE_STATE 以调用前面列表中的方法以外的方法,可以继续在所有 Android 版本中请求 READ_PHONE_STATE。不过,如果仅对前面列表中的方法使用 READ_PHONE_STATE 权限,请按以下方式更新您的清单文件:
- 更改 READ_PHONE_STATE 的声明,以使应用仅在 Android 10(API 级别 29)及更低版本中使用该权限。
- 添加 READ_PHONE_NUMBERS 权限。
<manifest ...><!-- Grants the READ_PHONE_STATE permission only on devices that runAndroid 10 (API level 29) and lower. --><uses-permission android:name="READ_PHONE_STATE"android:maxSdkVersion="29" /><uses-permission android:name="READ_PHONE_NUMBERS" /> </manifest>
自定义消息框视图被屏蔽
- 出于安全方面的考虑,同时也为了保持良好的用户体验,如果包含自定义视图的消息框是以 Android 11 或更高版本为目标平台的应用从后台发送的,系统会屏蔽这些消息框。请注意,仍允许使用文本消息框;此类消息框是使用 Toast.makeText() 创建的,并不调用 setView()。
- 如果您的应用仍尝试从后台发布包含自定义视图的消息框,系统不会向用户显示相应的消息,而是会在 logcat 中记录以下消息:
W/NotificationService: Blocking custom toast from package \<package> due to package not in the foreground
媒体intent操作需要系统默认相机
- 从 Android 11 开始,只有预装的系统相机应用可以响应以下 intent 操作:
- android.media.action.VIDEO_CAPTURE
- android.media.action.IMAGE_CAPTURE
- android.media.action.IMAGE_CAPTURE_SECURE
- 也就是说,如果我调用intent唤起照相机,使用VIDEO_CAPTURE的action,只有系统的相机能够响应,而第三方的相机应用不会响应了。
- 如果要使用特定的第三方相机应用来代表其捕获图片或视频,可以通过为intent设置软件包名称或组件来使这些intent变得明确。
软件包可见性
- Android 11 更改了应用查询用户已在设备上安装的其他应用以及与之交互的方式。使用 <queries> 元素,应用可以定义一组自身可访问的其他软件包。通过告知系统应向应用显示哪些其他软件包,此元素有助于鼓励最小权限原则。此外,此元素还可帮助 Google Play 等应用商店评估应用为用户提供的隐私权和安全性。
- 如果应用以 Android 11 或更高版本为目标平台,您可能需要在应用的清单文件中添加 <queries> 元素。在 <queries> 元素中,您可以按软件包名称、intent 签名或提供程序授权指定软件包。
前台服务类型
- 从 Android 9 开始,应用仅限于在前台访问摄像头和麦克风。为了进一步保护用户,Android 11 更改了前台服务访问摄像头和麦克风相关数据的方式。如果您的应用以 Android 11 为目标平台并且在某项前台服务中访问这些类型的数据,您需要在该前台服务的声明的 foregroundServiceType 属性中添加新的 camera 和 microphone 类型。
- 应用某项前台服务需要访问位置信息、摄像头和麦克风,那么就要在清单文件中这样添加:
<manifest ...><service ...android:foregroundServiceType="location|camera|microphone" /> </manifest>
4.8 Android12(API30-31)
SplashScreen
从 Android 12 开始,在搭载 Android 12 或更高版本的设备上运行时,所有应用都将拥有启动动画。这包括启动时的进入应用动作、显示应用图标的启动画面,以及向应用本身的过渡
- (1)应用图标应该是矢量可绘制对象(AVD XML),它可以是静态或动画形式。虽然动画的时长可以不受限制,但我们建议不超过1,000 毫秒。默认情况下,使用启动器图标。
- (2)可以选择添加图标背景;在图标与窗口背景之间需要更高的对比度时图标背景很有用。如果您使用一个自适应图标,当该图标与窗口背景之间的对比度足够高时,就会显示其背景。
- (3)与自适应图标一样,前景的三分之一被遮盖。
- (4)窗口背景由不透明的单色组成。如果窗口背景已设置且为纯色,则未设置相应的属性时默认使用该背景。
更安全的组件导出
以Android 12为目标平台的App,如果其包含的四大组件中使用到了Intent过滤器(intent-filter),则必须显式声明 android:exported 属性,否则App将无法在Android 12及更高系统版本的设备上安装。
定位权限:大概位置
- 如果您的应用请求 ACCESS_COARSE_LOCATION,但未请求 ACCESS_FINE_LOCATION,则此变更不会影响您的应用。
- 如果您的应用请求 ACCESS_FINE_LOCATION 运行时权限,您还应请求ACCESS_COARSE_LOCATION 权限,以便处理用户授予应用大致位置访问权限的情形。
PendingIntent可变性
- 如果您的应用程序以Android 12为目标平台,您必须为应用创建的每个 PendingIntent 对象指定可变性。这项额外的要求可提高应用的安全性。因为三方app可以通过劫持PendingIntent,然后改写里面的action、category、data等,造成重定向攻击。
- 适配的具体就是在创建 PendingIntent时,使用 PendingIntent.FLAG_MUTABLE 或 PendingIntent.FLAG_IMMUTABLE 标志。否则运行时会报 IllegalArgumentException。
蓝牙权限
- 如果您的应用程序面向Android 12或更高版本,使用蓝牙功能时请在应用程序的清单文件中声明以下权限:
- BLUETOOTH_SCAN:允许蓝牙设备扫描。
- BLUETOOTH_CONNECT:允许蓝牙设备连接。
- BLUETOOTH_ADVERTISE:允许当前蓝牙设备可以被其他蓝牙设备发现。
- 对于以前的与蓝牙相关的权限声明,设置android:maxSdkVersion到30。此应用兼容性步骤可帮助系统仅授予您的应用在运行Android 12 的设备上安装时所需的蓝牙权限。
<manifest ...><!-- Request legacy Bluetooth permissions on older devices. --><uses-permission android:name="android.permission.BLUETOOTH"android:maxSdkVersion="30" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"android:maxSdkVersion="30" /><uses-permission android:name="android.permission.BLUETOOTH_SCAN" /><uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /><uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /><!-- 只有当您的应用程序使用蓝牙扫描结果来获取物理位置时才需要 --><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />... </manifest>
- 如果您的应用程序使用蓝牙扫描结果来获取物理位置,请声明ACCESS_FINE_LOCATION。以前版本中(6.0 ~ 11)是必须申请定位权限,才可以进行蓝牙扫描。
- 在Android 12上,如果你的应用程序不使用蓝牙扫描结果来获取物理位置。可以添加android:usesPermissionFlags 属性到您的 BLUETOOTH_SCAN 权限声明,并将该属性的值设置为 neverForLocation。
<manifest ...><uses-permission android:name="android.permission.BLUETOOTH_SCAN"android:usesPermissionFlags="neverForLocation" /><!--Android 12后,可以删除定位权限 --><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />... </manifest>
4.9 Android13 (API33)
细化的媒体权限
如果应用以 Android 13 或更高版本为目标平台,并且需要访问其他应用已经创建的媒体文件,必须请求以下一项或多项细化的媒体权限,而不是READ_EXTERNAL_STORAGE 权限:
如果用户之前向您的应用授予了 READ_EXTERNAL_STORAGE 权限,系统会自动向您的应用授予细化的媒体权限。否则,当应用请求上表中显示的任何权限时,系统会显示面向用户的对话框。
媒体类型 请求权限 图片和照片 READ_MEDIA_IAMGES 视频 READ_MEDIA_VIDEO 音频文件 READ_MEDIA_AUDIO <manifest ...><!-- Required only if your app targets Android 13. --><!-- Declare one or more the following permissions only if your app needsto access data that's protected by them. --><uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /><uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /><uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /><!-- Required to maintain app compatibility. --><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"android:maxSdkVersion="32" /><application ...>...</application> </manifest>
通知运行时权限
在AndroidManifest.xml中对发送通知权限进行声明:
<manifest ...><uses-permission android:name="android.permission.POST_NOTIFICATIONS"/><application ...>...</application> </manifest>
POST_NOTIFICATIONS权限只有在应用程序的targetSdk指定成33或更高时才会有用。
要确认用户是否已启用通知,请调用 areNotificationsEnabled()。
静态广播注册
- 从Android 13开始,以Android13(API 33+)为目标平台的应用,注册静态广播时,需设置对其他应用的可见性:
- 若对其他应用可见,广播注册时设置:Context.RECEIVER_EXPORTED
- 若仅应用内使用,广播注册时设置:Context.RECEIVER_NOT_EXPORTED
private void registerTestReceiver() {IntentFilter filter = new IntentFilter();filter.addAction("com.xiaxl.test.action");// api >= 33if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {// 跨应用间使用MainActivity.this.registerReceiver(mTestReceiver, filter, Context.RECEIVER_EXPORTED);// 应用内使用//MainActivity.this.registerReceiver(mTestReceiver, filter, Context.RECEIVER_EXPORTED);}// api <= 32else {MainActivity.this.registerReceiver(mTestReceiver, filter);} }
- 目前该增强措施并非默认生效,开发者需启用 DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED兼容性框架,并在动态注册广播时指定是否接受其他应用的广播。
- 如果启用了 DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED 兼容性框架更改,则必须为每个广播接收器指定 RECEIVER_EXPORTED 或 RECEIVER_NOT_EXPORTED。否则,当您尝试注册广播接收器时,系统会抛出 SecurityException。
4.10 Android 14 (API34)
默认拒绝设定精确的闹钟
- 精确警报适用于需要在精确时间发生的用户意图的通知或操作。Android 12 中引入的应用安排精确闹钟的权限不再预先授予大多数以 Android 13 及更高版本为目标平台的新安装应用(默认情况下将设置为拒绝)。如果用户通过备份和还原操作将应用数据传输到搭载 Android 14 的设备,则该权限仍会被拒绝。如果现有应用已拥有此权限,则在设备升级到 Android 14 时,系统会预先授予该权限。
- 需要 SCHEDULE_EXACT_ALARM 权限才能通过以下 API 启动确切警报,否则将引发 SecurityException:
setExact() setExactAndAllowWhileIdle() setExactAndAllowWhileIdle() setAlarmClock()
对照片和视频进行独立授权
- Android 14 引入了所选照片访问权限,可让用户授权应用访问其媒体库中的特定图片和视频,而不是授予对指定类型的所有媒体内容的访问权限。即独自设置 READ_MEDIA_IMAGES 或 READ_MEDIA_VIDEO,注意这两个权限仅在Android13及以上才能运行。
- 新增了一个 READ_MEDIA_VISUAL_USER_SELECTED 权限,归于 Dangerous 等级。用于在用户点击自定义的相片挑选器需求请求拜访相片和视频的权限时运用,这样就不必去请求 READ_MEDIA_IMAGES 和 READ_MEDIA_VIDEO 这两个权限了。
private fun checkPermissionResult() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU&& (ContextCompat.checkSelfPermission(this, READ_MEDIA_IMAGES) == PERMISSION_GRANTED|| ContextCompat.checkSelfPermission(this, READ_MEDIA_VIDEO) == PERMISSION_GRANTED)) {// Android 13及以上完整照片和视频访问权限} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&ContextCompat.checkSelfPermission(this, READ_MEDIA_VISUAL_USER_SELECTED) == PERMISSION_GRANTED) {// Android 14及以上部分照片和视频访问权限} else if (ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) == PERMISSION_GRANTED) {// Android 12及以下完整本地读写访问权限} else {// 无本地读写访问权限} }
限制前台服务
- targetSdkVersion 34 的情况下,必须为应用内的每个前台服务(foreground-services) 指定至少一种前台服务类型。
- 前台服务类型是在 Android 10 引入的,通过 android:foregroundServiceType 可以指定 <service>
- 如果以 Android 14 为目标平台的应用未在清单中定义给定服务的类型,系统会在调用 startForeground() 时引发 MissingForegroundServiceTypeException。
最低可安装的目标 API 级别
从 Android 14 开始,targetSdkVersion 低于 23 (Android 6.0)的应用无法安装。要求应用满足这些最低目标 API 级别要求有助于提高用户的安全性和隐私性。
在 BluetoothAdapter 中强制执行 BLUETOOTH_CONNECT 权限
- 对于以 Android 14(API 级别 34)为目标平台的应用,Android 14 会在调用 BluetoothAdapter getProfileConnectionState() 方法时强制执行 BLUETOOTH_CONNECT 权限。
- 此方法已需要 BLUETOOTH_CONNECT 权限,但未被强制执行。请确保应用在应用的 AndroidManifest.xml 文件中声明 BLUETOOTH_CONNECT(如以下代码段所示),并在调用 getProfileConnectionState 之前检查用户是否已授予权限。
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
对隐式 intent 和待处理 intent 的限制
对于以 Android 14 为目标平台的应用,Android 会通过以下方式限制应用向内部应用组件发送隐式 intent:
隐式 intent 只能传送到导出的组件。应用必须使用显式 intent 传送到未导出的组件,或将该组件标记为已导出。
如果应用通过未指定组件或软件包的 intent 创建可变待处理 intent,系统现在会抛出异常。
这些变更可防止恶意应用拦截意在供应用内部组件使用的隐式 intent。比如在清单文件中声明:
<activity android:name=".AppActivity"android:exported="false"><intent-filter><action android:name="com.example.action.APP_ACTION" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></activity>
如果应用尝试使用隐式 intent 启动此 activity,则系统会抛出异常:
// Throws an exception when targeting Android 14. context.startActivity(Intent("com.example.action.APP_ACTION"))
如需启动非导出的 activity,应用应改用显式 intent:
// This makes the intent explicit. val explicitIntent = Intent("com.example.action.APP_ACTION")explicitIntent.apply {package = context.packageName }context.startActivity(explicitIntent)
注册的广播接收器必须指定导出行为
以 Android 14 为目标平台并使用上下文注册的接收器的应用和服务必须指定以下标志,以指明接收器是否应导出到设备上的所有其他应用:RECEIVER_EXPORTED 或 RECEIVER_NOT_EXPORTED。
val filter = IntentFilter(APP_SPECIFIC_BROADCAST) val listenToBroadcastsFromOtherApps = false val receiverFlags = if (listenToBroadcastsFromOtherApps) {ContextCompat.RECEIVER_EXPORTED } else {ContextCompat.RECEIVER_NOT_EXPORTED } ContextCompat.registerReceiver(context, br, filter, receiverFlags)
如果您的应用仅通过 Context#registerReceiver 方法(例如 Context#registerReceiver()针对 系统广播 注册接收器,那么它在注册接收器时不应指定标志。
五 刷脸支付适配
5.1 微信刷脸支付流程
https://open.weixin.qq.com/
https://pay.weixin.qq.com/wiki/doc/wxfacepay/develop/android/facepay.html
微信开放平台支付开通:
5.1.1,注册开放平台账号
5.1.2,进行开发者资质认证
5.1.3,开通商户号
5.1.4,新建移动应用(名字,logo,简介,介绍图,appid)
5.1.5,绑定应用包名和md5签名
5.1.6,开放平台开通支付能力
5.1.7,登录超管商户平台绑定appid,和账号主体(账号信息中的公司名字)
5.1.8,在开放平台确认授权商户号
5.1.9,接入支付平台SDK(微信支付,刷脸支付,扫码支付)
5.2 支付宝刷脸支付流程
https://open.alipay.com/
https://opendocs.alipay.com/open/20180402104715814204
支付宝开放平台支付开通:
5.2.1,注册开放平台账号
5.2.2,进行开发者资质认证
5.2.3,开通商户号
5.2.4,新建移动应用(名字,logo,简介,appid)
5.2.5,绑定应用包名和md5签名
5.2.6,进行开发配置,公钥私钥
5.2.7,进行ip白名单设置
5.2 注意:
微信支付宝熟练支付并不是随意机器就可以,必须要厂家授权的机器类型才可以,所以一般并不能同同时支付两种刷脸支付。