
Android 13(API 33)于 2022年8月15日 正式发布(发布时间较往年早了一些),正式版Release源代码也于当日被推送到AOSP Android开源项目。

截止到笔者撰写这篇文章时,国内部分应用软件开发厂商已逐步接到手机厂商(华米OV等)的新版本适配要求。当前,对于Android应用开发者来说,Android 13 的软件兼容适配已需提上工作日程。
为了贴合这篇文章的标题,本篇文章结合Android Developer官方文档,围绕Android13适配点与Android13新特性两个方面进行详细说明。
适配点:
READ_EXTERNAL_STORAGE 细分为IAMGES、VIDEO、AUDIO权限若设置 targetSdk>=33 则此项必需适配!)setAppCacheEnabled与setForceDark方法;若设置 targetSdk>=33 则此项必需适配!)静态广播时,需设置对其他应用的可见性若设置 targetSdk>=33 则此项必需适配!)POST_NOTIFICATIONS若设置 targetSdk>=33 则此项必需适配!)NEARBY_WIFI_DEVICES 运行时权限若设置 targetSdk>=33 则此项必需适配!)BODY_SENSORS_BACKGROUND 运行时权限若设置 targetSdk>=33 则此项必需适配!)新增内容隐藏API根据业务需求,选择性适配!)若设置 targetSdk>=33 则此项必需适配!)新特性:
前台服务管理器系统新特性无需适配!)从Android 13开始,以Android13(API 33+)为目标平台的应用,系统新增运行时权限READ_MEDIA_IAMGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO 替代原有的READ_EXTERNAL_STORAGE权限。
| 权限 | 权限说明 |
|---|---|
| READ_MEDIA_IAMGES | 图片权限 |
| READ_MEDIA_VIDEO | 视频权限 |
| READ_MEDIA_AUDIO | 音频权限 |

当应用升级到targetSdk>=33时:
READ_EXTERNAL_STORAGE权限的应用:系统将自动赋予对应的细化权限。READ_EXTERNAL_STORAGE权限:亲测系统将不会授予任何权限。细分媒体权限动态申请弹窗样式:
READ_MEDIA_IMAGES 和 READ_MEDIA_VIDEO 权限,系统将会提示如下权限弹窗:
READ_MEDIA_AUDIO 权限,系统将提示如下弹窗:
官方参考:
Android Developer 细分媒体权限:
https://developer.android.google.cn/about/versions/13/behavior-changes-13
从Android 13开始,以Android13(API 33+)为目标平台的应用,WebView存在以下方法与API调整:
WebSettings.setAppCacheEnabled() 方法废弃。WebSettings.setForceDark() 方法废弃。WebView 95+版本不再支持 setAppCacheEnabled

从Android 13开始以Android13(API 33+)为目标平台的应用,系统会根据应用的主题属性isLightTheme,自动设置WebView的浅色或深色主题样式(系统会根据 isLightTheme 来设置 prefers-color-scheme)。同时,开发者Webview设置主题样式相关API WebSettings.setForceDark() 方法将被废弃。
基于以上更改:
WebSettings.setAlgorithmicDarkeningAllowed()或WebSettingsCompat.setAlgorithmicDarkeningAllowed()方法。WebSettings.setForceDark()系统将提示错误:W/cr_WebSettings: setForceDark() is a no-op in an app with targetSdkVersion>=T
官方参考:
Android Developer 静态广播注册官方介绍:
https://developer.android.google.cn/about/versions/13/behavior-changes-13
从Android 13开始,以Android13(API 33+)为目标平台的应用,注册静态广播时,需设置对其他应用的可见性:
若对其他应用可见,广播注册时设置:Context.RECEIVER_EXPORTED若仅应用内使用,广播注册时设置:Context.RECEIVER_NOT_EXPORTEDprivate void registerTestReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction("com.xiaxl.test.action");
// api >= 33
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// 跨应用间使用
MainActivity.this.registerReceiver(mTestReceiver, filter, Context.RECEIVER_EXPORTED);
// 应用内使用
//MainActivity.this.registerReceiver(mTestReceiver, filter, Context.RECEIVER_EXPORTED);
}
// api <= 32
else {
MainActivity.this.registerReceiver(mTestReceiver, filter);
}
}
官方参考:
Android Developer 静态广播注册官方介绍:
https://developer.android.google.cn/about/versions/13/features#java
Android 13 引入了一种新的运行时通知权限:POST_NOTIFICATIONS。
POST_NOTIFICATIONS 权限级别被定义为dangerous 开发者使用该权限时需动态申请,等待用户主动授权:

