目次
一、Android14
1.1 Android14根本信息
1.2 迁移到Android14
二、针对所有应用的变动
2.1 字体缩放
2.2 sdk版本 >= 33的变动
2.2.1 默认拒绝设定准确的闹钟
2.2.2 授予对照片和视频的部门访问权限
2.3 上下文注册的广播会在应用缓存期间加入队列
2.4 应用只能终止自己的背景进程
2.5 最低可安装的目的API级别
2.6 用户可关闭不可关闭通知
三、targetSdk >= 34的变动
3.1 启动前台服务必须设置前台服务类型
3.2 OpenJDK17更新
3.3 JobScheduler 增强回调和网络举动
3.4 对隐式intent和待处理intent的限制
3.5 在运行时注册的广播接收器必须指定导出举动
3.6 安全的动态代码加载
3.7 针对从背景启动Activity的其他限制
3.8 压缩路径遍历
3.9 每个MediaProjection拍摄会话均必要征得用户同意
3.10 安全的全屏intent通知
四、新增/改善 功能
4.1 截屏监听
4.2 路径可查询和插值
4.3 各应用语言偏好设定
正文
一、Android14
1.1 Android14根本信息
Android 14 对应的 API 版本是 34 ,内部代号为 UpsideDownCake。
一直以来,谷歌都有效甜点名称来命名 Android 版本的传统,遵照的规律是首字母按照字母表的次序进行迭代。但是在 Android 10 推出时,这一传统有了变化,将 Android 版本重新命名为单纯的数字。但是内部仍然是有一个代号来代表每一个版本的,汗青版本以及代号如下表所示
1.2 迁移到Android14
适配高版本Android的条件条件 设备已经刷写了Android14版本的系统映像,主要工作是对应用做兼容性测试
对应版本的手机大概模拟器
Android 14 SDK 与低版本的Android studio 有一些不兼容的改动,为了避免这一类问题的导致的报错,官方建议我们把版本更换到Android Studio Flamingo | 2022.2.1 或更高版本
在AS 中下载对应的版本,分别在 SDK platform 以及 SDK Tools 中下载34 版本的
二、针对所以应用的变动
2.1 字体缩放
这个属于 无障碍功能 里面的一个子功能。
从 Android 14 开始,系统支持字体放大到 200%,主要是为了更好的为 弱视用户提供使用情况。
为防止屏幕上的大文本元素放大过大,系统会接纳非线性放大曲线。这种放大策略意味着大号文本的放大比例不会与较小的文本雷同。非线性字体缩放有助于保持不同大小元素之间的比例层次布局,同时缓解高级别线性文本缩放的问题(例如文本被截断或文本因超大表现大小而难以阅读)
1、设置 > 无障碍 > 表现大小和文字
2、在界面操作 放大或缩小文字
主要是对个app (三方&系统)的适配上有影响,app必要调治到最大比例后检查界面表现情况
1、以 sp 为单元文本大小
2、使用 TypedValue.applyDimension() 从 sp 单元转换为像素,并使用 TypedValue.deriveDimension() 将像素转换为 sp,这些方法会自动应用适当的非线性缩放曲线。
3、对 lineHeight 使用 sp 单元,以便行高随文本一起缩放。否则,假如您的文本为 sp,而 lineHeight 以 dp 或 px 为单元,则文本无法缩放且看起来局促。以 sp 为单元同时定义 textSize 和 lineHeight,TextView 会自动更正 lineHeight
2.2 sdk版本 >= 33的变动
2.2.1 默认拒绝设定准确的闹钟
Android 14 开始 ,targetSdkVersion>=33 的新安装用户 SCHEDULE_EXACT_ALARM 权限默认拒绝(此权限是在Android 12 中引入的),在使用以下几个方法
- setExact()
- setExactAndAllowWhileIdle()
- setAlarmClock()
时,会抛出 SecurityException 异常
继续使用准确闹钟必要做以下几个操作:
针对 SCHEDULE_EXACT_ALARM 权限 ,也有对应的处理办法:
1、在调用上述几个方法之前,先调用 AlarmManager.canScheduleExactAlarms() 来检查权限
2、无权限。则调用 包罗 ACTION_REQUEST_SCHEDULE_EXACT_ALARM 以及应用软件包名称的 intent,要求用户授予权限,代码示例:
- AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
- // permission is granted
- if (alarmManager.canScheduleExactAlarms()) {
- alarmManager.setExact(...);
- } else {
- // 申请权限
- startActivity(new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM));
- }
复制代码
3、调用
AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED 来让应用设置为监听并精确响应前台广播 ,系统在授予权限时会发送该广播
2.2.2 授予对照片和视频的部门访问权限
在升级 Android 14 之后,用户可以限制目的 SDK 版本高于或等于 33 的应用步伐仅能访问用户选定的照片。
具体操作是,当应用的照片权限被设置为“始终询问”时,当应用哀求权限后,系统权限管理器会询问用户是否让App访问所有照片,还是选择特定的照片,选择后者会弹出“照片选择器”让用户选择照片,应用只能访问用户选定的照片.
新增的权限为 READ_MEDIA_VISUAL_USER_SELECTED ,如必要访问所有媒体文件必要同步申请 READ_MEDIA_IMAGES 和 READ_MEDIA_VIDEO .
2.3 上下文注册的广播会在应用缓存期间加入队列
在 Android 14 中,当应用处于缓存状态时,系统可以将上下文注册的广播放入队列中。在清单中声明的广播不会加入队列,并且应用会从缓存状态中移除以进行广播传递。
当应用离开缓存状态(例如返回前台)时,系统会传递所有已加入队列的广播。某些广播的多个实例可以合并为一个广播。根据其他因素(例如系统运行状态),系统大概会从缓存状态中移除应用,并且传输之前加入队列的所有广播。
此项变动让广播接收变得不那么靠谱,也大概导致app 资源未实时烧毁导致内存泄漏
缓存进程是当前不必要的进程,因此当其他位置必要诸如内存等资源时,系统会根据必要随意终止该进程。在正常运行的系统中,这些是资源管理中涉及的唯一进程。
运行良好的系统始终会有多个缓存进程可用,以便在应用之间高效切换,并可根据必要定期终止缓存的应用。只有在非常关键的情况下,系统才会到达所有缓存进程都会终止的程度,并且必须开始终止服务进程。
由于系统大概随时终止缓存的进程,因此应用在处于缓存状态时应制止所有工作。假如应用必须执行用户关键使命,则应使用上述 API 以活泼进程状态运行工作。
缓存的进程通常会保存一个或多个用户当前不可见的 Activity 实例(其 onStop() 方法已被调用并返回)。假如它们在系统终止此类进程时精确实现其 Activity 生命周期,不会影响用户在返回该应用时的体验。当关联的 activity 在新进程中重新创建时,它可以恢复之前保存的状态。请注意,假如进程被系统终止,则不能包管会调用 onDestroy()。
缓存的进程会保存在列表中。此列表的确切排序政策是平台的实现细节。通常,它会尝试保存更实用的进程,例如托管用户的主屏幕应用或用户前次看到的 activity 的进程,然后运行其他类型的进程。您也可以应用终止进程的其他政策,例如对答应的进程数量设置硬性限制或限制进程可以持续缓存的时长。
2.4 应用只能终止自己的背景进程
从 Android 14 开始,当您的应用调用
killBackgroundProcesses() 时,该 API 只能终止您自己应用的背景进程。
假如您传入另一个应用的软件包名称,此方法对该应用的背景进程没有影响,
并且 Logcat 中会表现:Invalid packageName: com.example.anotherapp
2.5 最低可安装的目的API级别
基于安全性 方面的优化 ,从Android 14 开始 targetSdkVersion < 23 的应用无法安装。
Android 6.0 Marshmallow(API 级别 23)引入了运行时权限,必要动态申请权限,让用户选择是否同意,部门流氓软件会把 targetSdkVersion 设置为22,绕过此束缚。
低于 23 的应用安装时会提示:INSTALL_FAILED_DEPRECATED_SDK_VERSION: App package must target at least SDK version 23, but found 7
调试低版本的app 可以使用命令行来安装:
adb install --bypass-low-target-sdk-block xxxxxx.apk
2.6 用户可关闭不可关闭通知
向用户表现不可关闭的前台通知,从Android 14 已答应用户关闭此类通知
这项变动适用于通过 Notification.Builder#setOngoing(true) 或NotificationCompat.Builder#setOngoing(true) 设置 Notification.FLAG_ONGOING_EVENT 来制止用户关闭前台通知的应用。FLAG_ONGOING_EVENT 的举动已发生变化,使用户实际上能够关闭此类通知。
在以下情况下,此类通知仍不可关闭:
- 当手机处于锁定状态时
- 假如用户选择全部清除通知操作(有助于防止意外关闭)
别的,这一新举动不适用于以下用例中的不可关闭通知:
- 使用 MediaStyle 创建的通知(notification.setStyle(ew NotificationCompat.MediaStyle()))
- 安全和隐私用例的政策限制使用
- 企业设备政策控制器 (DPC) 和支持软件包
三、 targetSdk >= 34的变动
3.1 启动前台服务必须设置前台服务类型
假如有使用 startForeground() 在清单文件中必须要指定服务的前台类型,Android 10 里面 引入了android:foregroundServiceType 属性,用以资助开发者更有目的地定义面向用户的前台服务。
假如应用以 Android 14 为目的平台,则必须指定适当的前台服务类型。与从前的 Android 版本一样,可组合使用多个类型。下面列出了可供选择的前台服务类型:
- camera
- connectedDevice
- dataSync
- health
- location
- mediaPlayback
- mediaProjection
- microphone
- phoneCall
- remoteMessaging
- shortService
- specialUse
- systemExempted
Android 14 中新增了 health, remoteMessaging, shortService, specialUse 和 systemExempted 类型。
以下是清单中的前台服务类型声昭示例:
<manifest ...> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" /> <application ...> <service android:name=".MyMediaPlaybackService" android:foregroundServiceType="mediaPlayback" android:exported="false"> </service> </application> </manifest>
假如以 Android 14 为目的平台的应用未在清单中定义给定服务的类型,系统会在调用 startForeground() 时引发 MissingForegroundServiceTypeException。
3.2 OpenJDK 17更新
Android 14 将继续更新 Android 的核心库,以与最新 OpenJDK LTS 版本中的功能保持一致,包罗适合应用和平台开发者的库更新和 Java 17 语言支持。
以下变动大概会影响应用兼容性:
- 对正则表达式的更改:如今,为了更严格地遵照 OpenJDK 的语义,不答应无效的组引用。您大概会看到
java.util.regex.Matcher 类抛出 IllegalArgumentException 的新情况,因此请务必测试应用中使用正则表达式的情况。如需在测试期间启用或停用此变动,请使用兼容性框架工具切换 DISALLOW_INVALID_GROUP_REFERENCE 标志。
java.util.UUID.fromString() 方法会执行更严格的检查,因此大概会在反序列化期间看到 IllegalArgumentException。如需在测试期间启用或停用此变动,请使用兼容性框架工具切换 ENABLE_STRICT_VALIDATION 标志。
- ProGuard 问题:有时,在您尝试使用 ProGuard 缩减、混淆和优化应用时,添加
java.lang.ClassValue 类会导致问题。问题源自 Kotlin 库,该库会根据 Class.forName("java.lang.ClassValue") 是否会返回类更改运行时举动。假如应用是根据没有 java.lang.ClassValue 类的旧版运行时开发的,则这些优化大概会将 computeValue 方法从派生自 java.lang.ClassValue 的类中移除。
3.3 JobScheduler 增强回调和网络举动
自引入以来,JobScheduler 会预期您的应用在几秒内从 onStartJob 或 onStopJob 返回。在 Android 14 之前,假如作业运行时间太长,则会静默制止并失败。假如您的应用以 Android 14 或更高版本为目的平台且在主线程上超出了授权的时间,应用会触发 ANR,并表现错误消息“对 onStartJob 没有响应”或“对 onStopJob 没有响应”。请考虑迁移到 WorkManager,该版本可支持异步处理,或将所有繁重工作迁移到背景线程。
JobScheduler 使用时 ,假如使用 setRequiredNetworkType 或 setRequiredNetwork 束缚条件,则必要声明 ACCESS_NETWORK_STATE 权限。假如未声明 ACCESS_NETWORK_STATE 权限,并且以 Android 14 或更高版本为目的平台,则会导致 SecurityException。
3.4 对隐式intent和待处理intent的限制
对于以 Android 14 或更高版本为目的平台的应用,Android 会通过以下方式限制应用向内部应用组件发送隐式 intent:
- 隐式 intent 只能传送到导出的组件。应用必须使用显式 intent 传送到未导出的组件,或将该组件标记为已导出。
- 假如应用通过未指定组件或软件包的 intent 创建可变待处理 intent,系统会抛出异常。
这些变动可防止恶意应用拦截意在供应用内部组件使用的隐式 intent。
AndroidManifest.xml 声明如下:
- <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>
复制代码 使用隐式跳转:会抛出异常
- context.startActivity(new Intent("com.example.action.APP_ACTION"));
复制代码 必要指定包名:
- Intent explicitIntent = new Intent("com.example.action.APP_ACTION")
- explicitIntent.setPackage(context.getPackageName());
- context.startActivity(explicitIntent);
复制代码 3.5 在运行时注册的广播接收器必须指定导出举动
以 Android 14 或更高版本使用 Context#registerReceiver() 动态注册广播接收器 ,必要设置导出标记: RECEIVER_EXPORTED 或 RECEIVER_NOT_EXPORTED。
此要求有助于掩护应用免受安全毛病的影响。
注册系统广播时,不用指定标志。
3.6 安全的动态代码加载
应用以 Android 14(API 级别 34)或更高版本为目的平台,并使用动态代码加载 (DCL) 功能,则必须将所有动态加载的文件标记为只读,
假如必须动态加载代码,请使用以下方法,在动态文件(例如 DEX、JAR 或 APK 文件)打开并写入任何内容之前立刻将其设为只读:
- private void testDcl(File jar){
- try (FileOutputStream os = new FileOutputStream(jar)) {
- // Set the file to read-only first to prevent race conditions
- boolean b = jar.setReadOnly();
- // Then write the actual file content
- } catch (IOException e) { ... }
- PathClassLoader cl = new PathClassLoader(jar, parentClassLoader);
- }
复制代码 插件化/热更新等涉及到 这些操作的会受到影响,新下载的文件属性修改成只读文件,假如是已存在的文件最好先删除然后重新下载并且设置只读权限
3.7 针对从背景启动Activity的其他限制
https://developer.android.google.cn/guide/components/activities/background-starts
对于以 Android 14(API 级别 34)或更高版本为目的平台的应用,系统会进一步限制答应应用何时从背景启动 activity:
PendingIntent#send() 或类似方法发送 PendingIntent 时,假如它想要授予自己的背景 activity 启动待处理 intent 的启动特权,则必须选择启用。则该应用如今必须选择加入一个 ActivityOptions,具体为带有 setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
bindService() 方法绑定另一个背景应用的服务时,假如可见应用想要授予自己的背景 activity 对绑定服务的启动特权,则应用应在调用 bindService() 方法时包罗 BIND_ALLOW_ACTIVITY_STARTS 标志
3.8 压缩路径遍历
对于以 Android 14(API 级别 34)或更高版本为目的平台的应用,在遍历 ZIP 文件时,假如 Zip 文件名称包罗“..”或以“/”开头,在使用 ZipFile(String) 和 ZipInputStream.getNextEntry() 时会抛出 ZipException
应用可以通过调用 dalvik.system.ZipPathValidator.clearCallback() 选择停用此验证。
3.9 每个MediaProjection拍摄会话均必要征得用户同意
对于以 Android 14(API 级别 34)或更高版本为目的平台的应用,在以下任一情况下,MediaProjection#createVirtualDisplay 会抛出 SecurityException
- 应用会缓存从 MediaProjectionManager#createScreenCaptureIntent 返回的 Intent,并将其多次传递给 MediaProjectionManager#getMediaProjection。
- 在同一 MediaProjection 实例上多次调用 MediaProjection#createVirtualDisplay。
应用必须在每次捕获会话之前征求用户同意。单次拍摄会话是指对 MediaProjection#createVirtualDisplay 的单次调用,且每个 MediaProjection 实例只能使用一次。
假如应用必要调用 MediaProjection#createVirtualDisplay 来处理配置更改(例如屏幕方向或屏幕尺寸更改),可以按照以下步调更新现有 MediaProjection 实例的 VirtualDisplay:
- 使用新的宽度和高度调用 VirtualDisplay#resize。
- 为 VirtualDisplay#setSurface 提供具有新宽度和高度的新 Surface。
3.10 安全的全屏intent通知
对于以 Android 14(API 级别 34)或更高版本为目的平台的应用,只有提供通话和闹钟的应用才华使用 USE_FULL_SCREEN_INTENT 权限支持全屏 intent 通知。
四、新增/改善 功能
4.1 截屏监听
Android 14 引入了掩护护隐私的屏幕截图检测 API,可以在Activity 里面注册回调,在Activity 可见时,截屏会有对应的回调消息返回。操作步调如下:
- <uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />
复制代码
- final Activity.ScreenCaptureCallback screenCaptureCallback = new Activity.ScreenCaptureCallback() {
- @Override
- public void onScreenCaptured() {
- // Add logic to take action in your app.
- }
- };
-
- @Override
- protected void onStart() {
- super.onStart();
- registerScreenCaptureCallback(executor, screenCaptureCallback);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- unregisterScreenCaptureCallback(screenCaptureCallback);
- }
复制代码 禁止当前ACtivity截屏可以添加下面的flag
- activity.getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
复制代码 4.2 路径可查询和插值
Android 的 Path API 是一种强大且机动的机制,可用于创建和渲染矢量图形,能够描边或添补路径,根据线段、二次曲线或立方曲线构建路径,执行布尔运算以获取更复杂的形状,或同时执行所有这些操作。但是无法找出 Path 对象中实际包罗的内容;该对象的内部信息在创建后对于调用方是不透明的。
如需创建 Path,可以调用moveTo()、lineTo()和 cubicTo() 等方法来添加路径片段。但无法询问该路径有哪些段,因此必须在创建时保存该信息。
从 Android 14 开始,可以查询路径以了解其内部内容。首先使用 Path.getPathIterator API 获取 PathIterator:
- Path path = new Path();
- path.moveTo(1.0F, 1.0F);
- path.lineTo(2.0F, 2.0F);
- path.close();
- PathIterator pathIterator = path.getPathIterator();
复制代码 接下来,调用 PathIterator 逐个遍历片段,并检索每个片段的所有必要数据。以下示例使用了 PathIterator.Segment 对象,它会打包数据:
- while (pathIterator.hasNext()) {
- PathIterator.Segment segment = pathIterator.next();
- Log.i(LOG_TAG, "segment: " + segment.getVerb() + ", " + segment.getPoints());
- }
复制代码 PathIterator 还有一个非分配版 next(),您可以在其中传入缓冲区来保存点数据。
查询 Path 数据的一个重要用例是插值。例如,在两个不同的路径之间添加动画(或变形)。为了进一步简化该用例,Android 14 在 Path 中添加了 interpolate() 方法。假设两个路径具有雷同的内部布局,interpolate() 方法会使用该插值效果创建一个新的 Path。以下示例返回了形状介于 path 和 otherPath 之间的一半(线性插值为 0 .5)的路径:
- Path interpolatedResult = new Path();
- if (path.isInterpolatable(otherPath)) {
- path.interpolate(otherPath, 0.5F, interpolatedResult);
- }
复制代码 4.3 各应用语言偏好设定
Android 14 扩展了 Android 13(API 级别 33)中引入的按应用设定语言功能,并包罗以下额外功能:
从 Android Studio Giraffe Canary 7 和 AGP 8.1.0-alpha07 开始,您可以将应用配置为自动支持各应用语言偏好设定。Android Gradle 插件会根据您的项目资源生成 LocaleConfig 文件,并在最终清单文件中添加对该文件的引用,如许您就不再必要手动创建或更新该文件。AGP 使用应用模块的 res 文件夹中的资源以及任何库模块依赖项来确定要在 LocaleConfig 文件中添加的语言地区。
使用 LocaleManager 方法中的 setOverrideLocaleConfig() 和 getOverrideLocaleConfig() 可以在设备的系统设置中动态更新应用的受支持语言列表。有了这种机动性,您可以按地区自定义支持的语言列表、运行 A/B 实验,大概假如您的应用通过服务器端推送进行当地化,则可以提供更新后的语言地区列表。
IME 可以使用 getApplicationLocales() 方法查看当前应用的语言,并将 IME 语言与该语言进行匹配。
4.4 新增唤醒屏幕权限
Android 14 引入了 android.permision.TURN_SCREEN_ON 权限,目的平台为Android 14 及以上的应用使用唤醒屏幕时,必要在AndroidManifest文件中配置这个权限。
别的唤醒屏幕权限有一个对应的 appops 权限 AppOpsManager.OP_TURN_SCREEN_ON,这个权限在Android T上是默认开启,在Android U上对目的平台为Android 14及以上的应用默认关闭。
不申请权限调用下面API 无法唤醒屏幕
- PowerManager powerManager = (PowerManager) Context.getSystemService(
- Context.POWER_SERVICE);
- PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
- PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "testName");
- wakeLock.acquire(3000)
复制代码
本文是早期转载其他作者总结的内容,但具体链接不记得了,有知道的话可以评论贴一下~
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |