草庐IT

Android 13适配

凌云志 ! 2023-06-23 原文

目录

一. 创建安卓13模拟器或使用安卓13系统真机调试.

 1.下载 Android 13 SDK:

2. 设置模拟器

二.功能变化概览及适配方案

1.读写SD卡权限的调整​​​​​​​

2.撤销权限

3.通知权限的调整

4.后台运行限制


一. 创建安卓13模拟器或使用安卓13系统真机调试.

 1.下载 Android 13 SDK:

  • 依次点击 Tools > SDK Manager。
  • 在“SDK Platforms”标签页中,选择 Android 13 (Android API 33)。
  • 在 SDK Tools 标签页中,选择 Android SDK Build-Tools 33。

        点击OK安装 SDK。

 2. 设置模拟器

  • 依次点击 Tools > AVD Manager > "+ Create Virtual Device".
  • 选择"Phone" > "Next" > 选择 API Level 33   创建模拟器即可.

二.功能变化概览及适配方案

1.读写SD卡权限的调整

Android13之前,读取SD卡只需要申请一个权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
但Android13之后,这个权限被细化成了三个,这三个权限需要分别单独去申请。

Manifest.permission.READ_MEDIA_IMAGES
Manifest.permission.READ_MEDIA_VIDEO
Manifest.permission.READ_MEDIA_AUDIO

适配方案:

如果是升级Android13之前就已经具有读写SDK的权限,那么升级到13之后,自动就会有上述三个权限。

如果是升级Android13之后新装的应用,且targetSDK小于33,申请READ_EXTERNAL_STORAGE权限时,会自动转化为对上述三个权限的申请,申请框只一个.

 如果是升级Android13之后新装的应用,且targetSDK大于等于33,则申请READ_EXTERNAL_STORAGE权限时会自动拒绝(同理WRITE_EXTERNAL_STORAGE也是一样)。必须申请上面三个权限才可以。下午就是安卓13新安装APP,直接申请读写权限被拒绝.

安卓13动态权限兼容处理,打开相册不需要权限,但选择相片之后的操作需要自行测试是否正常.

1.在AndroidManifest.xml文件中添加权限,根据自己需要添加.

<!--安卓13之后读取图片权限-->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<!--安卓13之后读取视频权限-->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!--安卓13之后读取音频权限-->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />

2.发起动态权限申请,根据自身需要添加.

String[] list = new String[10];
if (Build.VERSION.SDK_INT >=33){
    list[0] = "android.permission.READ_MEDIA_IMAGES"; //图片
    list[1] = "android.permission.READ_MEDIA_VIDEO"; //视频
    list[2] = "android.permission.READ_MEDIA_AUDIO"; //音频
}else{
    list[0] = Manifest.permission.READ_EXTERNAL_STORAGE;
}
ActivityCompat.requestPermissions(MainActivity.this, list, 000);

下面是只申请图片权限的效果:

3.打开相册方法兼容

public static void openPhotoAlbum(Activity activity) {
        Intent intent;
        if (Build.VERSION.SDK_INT >= 33) {
            //安卓13以上打开相册.
            intent = new Intent("android.provider.action.PICK_IMAGES");
            intent.setType("images/*");//设置只显示图片
            /**
             * 设置选择照片的个数,默认1张时可不添加该属性,大于1的时候再设置.
             * 可指定图片数量上限为最大数字,调用 MediaStore.getPickImagesMaxLimit().
             */
            //intent.putExtra("android.provider.extra.PICK_IMAGES_MAX", MediaStore.getPickImagesMaxLimit());
        } else {
            intent = new Intent(Intent.ACTION_PICK);
            intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
        }
        activity.startActivityForResult(intent, 888);
    }

2.撤销权限

对不需要使用的权限进行撤销.

现在这张图片是申请了所有读取权限的.

 1.在AndroidManifest.xml中删除准备撤销的视频和音频权限. 2.在代码中把需要撤销的权限保存到List集合,然后调用API接口即可.

if (Build.VERSION.SDK_INT >= 33) {
            ArrayList<String> permissions = new ArrayList<>();
            permissions.add("android.permission.READ_MEDIA_VIDEO");
            permissions.add("android.permission.READ_MEDIA_AUDIO");
            revokeSelfPermissionsOnKill(permissions);
        }

3.撤销完权限之后再看app的权限,如下图已删除视频和音频权限.

3.通知权限的调整

Android13中,notifcation权限改成危险权限,需要动态申请。

简单来说,就是把权限级别升级了,申请方式不变,流程也不变,但是需要申请新的权限,老的已申请的通知权限在13版本上无法使用,即使 targetSDK < 33 也不行。

总结下来,分为三种场景:

1.应用在系统升级到13之前已经有通知权限,则自动授予新的通知权 POST_NOTIFICATIONS。

2.应用在13上新装,targetSDK<33,则申请该权限时只会弹一次,如果拒绝则此应用失去申请该权限的权利。

3.应用在13上新装,targetSDK>=33,每次申请该权限时都会弹。如果用户拒绝,下一次还可以继续申请。

适配方案:

首先,targetSdkVersion改为33。

其次,manifest中声明相关权限

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
最后代码中判断版本进行相关申请,如下:

private void checkAndSendNotification() {
        if (Build.VERSION.SDK_INT >= 33) {
            //检查是否有通知权限
            NotificationManager manager = getSystemService(NotificationManager.class);
            boolean enabled = manager.areNotificationsEnabled();
            if (!enabled) {
                String[] strings = {"android.permission.POST_NOTIFICATIONS"};
                requestPermissions(strings, 002);
                return;
            }
            sendNotification();
            return;
        } else {
            //继续执行老版本逻辑
            sendNotification();
        }
    }

    private void sendNotification() {
    }


4.后台运行限制

安卓13之前,应用的service是可以后台正常执行的。在13之后,某些情况下(比如低电量),会限制service的一些后台行为,比如限制网络的访问等等。用户进行前台互动操作后,则APP可以从受限分区移除。

主要分为三个级别,代码和描述如下:

private void handleAction() {
        UsageStatsManager systemService = getSystemService(UsageStatsManager.class);
        int appStandbyBucket = systemService.getAppStandbyBucket();
        //1.没有任何限制
        if (appStandbyBucket <= UsageStatsManager.STANDBY_BUCKET_ACTIVE) {
 
            return;
        }
        //2.应用最近几个小时内使用过,受到一定限制,限制程度较低。此时定时任务会被禁止执行
        if (appStandbyBucket <= UsageStatsManager.STANDBY_BUCKET_WORKING_SET) {
 
            return;
        }
        //3.和上面一样,只不过是几天内使用过。
        if (appStandbyBucket <= UsageStatsManager.STANDBY_BUCKET_FREQUENT) {
 
            return;
        }
        //4.限制访问网络
    }


三.新功能使用及使用样例
1.可降级权限
之前权限只有申请,没有降级。这次,新增了权限降级功能,开发者如果之前申请了某个权限,但是后续版本不需要了,可以主动调用API进行相关的降级处理。

        //activity or fragment 
        List<String> checkPermission = new ArrayList<>();
        checkPermission.add(Manifest.permission.READ_MEDIA_AUDIO);
        checkPermission.add(Manifest.permission.READ_MEDIA_IMAGES);
        checkPermission.add(Manifest.permission.READ_MEDIA_VIDEO);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            this.revokeSelfPermissionsOnKill(checkPermission);
        }
2.无需申请权限的相册选择器
我们通过新的API,可以直接访问相册,而无需申请任何权限,并且支持多选功能。

选择单张:

Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
startActivityForResult(intent, PHOTO_PICKER_REQUEST_CODE);
选择多张:

final int maxNumPhotosAndVideos = 10;
Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxNumPhotosAndVideos);
startActivityForResult(intent, PHOTO_PICKER_MULTI_SELECT_REQUEST_CODE);
还可以通过type区分视频还是图片,这样以后就不用自己去搞

intent.setType("video/*");
其实和原来的使用方式差别不大,但是多了一个选择数量的功能,以及不需要申请权限。

3.APP单独设置语言偏好
13之前,APP的语言设置都是跟随系统的,系统如果设置的是默认应用,那么APP也会自动的切换成英语模式。13开始,支持应用单独设置优先语言,不需要跟着系统语言设定走了。

首先,创建支持语言配置文件:

然后,在AndroidManifest.xml中进行使用配置。

要注意的时,locales_config.xml配置中文的话,是zh,而不是zh-rCH。具体大陆/香港/台湾省语言,是没办法选择的。

4.带主题的应用图标
其实就是让桌面快捷图标支持白天黑夜模式,但是实际上这个功能有可能不是我们本来设想的那样。这个功能是让某一张单色应用图标支持白天/黑夜模式的切换,而不是支持两张不同的图片分别在白天黑夜模式下进行显示,所以实际效果并没有那么的理想。

首先,我们需要创建一张VectorDrawable类型的资源图片,battery.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <group
        android:name="rotationGroup"
        android:pivotX="10.0"
        android:pivotY="10.0"
        android:rotation="15.0">
        <path
            android:name="vect"
            android:fillAlpha=".3"
            android:fillColor="#FF000000"
            android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V9h4.93L13,7v2h4V5.33C17,4.6 16.4,4 15.67,4z" />
        <path
            android:name="draw"
            android:fillColor="#FF000000"
            android:pathData="M13,12.5h2L11,20v-5.5H9L11.93,9H7v11.67C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V9h-4v3.5z" />
    </group>
</vector>
然后配置主题图标:launcher.xml

<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/icon_background" />
    <foreground android:drawable="@drawable/icon_light" />
    <monochrome android:drawable="@drawable/battery" />
</adaptive-icon>
其中monochrome就是那张主题图标,最终变化的也是这一张图片。

最后AndroidManifest.xml中进行配置:

最终效果图如下:

 白天模式/黑夜模式:

 原本图标效果:

需要注意的是,必须在设置中打开才可以使用该功能:

 3.附近WI-FI设备的新运行时权限
介绍:

扫描附近WI-FI设备时,之前需要申请的权限时ACCESS_FINE_LOCATION定位权限,这其实是不合适的。Android13修正了这个问题,新添加NEARBY_WIFI_DEVICES权限来解决这问题。

这项新权限会影响几个不同的 Wi-Fi 用例,包括以下用例:

查找或连接到附近的设备,如打印机或媒体投射设备。通过该工作流,您的应用可以完成以下类型的任务:
通过带外方式(例如通过 BLE)接收 AP 信息。
使用仅限本地使用的热点,通过 Wi-Fi 感知和连接功能发现并连接到设备。
通过 Wi-Fi 直连发现和连接到设备。
发起与已知 SSID(例如汽车或智能家居设备)的连接。
开启仅限本地使用的热点。
连接到附近的 Wi-Fi 感知设备。
使用案例:

manifest中进行申明:

<manifest ...>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
                     android:maxSdkVersion="32" />
    <application ...>
        ...
    </application>
</manifest>
代码中进行版本判断:

         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            checkPermission.add(Manifest.permission.NEARBY_WIFI_DEVICES);
        }else{
            checkPermission.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }

有关Android 13适配的更多相关文章

  1. ruby - 安装libv8(3.11.8.13)出错,Bundler无法继续 - 2

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

  2. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  3. ruby-on-rails - gem install rmagick -v 2.13.1 错误 Failed to build gem native extension on Mac OS 10.9.1 - 2

    我已经通过提供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/

  4. ruby-on-rails - 我应该使用哪个适用于 Ruby 的 CouchDB 适配器? - 2

    一些我找到的选项是ActiveCouchCouchRESTCouchPotatoRelaxDBcouch_foo我更喜欢GitHub上的项目,因为这让我更容易fork和推送修复。所有这些都符合该要求。我习惯了Rails,所以我喜欢像ActiveRecord模型一样工作的东西。另一方面,我也不希望我和Couch之间太多--毕竟我使用它作为我的数据库是有原因的。最后,它们似乎都得到了相当积极的维护(couch_foo可能是个异常(exception))。所以我想这归结为(不可否认和不幸的)主观:有没有人对他们有过好的或坏的经历? 最佳答案

  5. ruby-on-rails - 具有六边形架构和 DCI 模式的框架和数据库适配器 - 2

    我尝试用Ruby设计一个基于Web的应用程序。我开发了一个简单的核心应用程序,在没有框架和数据库的情况下在六边形架构中实现DCI范例。核心六边形中有小六边形和网络,数据库,日志等适配器。每个六边形都在没有数据库和框架的情况下自行运行。在这种方法中,我如何提供与数据库模型和实体类的关系作为独立于数据库的关系。我想在将来将框架从Rails更改为Sinatra或数据库。事实上,我如何在这个核心Hexagon中实现完全隔离的rails和mongodb的数据库适配器或框架适配器。有什么想法吗? 最佳答案 ROM呢?(Ruby对象映射器)。还有

  6. ruby-on-rails - Heroku 错误 H13 - 2

    自从我将我的应用程序部署到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-

  7. ruby-on-rails - 使用 PostgreSQL 适配器限制 ActiveRecord 迁移 5.0 中的文本列 - 2

    我的迁移看起来像这样classCreateQuestionings现在,当我运行$rakedb:migrate:reset时,在我的db/schema.rb中看不到限制:create_table"questionings",force::cascadedo|t|t.text"body",null:falseend我做错了吗还是这是一个错误?顺便说一下,我使用的是rails5.0.0.beta3和ruby​​2.3.0p0。 最佳答案 t.text在PostgreSQL和textdoesn'tallowforsizelimits中生成

  8. iOS适配Unity-2019 - 2

    iOS适配Unity-2019背景由于2019起,Unity的Xcode工程,更改了项目结构。Unity2018的结构:可以看Targets只有一个Unity-iPhone,Unity-iPhone直接依赖管理三方库。Unity2019以后:Targets多了一个UnityFramework,UnityFramework管理三方库,Unity-iPhone依赖于UnityFramwork。所以升级后,会有若干的问题,以下是对问题的解决方式。问题一错误描述error:exportArchive:Missingsigningidentifierat"/var/folders/fr//T/Xcode

  9. ruby - 将 OSX 更新到 10.13 (macOS High Sierra) 后不编译 SCSS - 2

    考拉版本:2.2.0Errormessage:/scss/styles.scss/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/dependency.rb:319:into_specs':Couldnotfind'sass'(>=0)among15totalgem(s)(Gem::LoadError)Checkedin'GEM_PATH=/Users/monstercritic/.gem/ruby/2.3.0:/Library/Ruby/Gems/2.3.0:/Syst

  10. ruby-on-rails - 无法在 Ubuntu 13.04 上安装 rmagick gem - 2

    当我尝试安装rmagic时:geminstallrmagic它给出了错误:Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingrmagick:ERROR:Failedtobuildgemnativeextension./home/biske/.rbenv/versions/2.0.0-p247/bin/rubyextconf.rbcheckingforRubyversion>=1.8.5...yescheckingforgcc...yescheckingforMagick-config...yesche

随机推荐