Android13(API 33+)为目标平台的应用:android.permission.POST_NOTIFICATION,另一方面代码中需动态申请该通知栏权限。<!-- AndroidManifest权限声明 -->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xiaxl.test">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
</manifest>
// Java代码动态申请POST_NOTIFICATIONS权限
if (Build.VERSION.SDK_INT >= 33) {
int checkPermission =
ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.POST_NOTIFICATIONS);
if (checkPermission != PackageManager.PERMISSION_GRANTED) {
//动态申请
ActivityCompat.requestPermissions(MainActivity.this, new String[]{
Manifest.permission.POST_NOTIFICATIONS}, PERMISSION_REQUEST_CODE);
} else {
//showRecordNotification();
}
} else {
//showRecordNotification();
}
POST_NOTIFICATIONS 动态授权申请弹窗如下图所示:

Android12(API 32-)为目标平台的应用:API 32-为目标平台的应用,运行在Android13及以上设备中时,当应用第一次显示通知时,系统会自动弹出以下提示框,要求用户动态授权。
官方参考:
Android Developer 通知运行时权限官方介绍:
https://developer.android.google.cn/guide/topics/ui/notifiers/notification-permission
从Android 13开始,Android系统新增了NEARBY_WIFI_DEVICES权限,将原有的ACCESS_FINE_LOCATION权限 与 Wi-Fi能力使用进行了区分(避免早先开发者使用Wi-Fi能力时,需要请求用户位置权限,从而引起用户的歧义)。

从Android 13开始,开发者只要不通过Wi-Fi推导用户的物理位置将无需再请求 ACCESS_FINE_LOCATION 权限,同时官方总结了新增权限NEARBY_WIFI_DEVICES的如下使用场景:

官方参考:
Android Developer NEARBY_WIFI_DEVICES:
https://developer.android.google.cn/reference/android/Manifest.permission#NEARBY_WIFI_DEVICES
从Android 13(API 33)开始,Android剪切板新增了一项新API:
Android 13(API 33)开始,用户可以选择使用API PersistableBundle#(ClipDescription.EXTRA_IS_SENSITIVE, true)隐藏要复制到剪切板的用户账户、密码登敏感信息。
相关API使用举例如下:
private void addData2Clipboard() {
ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = ClipData.newPlainText("111111", "我是密码");
ClipDescription description = clipData.getDescription();
// 隐私内容:剪切板加密
PersistableBundle persistableBundle = new PersistableBundle();
if (Build.VERSION.SDK_INT >= 33) {
persistableBundle.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);
} else {
persistableBundle.putBoolean("android.content.extra.IS_SENSITIVE", true);
}
description.setExtras(persistableBundle);
// 剪切板添加加密内容
clipboardManager.setPrimaryClip(clipData);
}
不使用新API与使用新API隐藏敏感信息,剪切板前后对比如下所示:

从Android 13开始,以Android13(API 33+)为目标平台的应用,在后台访问身体传感器(例如心率、体温和血氧饱和度)时,除了需要请求现有的 BODY_SENSORS 权限外,还需要请求 BODY_SENSORS_BACKGROUND 权限。

官方参考:
Android Developer BODY_SENSORS_BACKGROUND:
https://developer.android.google.cn/reference/android/Manifest.permission#BODY_SENSORS_BACKGROUND
官方从 Android 9(API 级别 28)开始,逐步开始对应用使用的非 SDK 接口实施了限制。
如果你的APP通过引用非 SDK 接口或尝试使用反射或 JNI 来获取句柄,这些限制就会起作用。官方给出的解释是为了提升用户体验、降低应用崩溃风险。
官方给出了一个检测工具,下载地址:veridex
https://android.googlesource.com/platform/prebuilts/runtime/+archive/master/appcompat.tar.gz
veridex使用方法:
appcompat.sh --dex-file=apk.apk

