返回顶部
首页 > 资讯 > 移动开发 >Android10(Api 29)新特性
  • 742
分享到

Android10(Api 29)新特性

apiAndroid 2022-06-06 13:06:30 742人浏览 安东尼
摘要

一.设备硬件标识符访问限制    限制应用访问不可重设的设备识别码,如 IMEI、序列号等,系统应用不受影响。 1.1. 原来的做法 // 在

一.设备硬件标识符访问限制

   限制应用访问不可重设的设备识别码,如 IMEI、序列号等,系统应用不受影响。

1.1. 原来的做法

// 在AndroidQ上以下方法都会有问题
// 返回:866976045261713;

TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
tm.getDeviceId();
tm.getSubscriberId();
tm.getDeviceId(TelephonyManager.PHONE_TYPE_NONE);

//返回:66J0218B19000977;
Build.getSerial();
在低于AndroidQ的系统上没问题
在AndroidQ及以上的系统上运行时:
如targetSdkVersion<Q,返回null或“unknown”;
如targetSdkVersion>=Q,抛异常:
SecurityException: getDeviceId: The user 10196 does not meet the requirements to access device identifiers.
   受影响的方法

Build
getSerial()
TelephonyManager
getImei()
getDeviceId()
getMeid()
getSimSerialNumber()
getSubscriberId()
1.2. 替代方案 1.2.1. 方案一

   使用AndroidId代替,缺点是应用签署密钥或用户(如系统恢复出产设置)不同返回的Id不同。与实际测试结果相符。
   经实际测试:相同签名密钥的不同应用androidId相同,不同签名的应用androidId不同。恢复出产设置或升级系统没测。

// 返回:496836e3a48d2d9d
String androidId = Settings.System.getString(context.getContentResolver(),
        Settings.Secure.ANDROID_ID);
1.2.2. 方案二

   通过硬件信息拼接,缺点是还是不能保证唯一。
   经测试:似乎与方案一比更稳定,不受密钥影响,但非官方建议,没安全感。

private static String makeDeviceId(Context context) {
    String  deviceInfo = new StringBuilder()
            .append(Build.BOARD).append("#")
            .append(Build.BRAND).append("#")
            //CPU_ABI,这个值和appp使用的so库是arm64-v8a还是armeabi-v7a有关,舍弃
            //.append(Build.CPU_ABI).append("#")
            .append(Build.DEVICE).append("#")
            .append(Build.DISPLAY).append("#")
            .append(Build.HOST).append("#")
            .append(Build.ID).append("#")
            .append(Build.MANUFACTURER).append("#")
            .append(Build.MODEL).append("#")
            .append(Build.PRODUCT).append("#")
            .append(Build.TAGS).append("#")
            .append(Build.TYPE).append("#")
            .append(Build.USER).append("#")
            .toString();
    try {
    	//22a49a46-b39e-36d1-b75f-a0d0b9c72d6c
       return UUID.nameUUIDFromBytes(deviceInfo.getBytes("utf8")).toString();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    String androidId = Settings.System.getString(context.getContentResolver(),
                Settings.Secure.ANDROID_ID);
    return androidId;
}
2. 禁止后台启动Activity 2.1. 情况描述

AndroidQ上,后台启动Activity会被系统忽略,不管targetSdkVersion多少;
AndroidQ上,即使应用有前台服务也不行;
AndroidQ以下版本没影响。

2.2. 解决方法

   发送全屏通知:

//AndroidManifest 声明新权限,不用动态申请
Intent intent = new Intent(this, ScopedStorageActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
        REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(this, Constants.CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_launcher_foreground)
        .setContentTitle("Incoming call")
        .setContentText("(919) 555-1234")
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setCateGory(NotificationCompat.CATEGORY_ALARM)
        //设置全屏通知后,发送通知直接启动Activity
        .setFullScreenIntent(pendingIntent, true)
        .build();
NotificationManager manager = getSystemService(NotificationManager.class);
manager.notify(445456, notification);

   但是:在华为mate20(api-28)上需要到设置中打开横幅通知;原生AndroidQ(beta6)上有效。

3. 后台应用增加定位限制 3.1. 情况描述

   后台应用要获取位置信息需要动态申请权限,


   在AndroidQ上运行:
   targetSdkVersion<Q,没影响,申请权限时系统默认会加上后台位置权限
   targetSdkVersion>=Q,需申请;
   应用变为后台应用90s后开始定位失败(Pixel AndroidQ-beta6)
   ACCESS_BACKGROUND_LOCATION不能单独申请,需要和    ACCESS_COARSE_LOCATION/ACCESS_FINE_LOCATION一起申请

3.2. 解决方法

   动态申请即可;
   启动前台服务


4. 分区存储 4.1. 情况描述

   从Android10开始应用将不可直接访问外部存储(/sdcard)文件,否则抛异常。
   在AndroidQ上运行:
   targetSdkVersion<Q,没影响;
   targetSdkVersion>=Q,默认启用过滤视图,应用以外的文件需要通过存储访问框架(SAF,StorageAccessFramework)读写。

4.2. 解决方法 4.2.1. 方法一

   停用过滤视图,使用旧版存储模式

   
     
       ...
4.2.2. 方法二

   将文件存储到过滤视图中,官方推荐。

   // /Android/data/com.example.androidq/files/Documents
   File dir = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);

   优点:不用申请读写权限;
   缺点:随应用卸载而删除;

4.2.3. 方法三

   使用存储访问框架(SAF),由用户指定要读写的文件。
   这个功能Android 4.4(API: 19)就有,官方文档在此。

4.2.4. 方法四

   获取用户指定的某个目录的读写权限
   从Android5.0(Api 21)开始就有
   步骤
   1. 申请目录的访问权限
   会打开系统的文件目录,由用户自己选择允许访问的目录,不用申请WRITE/READ_EXTERNAL_STORAGE权限。

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | 
        Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);				
