Android14(U) Adaptation Guide

1. Upgrade the compilation environment

development environment

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

准备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 编译的库需要在混淆文件中添加间接引用的类

Modification of TargetSdkVersion >=34

Limitations on implicit intents and pending intents

For apps targeting Android 14, Android restricts apps from sending implicit intents to internal app components in the following ways:

  • Implicit intents can only be delivered to exported components. Apply必须使用显式 intent 传送到未导出的组件 with package name to jump, or将该组件标记为已导出。
  • The system now throws an exception if an app creates a mutable pending intent from an intent that does not specify a component or package.

These changes prevent malicious apps from intercepting implicit intents intended for components inside the app.

1

2

3

4

5

6

7

8

9

10

11

12

<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);

Broadcast receivers registered at runtime must specify export behavior

On Android 14, the runtime dynamically registers the broadcast receiver through Context#registerReceiver() and needs to set the flag RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED , identifies whether to export the broadcast to avoid security vulnerabilities in the application. If a system broadcast is registered, there is no need to specify a tag.

Third-party SDK compatible modification methods:

If it is difficult to adapt to the third-party SDK, you can first override the broadcast registration method in Activity or Application. If there is no exportable flag, you can add it manually.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

@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 参数

Secure dynamic code loading (plug-in/hot update)

new DexClassLoad(x,x,x,)
DexFile.loadFile(x) will throw an exception

Set dynamic files (such as DEX, JAR or APK files) to read-only immediately before they are opened and any content is written. Plug-inization and hot fixes involving ClassLoad to load code will immediately report an error if the file has write permissions.

Change the properties of the newly downloaded file to read-only. If it is an existing file, it is best to delete it first and then download it again and set the read-only permission.

1

2

3

4

5

6

7

8

9

10

11

12

13

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();

        }

    }

}

Compression path traversal

For apps targeting Android 14, Android prevents Zip path traversal vulnerabilities by: If the Zip file entry name contains ".." or begins with "/",ZipFile(String) and ZipInputStream.getNextEntry() will throw ZipException.

Applications can choose to disable this verification by calling dalvik.system.ZipPathValidator.clearCallback() .

Additional restrictions on starting an Activity from the background

The system further limits the time an app can start an activity in the background:

  • When an app uses PendingIntent#send() Send PendingIntent and similar behavior, if the app wants to grant its own background service launch permission to launch the pending intent, then The app must now opt-in to a ActivityOptions with setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
  • When a visible application uses bindService() to bind the service of another application running in the background, if the visible application wants to grant its own background activity launch permission to the bound service , it must now opt in with the BIND_ALLOW_ACTIVITY_STARTS flag.

To start the foreground service, you must set the foreground service type

If you usestartForeground() you must specify the foreground type of the service in the manifest file. For example, for audio playback, you can use mediaPlayback< /span>

To help developers more purposefully define user-facing front-end services, Android 10 is available in  The android:foregroundServiceType attribute is introduced in the <service> element. 

If your app targets Android 14, you must specify the appropriate front service type. As in previous Android versions, multiple types can be combined. Listed below are the types of front desk services to choose from:

If the use cases in your app are not related to any of these types, it is strongly recommended that you migrate your logic to use WorkManager or User-initiated data transfer job.

Android 14 中新增了 health, remoteMessaging, shortService, specialUse 和 systemExempted 类type.

The following code snippet provides an example of a front-end service type declaration in a manifest:

1

2

3

4

5

6

7

8

9

10

11

<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>

If an app targeting Android 14 does not define the type of a given service in the manifest, the system will call startForeground() triggered when MissingForegroundServiceTypeException

Open JDK 17

Android 14 will continue to update Android's core libraries to align with features in the latest OpenJDK LTS releases, including library updates and Java 17 language support for app and platform developers.