以上截图中,blacklist、greylist、greylist-max-o、greylist-max-p含义如下:
官方参考:
Android Developer 非SDK接口限制:
https://developer.android.google.cn/guide/app-compatibility/restrictions-non-sdk-interfaces#test-for-non-sdk
从Android 13(API 33)开始,Android通知栏中新增了一项新特性:
用户可以选择在通知栏中通过“前台服务管理器”,对“正在运行的前台服务”进行停止操作。

Android Developer:Andoid13
https://developer.android.google.cn/about/versions/13
AOSP:Android13版本说明
https://source.android.google.cn/docs/setup/start/android-13-release
GoogleSource:Android13_r3
https://android.googlesource.com/platform/build/+/refs/tags/android-13.0.0_r4
文章首发于公众号”CODING技术小馆“,如果文章对您有帮助,欢迎关注我的公众号。
运行bundleinstall后出现此错误:Gem::Package::FormatError:nometadatafoundin/Users/jeanosorio/.rvm/gems/ruby-1.9.3-p286/cache/libv8-3.11.8.13-x86_64-darwin-12.gemAnerroroccurredwhileinstallinglibv8(3.11.8.13),andBundlercannotcontinue.Makesurethat`geminstalllibv8-v'3.11.8.13'`succeedsbeforebundling.我试试gemin
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
我已经通过提供MagickWand.h的路径尝试了一切,我安装了命令工具。谁能帮帮我?$geminstallrmagick-v2.13.1Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingrmagick:ERROR:Failedtobuildgemnativeextension./Users/ghazanfarali/.rvm/rubies/ruby-1.8.7-p357/bin/rubyextconf.rbcheckingforRubyversion>=1.8.5...yescheckingfor/
我安装了ruby、yeoman,当我运行我的项目时,出现了这个错误:Warning:Running"compass:dist"(compass)taskWarning:YouneedtohaveRubyandCompassinstalledthistasktowork.Moreinfo:https://github.com/gruUse--forcetocontinue.Use--forcetocontinue.我有进入可变session目标的路径,但它不起作用。谁能帮帮我? 最佳答案 我必须运行这个:geminstallcom
文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景 最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。 在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记
我不是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
一些我找到的选项是ActiveCouchCouchRESTCouchPotatoRelaxDBcouch_foo我更喜欢GitHub上的项目,因为这让我更容易fork和推送修复。所有这些都符合该要求。我习惯了Rails,所以我喜欢像ActiveRecord模型一样工作的东西。另一方面,我也不希望我和Couch之间太多--毕竟我使用它作为我的数据库是有原因的。最后,它们似乎都得到了相当积极的维护(couch_foo可能是个异常(exception))。所以我想这归结为(不可否认和不幸的)主观:有没有人对他们有过好的或坏的经历? 最佳答案
我尝试用Ruby设计一个基于Web的应用程序。我开发了一个简单的核心应用程序,在没有框架和数据库的情况下在六边形架构中实现DCI范例。核心六边形中有小六边形和网络,数据库,日志等适配器。每个六边形都在没有数据库和框架的情况下自行运行。在这种方法中,我如何提供与数据库模型和实体类的关系作为独立于数据库的关系。我想在将来将框架从Rails更改为Sinatra或数据库。事实上,我如何在这个核心Hexagon中实现完全隔离的rails和mongodb的数据库适配器或框架适配器。有什么想法吗? 最佳答案 ROM呢?(Ruby对象映射器)。还有
自从我将我的应用程序部署到heroku以来,在过去的几天里,我一直在断断续续地收到这个错误。它发生在我开始使用unicorn作为服务器之前和之后。有时我可以通过使用herokurunrakedb:migrate然后herokurestart让它恢复运行,但这只修复了几个小时,它又坏了。至于网页,它说“应用程序错误”。日志不是很有用,但每次发生此错误时都会显示以下内容:[2014-10-27T21:13:31.675956#2]ERROR--:worker=1PID:8timeout(16s>15s),killing[2014-10-27T21:13:31.731646#14]INFO-
我的迁移看起来像这样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中生成