Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Android 12 适配升级小结

Android 12 适配升级小结

作者头像
阿策小和尚
发布于 2022-08-30 07:21:01
发布于 2022-08-30 07:21:01
2.9K00
代码可运行
举报
文章被收录于专栏:阿策小和尚阿策小和尚
运行总次数:0
代码可运行

Android 12 发布已经有好几个月了,而且随着各大市场对应用适配的要求逐渐提高,和尚也尝试将一个历史的应用简单升级适配 Android 12

Android 12

Android 12 对应 Build.VERSION_CODES.S,使用 Material You 打造的全新系统界面,富有表现力、活力和个性。使用重新设计的微件、AppSearch、游戏模式和新的编解码器扩展您的应用。支持隐私信息中心和大致位置等新的保护功能。使用富媒体内容插入功能、更简便的模糊处理功能、经过改进的原生调试功能等提高工作效率。

Android 12 相对我们的历史项目来说属于较大版本的更新,在适配过程中遇到一系列问题,和尚简单记录整理一下。

SDK 版本号升级

和尚首先对 SDK 版本号进行升级,之后对升级后的应用逐步进行适配更新;

当前版本
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
minSdkVersion = 17
targetSdkVersion = 28
compileSdkVersion = 28
buildToolsVersion = '28.0.3'
升级后版本
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
minSdkVersion = 17
targetSdkVersion = 31
compileSdkVersion = 31
buildToolsVersion = '31.0.0'

Q1: Gradle 不匹配

升级 SDKsync 后遇到第一个 Gradle 不匹配问题;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Installed Build Tools revision 31.0.0 is corrupted. Remove and install again using the SDK Manager.

A1: 升级 Android 12 对应 Gradle 版本

历史版本 Gradle 对应版本是 3.3.3,升级到最新的 7.0.4

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
classpath 'com.android.tools.build:gradle:7.0.4'

Q2: distributionUrl 不匹配

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Caused by: org.gradle.api.internal.plugins.PluginApplicationException: Failed to apply plugin [id 'com.android.internal.version-check']
    at com.android.build.gradle.BasePlugin.apply(BasePlugin.kt:33)
    at com.android.build.gradle.LibraryPlugin.apply(LibraryPlugin.kt:26)
    at build_21d4k8dpcp55f408j9ar3yifm.run(/Users/user/Documents/workspace/App/adlibrary/build.gradle:1)
Caused by: java.lang.RuntimeException: Minimum supported Gradle version is 7.0.2. Current version is 6.1.1. If using the gradle wrapper, try editing the distributionUrl in /Users/user/Documents/workspace/App/gradle/wrapper/gradle-wrapper.properties to gradle-7.0.2-all.zip
    at com.android.build.gradle.internal.plugins.VersionCheckPlugin.apply(VersionCheckPlugin.kt:59)
    at com.android.build.gradle.internal.plugins.VersionCheckPlugin.apply(VersionCheckPlugin.kt:33)
    ...

A2: 升级 Android 12 对应 distributionUrl Gradle 版本

和尚将本地 gradle-wrapper.properties 中升级到与 classpath 一致的 7.0.2-all 即可;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip

Q3: Marven 仓库不支持 Http

和尚历史项目中引入了很多公司内部仓库和部分非 Https 的线上库,在 Gradle 升级后,Marven 仓库建议使用 Https 安全的仓库;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Could not resolve all dependencies for configuration ':classpath'.
   > Using insecure protocols with repositories, without explicit opt-in, is unsupported. Switch Maven repository 'maven(http://0.0.0.0:80/xxx/App)' to redirect to a secure protocol (like HTTPS) or allow insecure protocols. 
   See https://docs.gradle.org/7.0.2/dsl/org.gradle.api.artifacts.repositories.UrlArtifactRepository.html#org.gradle.api.artifacts.repositories.UrlArtifactRepository:allowInsecureProtocol for more details. 