The following changes may affect app compatibility:

  • Changes to regular expressions: In order to more strictly follow the semantics of OpenJDK, invalid group references are now not allowed. You may see new cases where the java.util.regex.Matcher class throws IllegalArgumentException , so be sure to 测试应用中使用正则表达式的情形 . To enable or disable this change during testing, please use the Compatibility Framework Tooltoggle the DISALLOW_INVALID_GROUP_REFERENCE flag.
  • UUID handling: The java.util.UUID.fromString() method now performs stricter checks when validating input parameters, so you may encounter errors during deserialization See IllegalArgumentException. To enable or disable this change during testing, please use the Compatibility Framework Tooltoggle the ENABLE_STRICT_VALIDATION flag.
  • ProGuard issues: Sometimes adding java.lang.ClassValue classes can cause problems when you try to minify, obfuscate, and optimize your app using ProGuard. The problem stems from a Kotlin library that changes the runtime behavior depending on whether Class.forName("java.lang.ClassValue") returns a class. If your app is developed against an older runtime that does not have the java.lang.ClassValue class, these optimizations may cause the computeValue method to derive from java.lang.ClassValue removed from the class.

Updates to restrict non-SDK interfaces in Android 14

Non-SDK API table (Official website download file)

Use LintTool list

Modification of TargetSdkVersion >=33

Deny setting precise alarms by default

 Starting from Android 14, new installation users with targetSdkVersion>=33 SCHEDULE_EXACT_ALARM Permission is denied by default, in use

  • setExact()
  • setExactAndAllowWhileIdle()
  • setAlarmClock()

When , the APP will throw an exception, which can be used before calling the above method. canScheduleExactAlarms()

判断是否有闹钟权限,并且设置AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED 监听前台广播并对其做出正确反应 ,系统会在用户授予权限时发送该广播。

三种种方式修改:

1

2

3

4

5

6

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" />这个普通权限不需要运行时申请,但是需要注意隐私声明

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    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 .

TargetSdkVersion==xxx 不区分版本对所有应用的更改

TargetSdkVersion<23的应用无法在Android U上安装

安全性,降低低版本权限问题导致APP数据泄露,升级TargetSdkVersion >=23

1

INSTALL_FAILED_DEPRECATED_SDK_VERSION: App package must target at least SDK version 23, but found 7

如果需要调试低版本Target的APP可以使用命令行安装

1

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) 和支持软件包

新增、改善功能

截屏监听

添加权限: 可以监听截屏但是截屏文件还需要使用常规方法自己获取

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<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

1

activity.getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);

Path 路径可查询过程中的点位信息

Android 的 Path API 是一种强大且灵活的机制,可用于创建和渲染矢量图形,能够描边或填充路径,根据线段、二次曲线或立方曲线构建路径,执行布尔运算以获取更复杂的形状,或同时执行所有这些操作。但是无法了解 Path 对象中实际包含的内容;该对象的内部信息在创建后对于调用方是不透明的。

如需创建 Path,可以调用 moveTo()lineTo() 和 cubicTo() 等方法来添加路径片段。但无法询问该路径有哪些片段,因此必须在创建时保留该信息。

从 Android 14 开始,可以查询路径以了解其内部内容。首先,需要使用 Path.getPathIterator API 获取 PathIterator 对象:

1

2

3

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 对象,它会打包数据

1

2

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)的路径:

1

2

3

4

Path interpolatedResult = new Path();

if (path.isInterpolatable(otherPath)) {   

    path.interpolate(otherPath, 0.5F, interpolatedResult);

}

单应用语言偏好/语法优化/地区偏好

功能和 API 概览  |  Android 开发者  |  Android Developers (google.cn)

位置权限新增标签描述

权限弹窗是会显示描述信息,需要在清单文件中添加

1

2

3

4

在应用的资源目录/etc/ASL/asl-locations.xml新增配置,

<ASL-locations>

<ASL  package="com.xx.xx">【Path to ASL XML} </ASL>

</ASL-locations>

新增用户初始化Job权限RUN_USER_INITIATED_JOBS

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 没有效果无法唤醒屏幕

1

2

3

4

5

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)

字体放大可以到200%

功能和 API 概览  |  Android 开发者  |  Android Developers (google.cn)

Guess you like

Origin blog.csdn.net/qq_33209777/article/details/134119916