startActivityForResult(intent, REQ_CODE);

   执行上述代码后会出现类似如下图界面,点击‘允许访问“DuoKan”’按钮,
允许了之后通过onActivityResult()的intent.getData()得到该目录的Uri,通过Uri可获取子目录和文件。这种方式的缺点是应用重装后权限失效, 即使可以保存了这个Uri也没用。

Uri dirUri = intent.getData();
// 持久化;应用重装后权限失效,即使知道这个uri也没用
SPUtil.setValue(this, SP_DOC_KEY, dirUri.toString());
//重要:少这行代码手机重启后会失去权限
getContentResolver().takePersistableUriPermission(dirUri, 
        Intent.FLAG_GRANT_READ_URI_PERMISSION);
        ```
      2. 通过Uri读写文件
      创建文件
```java
// 在mUri目录(‘DuoKan’目录)下创建'test.txt'文件
private void createFile() {
    DocumentFile documentFile = DocumentFile.fromTreeUri(this, mUri);
    DocumentFile file = documentFile.createFile("text/plain", "test.txt");
    if (file != null && file.exists()) {
        LogUtil.log(file.getName() + " created");
    }
}

   主要用到DocumentFile类,和File类的方法类似,有isFile、isDirectory、exists、listFiles等方法
删除文件

//删除"test.txt"
private void deleteFile() {
    DocumentFile documentFile = DocumentFile.fromTreeUri(this, mUri);
    // listFiles(),列出所有的子文件和文件夹
    for (DocumentFile file : documentFile.listFiles()) {
        if (file.isFile() && "test.txt".equals(file.getName())) {
            boolean delete = file.delete();
            LogUtil.log("deleteFile: " + delete);
            break;
        }
    }
}

   写入数据

private void writeFile(Uri uri) {
    try {
        ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "w");
        //这种方法会覆盖原来文件内容
        OutputStreamWriter output = 
                new OutputStreamWriter(new FileOutputStream(pfd.getFileDescriptor()));
        // 不能传uri.toString(),否则FileNotFoundException
        // OutputStreamWriter output = new OutputStreamWriter(new FileOutputStream(uri.toString(), true));
        output.write("这是一段文件写入测试\n");
        output.close();
        LogUtil.log("写入成功。");
    } catch (IOException e) {
        LogUtil.log(e);
    }
}

作者:雪芽蓝域zzs


--结束END--

本文标题: Android10(Api 29)新特性

