小秦哥 发表于 2024-9-15 20:32:50

Android 各版本适配(更新到Android14)

一 简介
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 VersionNameAPI LevelAndroid 15V35Android 14U34Android 13T33Android 12LS31Android 12.0S30Android 11.0R29Android 10.0Q28Android 9.0Pie27Android 8.1Orea26Android 8.0Orea25Android 7.1.1Nougat24Android 6.0MarshMallow23Android 5.1Lollipop22Android 5.0Lollipop21Android 4.4WKitKat Wera20Android 4.4KitKat 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清单文件中申请即可。危险权限需要在利用时动态申请,由用户决定是否授予
https://i-blog.csdnimg.cn/direct/edd829c4116f4c7cb253e93a1fa4aed8.png
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>
    ...
    <provider
      android:name="androidx.core.content.FileProvider"
      android:authorities="com.demo.fileprovider" <!--替换为自己的包名-->
      android:exported="false"
      android:grantUriPermissions="true">
      <meta-data
            android: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-path
      name="external_storage_root"
      path="." />
    <files-path
      name="files-path"
      path="." />
    <cache-path
      name="cache-path"
      path="." />
    <external-files-path
      name="external_file_path"
      path="." />
    <external-cache-path
      name="external_cache_path"
      path="." />
    <root-path
      name="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体系上面都不能正常展示。
                //通知渠道id
      val channelId = "channelId"
      val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
      if (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 = 1
      notificationManager.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 run
         Android 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 或更高版本的装备上运行时,所有应用都将拥有启动动画。这包罗启动时的进入应用动作、显示应用图标的启动画面,以及向应用自己的过渡
https://i-blog.csdnimg.cn/direct/8e3dff61671e4591a17316389ca4ede7.png
   

[*](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_MEDIA_IAMGES视频READ_MEDIA_VIDEO音频文件READ_MEDIA_AUDIO 如果用户之前向您的应用授予了 READ_EXTERNAL_STORAGE 权限,体系会自动向您的应用授予细化的媒体权限。否则,当应用请求上表中显示的任何权限时,体系会显示面向用户的对话框。<manifest ...>
    <!-- Required only if your app targets Android 13. -->
    <!-- Declare one or more the following permissions only if your app needs
    to 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 >= 33
    if (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 <= 32
    else {
      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.3 注意:
   微信付出宝熟练付出并不是随意机器就可以,必须要厂家授权的机器类型才可以,所以一般并不能同同时付出两种刷脸付出。
六 微信小程序开辟流程 
   https://mp.weixin.qq.com/
1,新建账号,完成资质认证
2,个人需要完成实名认证
3,企业需要营业执照
4,注册小程序,确定小程序信息和类目
5,小程序微信认证,个人需要打款30元考核费用,期间微信客户会打电话核实
6,小程序存案,工信部会发短信,24小时内点击毗连验证
7,下载微信开辟者工具,创建小程序项目,关联小程序id
8,上传预览版,可以在小程序平台看到版本管理
9,小程序必须开辟好后才能正式提交,期间可以上传预览

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Android 各版本适配(更新到Android14)