Android 12(API 31)于2021年10月4日正式发布,正式版源代码也于当日被推送到AOSP Android开源项目。截止到笔者撰写这篇文章时,国内各终端厂商的在售Android设备,已经逐步开启了Android 12正式版本的更新。当前,对于Android应用开发者来说,Android 12 的软件兼容适配已迫在眉睫。
对于 Android 12 的兼容适配,主要分为两类:一类默认影响所有运行的应用,另一类则只对声明 targetSdkVersion 31 的应用产生影响。
对于Android 12 的适配点,这里按照以下几个方面进行了归纳:
SplashScreen(影响所有应用);android:exported:android:exported(以Android12位目标平台的应用);精确闹钟:Alarm精确闹钟 需申请SCHEDULE_EXACT_ALARM权限(以Android12位目标平台的应用);通知栏布局样式再次调整(以Android12位目标平台的应用);精确位置:ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 权限(以Android12位目标平台的应用);禁止从后台启动前台服务(以Android12位目标平台的应用);不再需要申请设备位置信息相关权限(以Android12位目标平台的应用);官方文档描述:https://developer.android.google.cn/about/versions/12
(Android 启动页 SplashScreen:影响所有应用)
从 Android 12 开始,系统会在应用的冷启动和暖启动时,使用新的启动页 SplashScreen,该启动页默认由应用ICON + 应用主题的windowBackground内容构成。

影响在 Andorid 12 设备上运行的所有应用
SplashScreen相关API的引入影响在Andorid 12设备上运行的所有应用。对于应用开发者来说,无论你的应用targetSdkVersion 版本是多少,均需要进行SplashScreen的适配工作。
若未进行 SplashScreen 的适配工作
若开发者未进行SplashScreen的适配工作,当应用运行于Android 12及以上版本的设备,在应用的冷启动 或 温启动时:
SplashScreen 自定义与案例代码:
新的启动页中的显示元素可完全由由开发者自定义,官方建议开发者:将未适配Android12前前的应用启动页完全移除,并适配Android12新的启动页,从而避免启动页重复、减少加载时间的问题。
关于 SplashScreen 适配相关API的详细案例代码和API使用说明请参考文章:
Android 12 适配指南——SplashScreen
https://xiaxl.blog.csdn.net/article/details/123522277
(显示声明 android:exported:影响以Android 12为目标平台的应用「targetSdkVersion 31」)
从 Andorid 12 开始,当您的应用程序将目标版本设置为31或更高版本(targetSdkVersion 31)时,若应用程序组件(Activity、Service、Receiver、Provider)在配置清单manifest中未显示声明 android:exported 属性,则在进行应用开发或打包时,将会出现如下错误提示:
As of Android 12, android:exported must be set; use true to make the activity available to other apps, and false otherwise. For launcher activities, this should be set to true.
对于这一点的更改,官方描述如下图所示:

android:exported = true的作用?
当应用程序组件,需要被另一个应用(Application)的组件启动或调用时:true 允许调用;false 不允许其他应用启动或调用。例如:在Activity中用来标示:当前Activity是否可以被另一个Application的组件启动;
因此,在Android 12中需显示声明 android:exported 属性,举例如下:
// launcher Activity 需将exported设置为true
<activity
android:name=".SplashActivity"
android:exported="true"
android:theme="@style/Theme.SplashScreen.Demo">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
// 非launcher Activity 又无外部启动需求设置为fase
<activity
android:name=".MainActivity"
android:exported="false">
</activity>
(Alarm精确闹钟:影响以Android 12为目标平台的应用「targetSdkVersion 31」)
从 Andorid 12 开始,当您的应用程序将目标版本设置为31或更高版本(targetSdkVersion 31)时,若您的应用程序需要使用精确闹钟,需申请一个新的权限(闹钟和提醒权限),该权限为普通权限,无需动态申请:
<!--Android S alarm permission-->
<!--普通权限:无需动态申请-->
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
对于这一点的更改,官方描述如下图所示:

添加该权限的原因是:Android官方为了节省系统资源,希望应用开发者尽可能将应用调整为不再需要使用精确闹钟的状态,从而减少应用闹钟对操作系统的频繁唤醒。

(Notification通知栏:影响以Android 12为目标平台的应用「targetSdkVersion 31」)
从 Andorid 12 开始,系统再次更改了自定义通知栏的布局方式和样式。
系统会提供标准模板,此模板可确保自定义通知栏在所有状态下效果保持一致。
Android 12开始,系统提供Notification.DecoratedCustomViewStyle通知栏样式,用于展示与构建收起与展开状态的通知栏样式。
标准模板自定义通知栏的展示样式,如下图所示:

标准通知栏的收起状态:

custom-collapsed-view.jpg
标准通知栏的展开状态:

相关代码的使用方式如下:
// Get the layouts to use in the custom notification
val notificationSmallLayout = RemoteViews(packageName, R.layout.notification_small)
val notificationLargeLayoutExpanded = RemoteViews(packageName, R.layout.notification_large)
// Apply the layouts to the notification
val customNotification = NotificationCompat.Builder(context, channelId)
// icon
.setSmallIcon(R.drawable.ic_launcher)
// style
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
// 设置收起后通知布局
.setCustomContentView(notificationSmallLayout)
// 设置展后的通知布局
.setCustomBigContentView(notificationLargeLayoutExpanded)
.build()
notificationManager.notify(1, customNotification);
注:通知的背景颜色可能会因设备和系统版本而有所差异。因此,开始在在自定义布局中建议对文本使用Style:TextAppearance_Compat_Notification,对标题使用Style: TextAppearance_Compat_Notification_Title。以上样式会适应系统的颜色变化,不会出现黑色文本采用黑色背景或白色文本采用白色背景的情况。
举例如下:
<TextView
android:id="@+id/notification_title"
style="@style/TextAppearance.Compat.Notification.Title"
android:layout_width="match_parent"
android:layout_height="48dp"
android:text="notification_small" />
通知栏 相关官方文档参考:
Android 12 中的兼容性变更:
https://mp.weixin.qq.com/s/ek2UT0vauTeVQQF0K5fkSQ
Android 12 行为变更——自定义通知:
https://developer.android.google.cn/about/versions/12/behavior-changes-12?hl=zh-cn
developer自定义通知栏:
https://developer.android.google.cn/training/notify-user/custom-notification?hl=zh-cn#kotlin
(精确位置:影响以Android 12为目标平台的应用「targetSdkVersion 31」)
从 Andorid 12 开始,当您的应用程序将目标版本设置为31或更高版本(targetSdkVersion 31)时,若应用程序请求设备的精确位置,需同时请求 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 权限。
发出精确位置申请后,用户侧设备将弹出动态授权申请弹窗:

若开发者只请求ACCESS_FINE_LOCATION权限,将弹出以下错误提示:
ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION.
精确位置 相关官方文档参考:
developer位置授权:
https://developer.android.google.cn/training/location/permissions?hl=zh-cn#approximate-request
Android 12行为变更——大致位置:
https://developer.android.google.cn/about/versions/12/behavior-changes-12?hl=zh-cn
(前台服务:影响以Android 12为目标平台的应用「targetSdkVersion 31」)
从 Andorid 12 开始,当您的应用程序将目标版本设置为31或更高版本(targetSdkVersion 31)时,将禁止从后台启动前台服务,并对启动前台服务作了限制。
调整后,以下情况可启动前台服务:
(蓝牙权限:影响以Android 12为目标平台的应用「targetSdkVersion 31」)
Android 12 引入了 BLUETOOTH_SCAN、BLUETOOTH_ADVERTISE 和 BLUETOOTH_CONNECT 权限。这些权限可让以 Android 应用更轻松地与蓝牙设备互动,不再需要申请设备位置信息相关权限。
Android 12 开始,Google官方将蓝牙扫描与位置权限进行了分离,因为官方发现:在隐私层面上,很难向终端用户解释位置权限与蓝牙的关系。
Android developer:Andoid12
https://developer.android.google.cn/about/versions/12?hl=zh-cn
Android开发者:Android 12 正式发布
https://mp.weixin.qq.com/s/OiFSWEnc-0N2z7JYWTJluw
AOSP:Android 开源项目
https://source.android.google.cn/
Material You:
https://material.io/blog/announcing-material-you
Material 设计组件:
https://github.com/material-components/material-components-android/releases
androidx releases core:
https://developer.android.com/jetpack/androidx/releases/core?hl=zh-cn
文章首发于公众号”CODING技术小馆“,如果文章对您有帮助,欢迎关注我的公众号。