A3: 升级 Https 线上库或解决安全警告

对于部分线上 Marven 仓库可以更新至 Https,对于不可更新的库可以通过添加 allowInsecureProtocol 属性解决 Gradle 仓库地址的不安全警告;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
repositories {
    maven {
      url "http://0.0.0.0:80/xxx/App"
      allowInsecureProtocol = true
    }
}

Q4: compile 弃用

和尚的历史项目中有个别 Module 中未及时修改 compile(),而 Gradle 升级之后已完全弃用 compile()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
A problem occurred evaluating project ':lib'.
> Could not find method compile() for arguments [directory 'libs'] on object of type
    org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

A4: 更新为 api 或 implementation

根据具体的业务需求将 compile() 更新为 api / implementation 即可;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
api fileTree(dir: 'libs', include: ['*.jar'])

Q5: Android 工程依赖的 Java 版本过低

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
A problem occurred evaluating project ':lib'.
> Failed to apply plugin 'com.android.internal.library'.
   > Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
     You can try some of the following options:
       - changing the IDE settings.
       - changing the JAVA_HOME environment variable.
       - changing `org.gradle.java.home` in `gradle.properties`.

A5: 更新 Android 依赖版本为 jdk 11.0.13

通过 AndroidStudio -> Preferences… -> Gradle 更新 jdk 版本即可;

Q6: AGCPluginTask 中 randomEncryptComponent 属性不应使用 @Optional 进行注释

和尚的历史项目中使用了 Huawei HMS 推送等,使用的 Marven 库版本较低,与升级后的 Gradle 不兼容;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':push:processDebugManifest'.
> A failure occurred while executing com.android.build.gradle.tasks.ProcessLibraryManifest$ProcessLibWorkAction
   > Manifest merger failed with multiple errors, see logs

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
==============================================================================

2: Task failed with an exception.
-----------
* What went wrong:
A problem was found with the configuration of task ':app:processDebugAGCPlugin' (type 'AGCPluginTask').
  - Type 'com.huawei.agconnect.agcp.AGCPluginTask' property 'randomEncryptComponent' of type boolean shouldn't be annotated with @Optional.

    Reason: Properties of primitive type cannot be optional.

    Possible solutions:
      1. Remove the @Optional annotation.
      2. Use the java.lang.Boolean type instead.

    Please refer to https://docs.gradle.org/7.0.2/userguide/validation_problems.html#cannot_use_optional_on_primitive_types for more details about this problem.

A6: 升级华为 HMS 库版本

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
classpath 'com.huawei.agconnect:agcp:1.5.2.300'

Q7: 使用 Intent 过滤器的 Service 需设置 exported 属性

此元素设置 Activity 是否可由其他应用的组件启动 —“true” 表示可以,“false” 表示不可以。若为 “false”,则 Activity 只能由同一应用的组件或使用同一用户 ID 的不同应用启动。 如果您使用的是 Intent 过滤器,则不应将此元素设置为 “false”。否则,在应用尝试调用 Activity 时,系统会抛出 ActivityNotFoundException 异常。相反,您不应为其设置 Intent 过滤器,以免其他应用调用 Activity

如果没有 Intent 过滤器,则此元素的默认值为 “false”。如果您将元素设置为 “true”,则任何知道其确切类名的应用均可访问 Activity,但在系统尝试匹配隐式 Intent 时,该 Activity 无法解析;

此属性并非是限制 Activity 向其他应用公开的唯一方式。您还可使用权限来限制哪些外部实体能够调用 Activity

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/.../src/main/AndroidManifest.xml Error:
    android:exported needs to be explicitly specified for <service>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. 
    See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.
/.../src/main/AndroidManifest.xml Error:
    android:exported needs to be explicitly specified for <service>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. 
    See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.