本文链接: https://lsjlt.com/news/29354.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android10(Api 29)新特性
    一.设备硬件标识符访问限制    限制应用访问不可重设的设备识别码,如 IMEI、序列号等,系统应用不受影响。 1.1. 原来的做法 // 在...
    99+
    2022-06-06
    api Android
  • 新特性解读 | mysql 8.0 memcached api 新特性
    作者:杨涛涛 资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MyS...
    99+
    2017-07-06
    新特性解读 | mysql 8.0 memcached api 新特性
  • Java8新特性之Stream API详解
    目录一、前言二、使用流程三、案例演示一、前言 StreamAPI在Java8版本中使用,关注的是对数据的筛选、查找、存储等 它可以做的事情有:过滤、排序、映射、归约 二、使用流程 S...
    99+
    2024-04-02
  • java8新特性之日期时间API
    目录jdk8之前 一、java.lang.System二、java.util.Date And java.sql.Date三、java.text.SimpleDateFor...
    99+
    2024-04-02
  • java9新特性Reactive Stream响应式编程 API
    目录一、Java9 Reactive Stream API二、Java响应式编程四大接口2.1.Subscriber Interface(订阅者订阅接口)2.2.Subscripti...
    99+
    2024-04-02
  • Java9新特性Stream流API优化与增强
    目录1.Stream.takeWhile(Predicate)2.Stream.dropWhile(Predicate)3.StreamStream.iterate(T,Predic...
    99+
    2024-04-02
  • JDK 新特性篇:JDK 8 新特性详解
    Java8新特性简介 Java 8 (又称为 JDK 1.8) 是 Java 语言开发的一个主要版本。Java 8 是 Oracle 公司于 2014 年 3 月发布,可以看成是自 Java 5 以来最具革命性的版本。Java 8 为 J...
    99+
    2023-09-12
    java jvm 开发语言
  • JDK 新特性篇:JDK 9 新特性详解
    JDK 9 是 Java 平台的一次重大更新,引入了许多新的特性和改进。以下是 JDK 9 的一些主要新特性的详细解释。模块化系统(...
    99+
    2023-09-13
    JDK
  • JDK 新特性篇:JDK 10 新特性详解
    JDK 10 是 Java 开发工具包的一个版本,其中包含了一些新的特性和改进。下面是 JDK 10 的一些新特性的详细解释:1. ...
    99+
    2023-09-14
    JDK
  • Java8新特性Optional类及新时间日期API示例详解
    目录Optional类以前对null的处理Optional类介绍Optional的基本使用Optional的常用方法新时间日期API旧版日期时间的问题新日期时间API介绍日期时间的常...
    99+
    2022-11-13
    Java8 Optional类时间日期API Java8 新特性
  • mysql5.7新特性
        mysql5.7版本出来后还是有大量的修改以及一些调优,修复一些bug,删掉了一些旧的参数,在这里就简单的整理一下   因为平时都是使用二进制包安装...
    99+
    2024-04-02
  • Angular5.0.0新特性
    文章来自官网部分翻译https://blog.angular.io/version-5-0-0-of-angular-now-available-37e414935cedAngular5.0.0版本已经正式发布总结一下v5.0.0带来的新变...
    99+
    2023-05-30
    angular5.0.0 新特性 la
  • css3新特性
    强大的选择器    允许在标签中指定特定的HTML元素,而不必使用多余的类、ID、或者js脚本。    高级选择器可以避免在标签中添加大量的class、id属性,从而更加简洁和轻量,更方便于维护。半透明度效果    RGBA和HSLA不仅可...
    99+
    2023-01-31
    新特性
  • jdk8新特性
    jdk8新特性:1、Lambda表达式;2、Stream API;3、函数式接口;4、默认方法;5、方法引用;6、新的日期和时间API;7、并发增强;8、其他改进等等。JDK 8是Java开发工具包(Java Development Kit...
    99+
    2023-08-14
  • JDK6.0的新特性之六:插入式注解处理API(Pluggable Annotation Processing API)
    作者: 飞翼 发表日期: 2007-01-03 20:10...
    99+
    2023-06-03
  • 深入理解Java8新特性之新日期时间API的应用
    目录1.新旧对比(线程安全问题)2.LocalDate3.LocalTime4.LocalDateTime5.Instant6.Duration、Period7.TestTempor...
    99+
    2024-04-02
  • Java 9特性的三个新的API分别是什么
    本篇文章给大家分享的是有关Java 9特性的三个新的API分别是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Oracle已经公布,Java9***增强计划集(众所周知的J...
    99+
    2023-06-17
  • java9新特性Reactive Stream响应式编程API怎么用
    这篇文章主要介绍“java9新特性Reactive Stream响应式编程API怎么用”,在日常操作中,相信很多人在java9新特性Reactive Stream响应式编程API怎么用问题上存在疑惑,小编查阅了各式资料,...
    99+
    2023-06-29
  • 新特性解读 | MySQL 8.0 新特性-副本集(replicaset)
    引言 之前,我介绍过一篇《MySQL Innodb Cluster 扫盲篇》。 MySQL Innodb Cluster = MySQL Shell + MySQL Router + MySQL Group Replication(MGR...
    99+
    2021-10-20
    新特性解读 | MySQL 8.0 新特性-副本集(replicaset)
  • Redis新特性GEOHASH
    一、简言    Redis 的 GEO 特性将在 Redis 3.2 版本释出, 这个功能可以将用户给定的地理位置信息储存起来, 并对这些信息进行操作    ...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作