最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
我安装了ruby、yeoman,当我运行我的项目时,出现了这个错误:Warning:Running"compass:dist"(compass)taskWarning:YouneedtohaveRubyandCompassinstalledthistasktowork.Moreinfo:https://github.com/gruUse--forcetocontinue.Use--forcetocontinue.我有进入可变session目标的路径,但它不起作用。谁能帮帮我? 最佳答案 我必须运行这个:geminstallcom
深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG
文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景 最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。 在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记
这个问题在这里已经有了答案:Unabletoinstallgem-Failedtobuildgemnativeextension-cannotloadsuchfile--mkmf(LoadError)(17个答案)关闭9年前。嘿,我正在尝试在一台新的ubuntu机器上安装rails。我安装了ruby和rvm,但出现“无法构建gemnative扩展”错误。这是什么意思?$sudogeminstallrails-v3.2.9(没有sudo表示我没有权限)然后它会输出很多“获取”命令,最终会出现这个错误:Buildingnativeextensions.Thiscouldtakeawhi
我不是Ruby专家,但想弄清楚发生了什么,因为我试图让指南针在节点应用程序中工作,但我的Ruby似乎坏了。打字:ruby--version让我:ruby2.1.1p76(2014-02-24revision45161)[x86_64-darwin13.0]我安装了Homebrew,之前遇到过Ruby版本的问题,但它似乎已安装并且可以正常工作。但是,当我使用gem输入请求时,出现此错误:$gem-hErrorloadingRubyGemsplugin"/Users/user_dir/.rvm/gems/ruby-2.1.1@global/gems/executable-hooks-1.3
我想知道如何从Apple.p12文件中提取key。根据我有限的理解,.p12文件是X504证书和私钥的组合。我看到我遇到的每个.p12文件都有一个X504证书和至少一个key,在某些情况下有两个key。这是因为每个.p12都有一个Apple开发人员key,有些还有一个额外的key(可能是Appleroot授权key)。我只考虑那些具有两个key的.p12文件是有效的。我的目标是区分具有一个key的.p12文件和具有两个key的.p12文件。到目前为止,我已经使用OpenSSL来检查X504文件和任何.p12的key。例如,我有这段代码可以检查目录中的所有.p12文件:Dir.glob(
一些我找到的选项是ActiveCouchCouchRESTCouchPotatoRelaxDBcouch_foo我更喜欢GitHub上的项目,因为这让我更容易fork和推送修复。所有这些都符合该要求。我习惯了Rails,所以我喜欢像ActiveRecord模型一样工作的东西。另一方面,我也不希望我和Couch之间太多--毕竟我使用它作为我的数据库是有原因的。最后,它们似乎都得到了相当积极的维护(couch_foo可能是个异常(exception))。所以我想这归结为(不可否认和不幸的)主观:有没有人对他们有过好的或坏的经历? 最佳答案
我尝试用Ruby设计一个基于Web的应用程序。我开发了一个简单的核心应用程序,在没有框架和数据库的情况下在六边形架构中实现DCI范例。核心六边形中有小六边形和网络,数据库,日志等适配器。每个六边形都在没有数据库和框架的情况下自行运行。在这种方法中,我如何提供与数据库模型和实体类的关系作为独立于数据库的关系。我想在将来将框架从Rails更改为Sinatra或数据库。事实上,我如何在这个核心Hexagon中实现完全隔离的rails和mongodb的数据库适配器或框架适配器。有什么想法吗? 最佳答案 ROM呢?(Ruby对象映射器)。还有
我的迁移看起来像这样classCreateQuestionings现在,当我运行$rakedb:migrate:reset时,在我的db/schema.rb中看不到限制:create_table"questionings",force::cascadedo|t|t.text"body",null:falseend我做错了吗还是这是一个错误?顺便说一下,我使用的是rails5.0.0.beta3和ruby2.3.0p0。 最佳答案 t.text在PostgreSQL和textdoesn'tallowforsizelimits中生成