A7: 在所有 Module 中找到使用 Intent 过滤器的 Service 并按业务需求添加对应的 exported 属性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<service
    android:name="com.xxx.app.push.OPushMessageService"
    android:permission="com.coloros.mcs.permission.SEND_MCS_MESSAGE"
    android:exported="true">
  <intent-filter>
    <action android:name="com.coloros.mcs.action.RECEIVE_MCS_MESSAGE" />
  </intent-filter>
</service>

Q8: 使用 Intent 过滤器的 Receiver 需设置 exported 属性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/.../src/main/AndroidManifest.xml Error:
    android:exported needs to be explicitly specified for <receiver>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.
/.../src/main/AndroidManifest.xml Error:
    android:exported needs to be explicitly specified for <receiver>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.

A8: 在所有 Module 中找到使用 Intent 过滤器的 Receiver 并按业务需求添加对应的 exported 属性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<receiver android:name="com.xxx.app.SystemReceiver"
    android:exported="false">
  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    <action android:name="android.intent.action.USER_PRESENT" />
  </intent-filter>
  <intent-filter>
    <action android:name="android.intent.action.PACKAGE_REMOVED" />

    <data android:scheme="package" />
  </intent-filter>
</receiver>

Q9: 使用 Intent 过滤器的 Activity 需设置 exported 属性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/.../src/main/AndroidManifest.xml Error:
    android:exported needs to be explicitly specified for <activity>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.
/.../src/main/AndroidManifest.xml Error:
    android:exported needs to be explicitly specified for <activity>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.

A9: 在所有 Module 中找到使用 Intent 过滤器的 Activity 并按业务需求添加对应的 exported 属性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<activity
    android:name=".xxx.app.TestActivity"
    android:exported="false"
    android:theme="@style/Theme.notAnimation">
  <intent-filter>
    <action android:name="com.sogou.novel.reader.setting.clean" />

    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

Q10: PendingIntent 需声明可变性

