赞
踩
ini
复制代码
准备Flamingo 或者最新Bate 版本的Android Studio 准备Android 14 的设备((https://developer.android.google.cn/about/versions/14/devices?hl=zh-cn)) gradle配置 classpath 'com.android.tools.build:gradle:8.0.0' distributionUrl=https://services.gradle.org/distributions/gradle-8.0.0-bin.zip 设置Android 14 SDK android { compileSdkPreview = "UpsideDownCake" ... defaultConfig { targetSdkPreview = "UpsideDownCake" } } 生成BuildConfig和AIDL 关联文件 buildFeatures { buildConfig = true aidl = true } R文件传递 android.nonTransitiveRClass=false View的id区分时使用Switc case 使用 if()else if() 替换 switch case 或者在Gradle.properties中添加android.nonFinalResIds=false 设置命名空间:删除Manifest下的package标签,将包名信息添加到gradle的android路径下 android { namespace = "com.xx.xx" } 项目中使用CompileOnly 编译的库需要在混淆文件中添加间接引用的类
对于以 Android 14 为目标平台的应用,Android 会通过以下方式限制应用向内部应用组件发送隐式 intent:
必须使用显式 intent 传送到未导出的组件
带包名的去跳转,或将该组件标记为已导出。
这些变更可防止恶意应用拦截意在供应用内部组件使用的隐式 intent。
ini
复制代码
<activity android:name=".AppActivity" android:exported="false"> //false 不可导出 true可导出 <intent-filter> <action android:name="com.example.action.APP_ACTION" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> Intent explicitIntent =new Intent("com.example.action.APP_ACTION") //跳转不可导出,需要设置包名 explicitIntent.setPackage(context.getPackageName()); context.startActivity(explicitIntent);
在 Android 14 上,运行时通过 Context#registerReceiver()
动态注册广播接收器,需要设置标记 RECEIVER_EXPORTED
或 RECEIVER_NOT_EXPORTED
,标识是否导出该广播,避免应用程序出现安全漏洞,如果注册的是系统广播,则不需要指定标记。
三方SDK兼容修改方式:
如果三方SDK适配困难可以先在Activity或者Application中复写广播注册方法,如果有未添加是否可导出标记可以手动添加上
less
复制代码
@Override public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter) { return registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED或者Context.RECEIVER_NOT_EXPORTED); } @Override public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter, int flags) { Intent intent=null; try { boolean flagExported = (flags & Context.RECEIVER_EXPORTED) != 0; boolean flagNotExported = (flags & Context.RECEIVER_NOT_EXPORTED) != 0; if(!flagExported && !flagNotExported){ intent = super.registerReceiver(receiver, filter, flags|Context.RECEIVER_EXPORTED或者Context.RECEIVER_NOT_EXPORTED); return intent; } intent = super.registerReceiver(receiver, filter,flag); } catch (Throwable e) { } return intent; } 。。。。。其他多参方法补上EXPORTED 参数
new DexClassLoad(x,x,x,)
DexFile.loadFile(x) 都会抛异常
在动态文件(例如 DEX、JAR 或 APK 文件)打开并写入任何内容之前立即将其设为只读,插件化、热修复涉及ClassLoad去加载代码的地方,如果文件有写权限会立即报错。
将新下载的文件属性修改成只读文件,如果是已存在的文件最好可以先删除然后重新下载并且设置只读权限。
scss
复制代码
public static void modifyFileOnlyRead(String apkPath) { if (Util.isAndroidU()) { try { File file = new File(apkPath); boolean b = file.setReadOnly(); if (file.canWrite()) { Runtime.getRuntime().exec("chmod 400 " + apkPath); } } catch (Exception e) { e.printStackTrace(); } } }
对于以 Android 14 为目标平台的应用,Android 会通过以下方式防止 Zip 路径遍历漏洞:如果 Zip 文件条目名称包含“..”或以“/”开头,ZipFile(String)
和 ZipInputStream.getNextEntry()
会抛出 ZipException
。
应用可以通过调用 dalvik.system.ZipPathValidator.clearCallback()
选择停用此验证。
系统进一步限制了应用在后台启动 Activity 的时间:
PendingIntent#send()
发送 PendingIntent
以及类似行为时,如果应用想要授予其自己的后台 service 启动权限以启动 pending intent,则该应用现在必须选择加入一个 ActivityOptions
,具体为带有 setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
bindService()
绑定另一个在后台运行的应用的服务时,如果该可见应用想要将其自己的后台 activity 启动权限授予绑定服务,则它现在必须选择加入 BIND_ALLOW_ACTIVITY_STARTS
标志。如果有使用startForeground() 在清单文件中必须要指定服务的前台类型,例如音频播放类的可以使用mediaPlayback
为了帮助开发者更有目的地定义面向用户的前台服务,Android 10 在 <service> 元素内引入了 android:foregroundServiceType
属性。
如果您的应用以 Android 14 为目标平台,则必须指定适当的前台服务类型。与以前的 Android 版本一样,可组合使用多个类型。下面列出了可供选择的前台服务类型:
如果应用中的用例与这些类型均不相关,强烈建议您迁移逻辑以使用 WorkManager 或用户发起的数据传输作业。
Android 14 中新增了 health, remoteMessaging, shortService, specialUse
和 systemExempted
类型。
以下代码段提供了一个清单中的前台服务类型声明示例:
ini
复制代码
<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
Android 14 将继续更新 Android 的核心库,以与最新 OpenJDK LTS 版本中的功能保持一致,包括适合应用和平台开发者的库更新和 Java 17 语言支持。
以下变更可能会影响应用兼容性:
java.util.regex.Matcher
类抛出 IllegalArgumentException
的新情况,因此请务必测试应用中使用正则表达式的情形
。如需在测试期间启用或停用此变更,请使用兼容性框架工具切换 DISALLOW_INVALID_GROUP_REFERENCE
标志。java.util.UUID.fromString()
方法会执行更严格的检查,因此您可能会在反序列化期间看到 IllegalArgumentException
。如需在测试期间启用或停用此变更,请使用兼容性框架工具切换 ENABLE_STRICT_VALIDATION
标志。java.lang.ClassValue
类会导致问题。问题源自 Kotlin 库,该库会根据 Class.forName("java.lang.ClassValue")
是否会返回类更改运行时行为。如果您的应用是根据没有 java.lang.ClassValue
类的旧版运行时开发的,则这些优化可能会将 computeValue
方法从派生自 java.lang.ClassValue
的类中移除。非SDK API 表 (官网下载文件)
使用 Lint工具检查
Android 14 开始 ,targetSdkVersion>=33的新安装用户 SCHEDULE_EXACT_ALARM
权限默认拒绝,在使用
setExact()
setExactAndAllowWhileIdle()
setAlarmClock()
时,APP会抛出异常,可在调用上述方法之前使用 canScheduleExactAlarms()
判断是否有闹钟权限,并且设置AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
监听前台广播并对其做出正确反应 ,系统会在用户授予权限时发送该广播。
三种种方式修改:
需要使用ACTION_REQUEST_SCHEDULE_EXACT_ALARM
这个Action
跳转系统页面去手动开启此权限
复制代码
public static void openAlarmPage(Context context){ //可定义广播监听 SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED 是否开启 Intent intent = new Intent(); intent.setAction(ACTION_REQUEST_SCHEDULE_EXACT_ALARM); context. startActivity(intent); }
Menifest申明<uses-permission
android:name
="android.permission.USE_EXACT_ALARM" />
这个普通权限不需要运行时申请,但是需要注意隐私声明
无权限时使用 这个api AlarmManager.setExact(x,x,OnAlarmListener
,x,x)在OnAlarmListenr中再次开启定时
复制代码
1. public void start () { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { alarmManager.setExact(xxx, xxx, "TAG", new AlarmManager.OnAlarmListener() { @Override public void onAlarm() { start(); } }, xx); } }
只授予所选中媒体文件的权限
针对Android 13 及以上用户 Android 14 以上新增的权限 READ_MEDIA_VISUAL_USER_SELECTED
仅允许授予选中媒体文件的访问权限。如需要访问所有媒体文件需要同步申请READ_MEDIA_IMAGES
和 READ_MEDIA_VIDEO
.
安全性,降低低版本权限问题导致APP数据泄露,升级TargetSdkVersion >=23
go
复制代码
INSTALL_FAILED_DEPRECATED_SDK_VERSION: App package must target at least SDK version 23, but found 7
如果需要调试低版本Target的APP可以使用命令行安装
css
复制代码
adb install --bypass-low-target-sdk-block app.apk
应用进入缓存状态(例如进入后台) 上下文注册的广播会加入队列,等待应用退出缓存状态时,会一次性将多个在缓存队列的广播一次性发送, 存在广播合并的情况, 例如监听屏幕开启/关闭/开启/关闭, 应用只能接受开启-关闭 中间的状态会丢失.,广播也可能由于系统原因会从缓存队列删除. 此项变更让广播接收变得不那么靠谱,可能会导致APP资源得不到销毁引起内存泄露
从 Android 14 开始,当您的应用调用 killBackgroundProcesses()
时,该 API 只能终止您自己应用的后台进程。(影响第三方杀进程的应用例如(360手机卫士))
这项变更适用于通过 Notification.Builder#setOngoing(true)
或 NotificationCompat.Builder#setOngoing(true)
设置 Notification.FLAG_ONGOING_EVENT
来阻止用户关闭前台通知的应用。FLAG_ONGOING_EVENT
的行为已发生变化,使用户实际上能够关闭此类通知。
在以下情况下,此类通知仍不可关闭:
如果用户选择
全部清除
通知操作
(有助于防止意外关闭)此外,这一新行为不适用于以下用例中的不可关闭通知:
使用 MediaStyle
创建的通知(notification.setStyle(ew NotificationCompat.MediaStyle()))
安全和隐私用例的政策限制使用
企业设备政策控制器 (DPC) 和支持软件包
添加权限: 可以监听截屏但是截屏文件还需要使用常规方法自己获取
typescript
复制代码
<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(); // Pass in the callback created in the previous step // and the intended callback executor (e.g. Activity s mainExecutor). registerScreenCaptureCallback(executor, screenCaptureCallback); } @Override protected void onStop() { super.onStop(); unregisterScreenCaptureCallback(screenCaptureCallback); }
禁止当前ACtivity截屏可以添加下面的flag
scss
复制代码
activity.getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
Android 的 Path
API 是一种强大且灵活的机制,可用于创建和渲染矢量图形,能够描边或填充路径,根据线段、二次曲线或立方曲线构建路径,执行布尔运算以获取更复杂的形状,或同时执行所有这些操作。但是无法了解 Path 对象中实际包含的内容;该对象的内部信息在创建后对于调用方是不透明的。
如需创建 Path
,可以调用 moveTo()
、lineTo()
和 cubicTo()
等方法来添加路径片段。但无法询问该路径有哪些片段,因此必须在创建时保留该信息。
从 Android 14 开始,可以查询路径以了解其内部内容。首先,需要使用 Path.getPathIterator
API 获取 PathIterator
对象:
lua
复制代码
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
对象,它会打包数据:
less
复制代码
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)的路径:
ini
复制代码
Path interpolatedResult = new Path(); if (path.isInterpolatable(otherPath)) { path.interpolate(otherPath, 0.5F, interpolatedResult); }
功能和 API 概览 | Android 开发者 | Android Developers (google.cn)
权限弹窗是会显示描述信息,需要在清单文件中添加
xml
复制代码
在应用的资源目录/etc/ASL/asl-locations.xml新增配置, <ASL-locations> <ASL package="com.xx.xx">【Path to ASL XML} </ASL> </ASL-locations>
Android 14 引入了android.permision.RUN_USER_INITIATED_JOBS权限,允许一个应用执行用户初始化Job权限,此权限可以被用手动关闭或者被系统撤销,应用需要targestsdk升级到U后来请求此权限
Android 14 引入了android.permision.TURN_SCREEN_ON权限,目标平台为Android 14及以上的应用使用唤醒屏幕时,需要在AndroidManifest文件中配置这个权限。另外唤醒屏幕权限有一个对应的appops权限AppOpsManager.OP_TURN_SCREEN_ON,这个权限在Android T上是默认开启,在Android U上对目标平台为Android 14及以上的应用默认关闭。
不申请权限调用下面API 没有效果无法唤醒屏幕
ini
复制代码
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)
功能和 API 概览 | Android 开发者 | Android Developers (google.cn)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。