Android 12 中创建 PendingIntent 的时候,需要显示的声明是否可变,请分别使用 PendingIntent.FLAG_MUTABLEPendingIntent.FLAG_IMMUTABLE 标志,如果您的应用试图在不设置任何可变标志的情况下创建 PendingIntent 对象,系统会抛出 IllegalArgumentException 异常;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PACKAGE_NAME: Targeting S+ (version 10000 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.

A10: 根据业务设置 PendingIntent 可变性

PendingIntent 是一个可以给另一个应用程序使用的 IntentPendingIntent 接收待处理意图的应用程序可以使用与产生待处理意图的应用程序相同的权限和身份执行待处理意图中指定的操作;

Adnroid 12 之前,默认创建一个 PendingIntent 它是可变的,因此其他恶意应用程序可能会拦截,重定向或修改此 Intent

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PendingIntent pendingIntent = PendingIntent.getBroadcast(getContext().getApplicationContext(), type, intent, PendingIntent.FLAG_IMMUTABLE);

W11: 避免使用 flatDirs 提醒

Gradle 升级之后,提示避免使用 flatDir 提醒,因该方式不支持任何元数据方式;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Using flatDir should be avoided because it doesn't support any meta-data formats.
Using flatDir2 should be avoided because it doesn't support any meta-data formats.

A11: 使用 jniLibs.srcDirs 方式引入 libs 库

Gradle 升级之后使用 jniLibs.srcDirs 方式替代 flatDirlibs 库引入,并更新 aar 引入方式;

当前版本
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
repositories {
    flatDir {
        dirs 'libs'
    }
}

implementation(name: 'test_name', ext: 'aar')
升级后版本
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
android {
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
}

implementation (files("libs/test_name.aar"))

W12: dexOptions 弃用提醒

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DSL element 'dexOptions' is obsolete and should be removed.
It will be removed in version 8.0 of the Android Gradle plugin.
Using it has no effect, and the AndroidGradle plugin optimizes dexing automatically.

A12: Gradle 升级后 dexOptions 已弃用,删除即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dexOptions {
    preDexLibraries = true
}

Tips:

和尚在测试过程中,明明代码中所有涉及 intent-filter 过滤器的 Activity / Service / Receiver 都已经设置了 exported 属性,但依旧提示使用 Intent 过滤器的 XX 需设置 exported 属性;其原因在于引入了各类三方 SDK,在引入的各类三方库中可以存在对应的未设置 exported 属性的 Activity / Service / Receiver,单独设置处理一下即可;


Android 12 的初步升级到此位置,还有很多特有的属性,和尚会在后续的适配中进行完善;如有错误,请多多指导!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 阿策小和尚 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Lottie 超酷炫动画效果,了解下?
说到动画效果,一般都会感到很高端,感觉很酷炫;而和尚技术有限,稍复杂的动画效果也需要很多时间处理,但是遇到时间紧任务重的情况该怎么办呢?那就尝试一下 Lottie 吧,酷炫的动画集成却相当简单,还支持跨平台。
阿策小和尚
2019/08/12
1.8K0
Lottie 超酷炫动画效果,了解下?
【源码分析】Lottie 实现炫酷动画背后的原理
自我在内网发布了一篇关于 Lottie 的重点原理分析的文章之后,就不断有同事来找我询问关于 Lottie 的各种东西,最近又有同事来问,就想着可能对大家也会有所帮助,就稍作处理后分享出来。
程序亦非猿
2019/08/16
2K0
【源码分析】Lottie 实现炫酷动画背后的原理
UWP 创建动画的极简方式 — LottieUWP
提到 UWP 中创建动画,第一个想到的大多都是 StoryBoard。因为 UWP 和 WPF 的界面都是基于 XAML 语言的,所以实现 StoryBoard 会非常方便。 来看一个简单的 StoryBoard 例子: <Page...> <Grid x:Name="grid"> <Grid.Resources> <Storyboard x:Key="demoStoryBoard" AutoReverse="True" RepeatBehavior="For
Shao Meng
2018/04/28
1.6K0
UWP 创建动画的极简方式 — LottieUWP
D10-Android自定义控件之动画篇2-动画监听
本篇接上一篇: AnimatorSet的使用,将多个Animator组合进行动画 动画的监听 ---- 一、AnimatorSet的使用 在此之前先看一下AnimatorSet、Animat
张风捷特烈
2018/09/29
4850
D10-Android自定义控件之动画篇2-动画监听
Android优化之Hardware Layer
项目中越来越多的动画,越来越多的效果导致了应用性能越来越低。该如何提升。 ###简介 在View播放动画的过程中每一帧都需要被重绘。如果使用view layers,就不用每帧都去重绘,因为View渲染一旦离开屏幕缓冲区就可以被重用。 而且,hardware layers会在GPU上缓存,这样就会让一些动画过程中的操作变得更快。通过hardware layers可以快速的渲染一些简单的转变(位移、选中、缩放、颜色渐变)。由于很多动画都是这些动作的结合,所以hardware layers可以显著的提高动
xiangzhihong
2018/01/26
7270
Android开发笔记(九十六)集合动画与属性动画
补间动画有四大类:透明度动画AlphaAnimation、旋转动画RotateAnimation、缩放动画ScaleAnimation、平移动画TranslateAnimation,而集合动画AnimationSet便是用来将几个补间动画组装起来。即在同一时刻,让某视图呈现出多种动画效果,如一边缩放一边旋转。 下面是AnimationSet的常用方法: addAnimation : 添加动画。 setFillAfter : 设置是否维持结束画面。true表示动画结束后停留在结束画面,false表示动画结束后恢复到开始画面。 setRepeatMode : 设置重播模式。RESTART表示从头开始,REVERSE表示倒过来开始。 setDuration : 设置动画的持续时间。 setStartTime : 设置动画的开始时间。Animation.START_ON_FIRST_FRAME表示当前时间,其他值表示转换为整型数的时间。一般无需调用该方法,默认就是立即开始播放。 setInterpolator : 设置动画的插值器。
aqi00
2019/01/18
9730
Android十八章:属性动画Android属性动画(第一话)
Android动画能给界面带来很炫的效果,如果我们要实现这些效果,在android3.0版本前实现动画主要有2种方式,帧动画和补间动画。
ppjun
2018/09/05
1.1K0
android代码实现ScaleAnimation[通俗易懂]
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.ScaleAnimation; import android.widget.ImageView;
全栈程序员站长
2022/11/03
4770
Lottie : 让动画如此简单
本文介绍了在Android开发中,使用Lottie动画库实现更高效、更简洁的动画效果,同时避免了XML布局的繁琐和冗余。通过实例展示了如何在Android应用中使用Lottie动画,并总结了一些关于Lottie动画在实际应用中的使用经验和技巧。
QQ音乐技术团队
2017/09/11
29.7K4
Lottie : 让动画如此简单
从零开始学Android自定义View之动画系列——属性动画(2)
独立的动画能够实现的视觉效果毕竟是相当有限的,因此将多个动画组合到一起播放就显得尤为重要。幸运的是,Android团队在设计属性动画的时候也充分考虑到了组合动画的功能,因此提供了一套非常丰富的API来让我们将多个动画组合到一起。 实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:
老马的编程之旅
2022/06/22
5290
从零开始学Android自定义View之动画系列——属性动画(2)
揭露动画实现时的注意事项(附上bug-logcat)
昨天晚上开始学一下这个揭露动画,准备用在项目中做一个转场,啃完了API之后开始写个小demo,距离跑成功一步之遥的当儿,出了个bug,就怎么点击按钮都没用。
凌川江雪
2018/12/07
7140
Android动画基础详析 | 属性动画基础及ValueAnimator
在上篇博客Android动画基础详析 | 概述、逐帧动画、视图动画(附诸多实际运行效果动图)的基础上我们新建一个property包和一个PropertyActivity:
凌川江雪
2019/09/30
1.5K0
Android动画基础详析 | 属性动画基础及ValueAnimator
自定义View(三)-动画-属性动画ValueAnimator
之前我们把视图动画(也就是View动画)分析的差不多了,当然帧动画我们没有讲解,其实帧动画比较简单,就是通过顺序播放一系列的图像从而产生动画效果,可以简单理解为图片的切换。和我们小时候玩的翻书让物体动起来是一个道理。它使用起来也比较简单。所以我们就不单独拿出来讲解。到后面我们会用到时再去简单讲解。这篇我们继续来学习动画之属性动画(Property Animator)。
g小志
2018/09/11
1.4K0
自定义View(三)-动画-属性动画ValueAnimator
Lottie内存泄漏问题的定位与分析
Lottie是Airbnb开源的跨平台动画库,支持iOS、Android、React Native 和 Web 等平台。它可以解析使用 Bodymovin 导出为 json 的 Adobe After Effects 动画,允许应用程序像使用静态图像一样轻松使用动画。
用户5521279
2020/07/07
7.1K0
Lottie内存泄漏问题的定位与分析
自定义View实战--实现一个清新美观的加载按钮
当时在心里问自己能不能做,答案肯定是能做的,不过我比较懒,觉得中间那个伸缩变化要编写很多代码,所以懒得理。后来,为了不让自己那么浮躁,也为了锻炼自己的耐心程度,还是坚持实现它了。这个过程,觉得自己还是有所收获,把握了一些想当然的细节,输理了对于自定义 View 的流程。
Frank909
2019/01/14
6070
Android自定义View-SVG动画
SVG是可缩放矢量图形,全称Scalable Vector Graphics。经过数学计算利用直线和曲线绘制而成,无论怎么放大,都不会出现马赛克现象。可以使用Illustrator矢量图绘图软件来进行绘图。
音视频开发进阶
2020/08/27
2.9K0
Android自定义View-SVG动画
相关推荐
Lottie 超酷炫动画效果,了解下?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验