乐趣区

关于前端:Android-各版本新特性

Android 各版本新个性

一:介绍
咱们能够看到 Android 版本对应的 Api 版本

二:Android 6.0
Google I/O 2015 大会如约已于 2015 年 5 月 28 日举办。在发布会上代号为“Marshmallow(棉花糖)”的安卓 6.0 零碎正式推出。
Android 6.0 的 API 级别:23
新个性:
1. 运行时权限(最次要)
此版本引入了一种新的权限模式,用户可间接在运行时治理利用权限。
对于以 Android 6.0(API 级别 23)或更高版本为指标平台的利用,请务必在运行时检查和申请权限。要确定您的利用是否已被授予权限,请调用新增的 checkSelfPermission() 办法。要申请权限,请调用新增的 requestPermissions() 办法。即便您的利用并不以 Android 6.0(API 级别 23)为指标平台,您也应该在新权限模式下测试您的利用。
2. 勾销反对 Apache HTTP 客户端
Android 6.0 版本移除了对 Apache HTTP 客户端的反对。
如果您的利用应用该客户端,并以 Android 2.3(API 级别 9)或更高版本为指标平台,请改用 HttpURLConnection 类。此 API 效率更高,因为它能够通过通明压缩和响应缓存缩小网络应用,并可最大限度升高耗电量。要持续应用 Apache HTTP API,您必须先在 build.gradle 文件中申明以下编译时依赖项:

android {useLibrary 'org.apache.http.legacy'// 应用 Apache 库}

三:Android 7.0
Android 7.0 是 Google 推出的智能手机操作系统,官网代号为“Nougat”(牛轧糖)。于 2016 年 5 月 18-20 日(美国西部工夫)在 Google I/ O 开发者大会上正式公布,公布地点是山景城的 Shoreline Ampitheatre 圆形剧场
Android 7.0 包含旨在缩短设施电池寿命和缩小 RAM 应用的零碎行为变更。这些变更可能会影响您的利用拜访系统资源,以及您的利用通过特定隐式 intent 与其余利用交互的形式。
新个性:
1. 低电耗模式
Android 6.0 引入了低电耗模式,当用户设施未插接电源,处于静止状态且屏幕敞开时,该模式会推延 CPU 和网络流动,从而缩短电池寿命。而 Android 7.0 则通过在设施未插接电源且屏幕敞开状态下、但不肯定要处于静止状态(例如用户外出时把手持式设施装在口袋里)时利用局部 CPU 和网络限度,进一步加强了低电耗模式。
2. 零碎权限的更改
为了进步公有文件的安全性,面向 Android 7.0 或更高版本的利用公有目录被限度拜访 (0700)。此设置可避免公有文件的元数据透露,如它们的大小或存在性。此权限更改有多重副作用
传递软件包网域外的 file:// URI 可能给接收器留下无法访问的门路。因而,尝试传递 file:// URI 会触发 FileUriExposedException。分享公有文件内容的举荐办法是应用 FileProvider。
Android7.0 之前拜访零碎相册

     File file = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".jpg");
                if (!file.getParentFile().exists()) file.getParentFile().mkdirs();
                Uri imageUri = Uri.fromFile(file);
                Intent intent = new Intent();
// 设置 Action 为拍照
                intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
// 将拍取的照片保留到指定 URI
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                startActivityForResult(intent, 1);

在 7.0 之后的话拜访相册会报如下谬误:
android.os.FileUriExposedException: file:///storage/emulated/0/temp/1627010812423.jpg exposed beyond app through ClipData.Item.getUri()
在 Android7.0 零碎上,Android 框架强制执行了 StrictMode API 政策禁止向你的利用外公开 file:// URI。如果一项蕴含文件 file:// URI 类型 的 Intent 来到你的利用,利用失败,并呈现 FileUriExposedException 异样,如调用零碎相机拍照,或裁切照片。
解决办法:
第一步:在清单文件 AndroidManifest.xml 中注册 provider

  <provider

            android:name="androidx.core.content.FileProvider"// 非 androidx 下 android:name="android.support.v4.content.FileProvider"
            android:authorities="com.ruan.mygitignore.fileprovider"// 包名.fileprovider
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_path" />

参数解释:

  • name: 是固定的
  • android:authorities 举荐写您的利用包名 +“.fileprovider”,其实这里不肯定要写 fileprovider,您也能够轻易写,只有与前面应用 FileProvider.getUriForFile()这个办法中的第二个参数 authority 对应起来即可;(URI uri = FileProvider.getUriForFile(context, “com.ruan.mygitignore.fileprovider”, file);)
  • android:grantUriPermissions 固定 true,示意 uri 拜访受权;
  • android:exported 固定的 false,我试着写了 true 报平安异样。
  • android:resource 示意咱们 app 要共享文件的门路的资源文件。

第二步:res 文件夹下,新建一个 xml 文件夹,名字就是上一步 android:resource=”@xml/file_paths”对应的内容

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="Camera"
        path="" />
</paths>
  • 命名为“file_paths”(名字能够轻易起,只有和第一步中在 manifest 注册的 provider 所援用的 resource 保持一致即可)的资源文件。
  • 上述代码中 path=”“,是有非凡意义的,它指的是根目录,也就是说您能够向其它的利用拜访根目录及其子目录下任何一个文件了,如果您将 path 设为 path=”pictures”,那么它代表着根目录下的 pictures 目录(eg:/storage/emulated/0/pictures),这时您拜访 pictures 目录范畴之外的文件是不行的。
  • files-path 代表的根目录:Context.getFilesDir()
  • external-path 代表的根目录: Environment.getExternalStorageDirectory()
  • cache-path 代表的根目录: getCacheDir()

第三步:应用 FlieProvider

 /*
     * 相册,抉择一张图片
     */
  private void getPhoto(Context context) {
        // 这里用工夫命名是发现用固定名命名后第二次裁剪图片任然是第一次的图,没有笼罩上一次图片资源;7.0 之前固定名会替换
        File file = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".jpg");
        if (!file.getParentFile().exists()) file.getParentFile().mkdirs();
        // 通过 FileProvider 创立一个 content 类型的 Uri
        Uri imageUri = FileProvider.getUriForFile(context, "com.ruan.mygitignore.fileprovider", file);
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        // 设置 Action 为拍照
        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
        // 将拍取的照片保留到指定 URI
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        // 开启一个带有返回值的 Activity,申请码为 PHOTO_REQUEST_GALLERY
        startActivityForResult(intent, 1);
         System.out.println(imageUri);
    }
    
    // 后果
 System.out: content://com.ruan.mygitignore.fileprovider/Camera/temp/1627018704311.jpg   

最简略的以关上相机为例:

   File file = new File(Environment.getExternalStorageDirectory(), "/temp/" + System.currentTimeMillis() + ".jpg");

                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                if (Build.VERSION.SDK_INT >= 24) {intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    //24 以上应用 FileProvider
                    intent.putExtra(MediaStore.EXTRA_OUTPUT,
                            FileProvider.getUriForFile(FiveTeenActivity.this, "com.ruan.mygitignore.fileprovider", file));
                }else{
                    //24 以下
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
                }
                startActivityForResult(intent, 1);

1、将之前 Uri 的 scheme 类型为 file 的 Uri 改成了有 FileProvider 创立一个 content 类型的 Uri。
2、增加了 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 来对指标利用长期受权该 Uri 所代表的文件。

四:Android 8.0
2017 年 8 月 22 日,谷歌正式公布了 Android 8.0 的正式版,其正式名称为:Android Oreo(奥利奥)。2017 年 12 月 5 日谷歌正式公布了 Android 8.1 的正式版。
新个性:
1. 告诉渠道 — Notification Channels
告诉渠道是由利用自行定义的告诉内容类别,借助渠道,开发者能够让用户对不同品种的告诉进行精密管制,用户能够独自拦挡或更改每个渠道的行为,而不是对立治理利用的所有告诉。
创立告诉渠道的步骤:

  • 创立 NotificationChannel 对象,并设置利用内惟一的告诉 ID。
  • 配置告诉渠道的属性,比方提醒声音等。
  • 在 NotificationManager 中注册告诉渠道对象。

    2、画中画模式 — PIP
    Android O 现已反对 Activity 的画中画模式。PIP 是一种多窗口显示模式,多用于视频播放。这和一般的画中画分屏模式并不相同。这一性能的唤醒只须要点击 Home 键按钮,如果想完结这一模式,能够将小窗口滑下来以终止。
    对于生命周期
    PIP 模式不会扭转 Activity 的生命周期。在指定工夫只有最近与用户交互过的 Activity 为活动状态。该 Activity 将被视为顶级 Activity。所有其余 Activity 尽管可见,但均处于暂停状态。当一个 Activity 处于 PIP 模式时,其实它是出在暂停状态,但其内容会持续展现。
    API 变更
    在 Android O 中新增 PictureInPictureArgs 对象来指明你的 Activity 在 PIP 模式中的属性,比方长宽比等。
    Android O 还新增了以下办法来反对 PIP。
Activity.enterPictureInPictureMode(PictureInPictureArgs args):将 Activity 置于 PIP 模式之下。Activity.setPictureInPictureArgs():用于更新 Activity 在 PIP 模式下的设置。如果 Activity 正处于 PIP 模式之下,那么更改的属性将立刻失效。

五:Android 9.0
Android 9.0 是谷歌研发的挪动端操作系统,开发代号为“Pie”(派),于 2018 年 8 月 7 日正式公布
1. 利用 wifi RTT 进行室内定位
Android 9 增加了对 IEEE 802.11mc Wi-Fi 协定(也称为 Wi-Fi Round-Trip-Time (RTT))的平台反对,从而让您的利用能够利用室内定位性能。

在运行 Android 9 且具备硬件反对的设施上,利用能够应用 RTT API 来测量与左近反对 RTT 的 Wi-Fi 接入点 (AP) 的间隔。设施必须已启用位置服务并开启 Wi-Fi 扫描(在 Settings > Location 下),同时您的利用必须具备 ACCESS_FINE_LOCATION 权限。

设施无需连贯到接入点即可应用 RTT。为了爱护隐衷,只有手机能够确定与接入点的间隔;接入点无此信息。

如果您的设施测量与 3 个或更多接入点的间隔,您能够应用一个多点定位算法来预估与这些测量值最相符的设施地位。后果通常精准至 1 至 2 米。

通过这种精确性,您能够打造新的体验,例如楼内导航、基于精密地位的服务,如无歧义语音管制(例如,“关上这盏灯”),以及基于地位的信息(如“此产品是否有特地优惠?”)。
2. 显示屏缺口反对
Android 9 反对最新的全面屏,其中蕴含为摄像头和扬声器预留空间的屏幕缺口。通过 DisplayCutout 类可确定非性能区域的地位和形态,这些区域不应显示内容。要确定这些屏幕缺口区域是否存在及其地位,请应用 getDisplayCutout() 函数。

全新的窗口布局属性 layoutInDisplayCutoutMode 让您的利用能够为设施屏幕缺口四周的内容进行布局。您能够将此属性设为下列值之一:
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
能够按以下办法在任何运行 Android 9 的设施或模拟器上模仿屏幕缺口:

启用开发者选项。
在 Developer options 屏幕中,向下滚动至 Drawing 局部并抉择 Simulate a display with a cutout。
抉择屏幕缺口的大小。
注:咱们建议您通过应用运行 Android 9 的设施或模拟器测试屏幕缺口四周的内容显示。
3. 前台服务
如果利用以 Android 9 或更高版本为指标平台并应用前台服务,则必须申请 FOREGROUND_SERVICE 权限。这是一般权限,因而,零碎会主动为申请权限的利用授予此权限。

如果以 Android 9 或更高版本为指标平台的利用尝试创立前台服务且未申请 FOREGROUND_SERVICE,则零碎会抛出 SecurityException。

public class FloatPasswordWindowService extends Service {

 @Override
    public void onCreate() {super.onCreate();
       
    }
      @Nullable
    @Override
    public IBinder onBind(Intent intent) {LogUtils.d("FloatWindowService:onBind");
        return null;
    }
    
     @Override
  public int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, "onStartCommand()");
    // 参数一:惟一的告诉标识;参数二:告诉音讯。startForeground(110, notification);// 开始前台服务
  }
  
  @Override
public void onDestroy() {Log.d(TAG, "onDestroy()");
  stopForeground(true);// 进行前台服务 -- 参数:示意是否移除之前的告诉
  super.onDestroy();}
}

9.0 要求创立一个前台服务须要申请 FOREGROUND_SERVICE 权限,否则零碎会引发 SecurityException。

Intent intentService = new Intent(this, MyService.class);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {startForegroundService(intentService);// 开启前台服务
} else {startService(intentService);
}

PS:表遗记 AndroidManifest.xml 中增加 FOREGROUND_SERVICE 权限

//9.0 这个前台服务权限不要忘了
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

4. 启动 Activity
在 9.0 中,不能间接非 Activity 环境中(比方 Service,Application)启动 Activity,否则会解体报错。
这类问题个别会在点击推送音讯跳转页面这类场景,解决办法就是 Intent 中增加标记 FLAG_ACTIVITY_NEW_TASK

Intent intent = new Intent(this, TestActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

5.Http 申请
请查看之前写的文章
https://segmentfault.com/a/11…
6.Apache HTTP 客户端弃用
在 Android 6.0 时,就曾经勾销了对 Apache HTTP 客户端的反对。从 Android 9.0 开始,默认状况下该库已从 bootclasspath 中移除。然而耐不住有些 SDK 中还在应用,比方我见到的友盟 QQ 分享报错问题。
所以要想持续应用 Apache HTTP,须要在利用的 AndroidManifest.xml 文件中增加:

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:networkSecurityConfig="@xml/network_security_config"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyGitignore">

<uses-library android:name="org.apache.http.legacy" android:required="false"/>// 应用这个
<application/>

六:Android 10
Android 10 蕴含多项性能降级,包含手势导航、告诉栏治理、全局光明模式等等,告诉治理新增了“优先”、“无声”和“自适应告诉”三种性能,新增深色主题的背景
1. 用户存储权限的变更
Android Q 在内部存储设备中为每个利用提供了一个“隔离存储沙盒”(例如 /sdcard)。任何其余利用都无奈间接拜访您利用的沙盒文件。因为文件是您利用的公有文件,因而您不再须要任何权限即可在内部存储设备中拜访和保留本人的文件。此变更可让您更轻松地保障用户文件的隐衷性,并有助于缩小利用所需的权限数量。
谷歌官网举荐利用在沙盒内存储文件的地址为 Context.getExternalFilesDir()下的文件夹。比方要存储一张图片, 则应放在 Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)中。
2. 用户的定位权限的变更
为了让用户更好地管制利用对地位信息的拜访权限,Android Q 引入了新的地位权限 ACCESS_BACKGROUND_LOCATION。

与现有的 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 权限不同,新权限仅会影响利用在后盾运行时对地位信息的拜访权。除非利用的某个 Activity 可见或利用正在运行前台服务,否则利用将被视为在后盾运行。
与 iOS 零碎一样,Q 中也退出了后盾地位权限 ACCESS_BACKGROUND_LOCATION,如果利用须要在后盾时也取得用户地位(比方滴滴),就须要动静申请 ACCESS_BACKGROUND_LOCATION 权限。

当然如果不需要的话,利用就无需任何改变,且谷歌会依照利用的 targetSDK 作出不同解决:
targetSDK <= P 利用如果申请了 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 权限,Q 设施会主动帮你申请 ACCESS_BACKGROUND_LOCATION 权限。

3. 设施惟一标识符的变更
从 Android Q 开始,利用必须具备 READ_PRIVILEGED_PHONE_STATE 签名权限能力拜访设施的不可重置标识符(蕴含 IMEI 和序列号)。
如果您的利用没有该权限,但您仍尝试查问标识符的相干信息,会返回空值或报错。
设施惟一标识符须要特地留神,原来的 READ_PHONE_STATE 权限曾经不能取得 IMEI 和序列。
如果想在 Q 设施上通过应用以下代码获取设施的 ID

((TelephonyManager)getActivity().getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId()

则执行以上代码会返回空值 (targetSDK<=P) 或者报错 (targetSDK==Q)。且官网所说的 READ_PRIVILEGED_PHONE_STATE 权限只提供给零碎 app,所以这个办法行不通了。
谷歌官网给予了设施惟一 ID 最佳做法,然而此办法给出的 ID 可变,能够依照具体需要具体解决。本文给出一个不变和根本不反复的 UUID 办法:

public static String getUUID() {
    String serial = null;
    String m_szDevIDShort = "35" +
        Build.BOARD.length() % 10 + Build.BRAND.length() % 10 +
        Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 +
        Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 +
        Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 +
        Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 +
        Build.TAGS.length() % 10 + Build.TYPE.length() % 10 +
        Build.USER.length() % 10; //13 位

    try {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {serial = android.os.Build.getSerial();
            } else {serial = Build.SERIAL;}
            //API>=9 应用 serial 号
            return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();} catch (Exception exception) {
            //serial 须要一个初始化
            serial = "serial"; // 轻易一个初始化
      }
    // 应用硬件信息拼凑进去的 15 位号码
    return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();}

七:Android 11
Android 11 正式版零碎在 2020 年 9 月 9 日正式公布。零碎次要加强了聊天气泡,安全性和隐衷性的爱护,电源菜单,能够更好的反对瀑布屏,折叠屏,双屏和 Vulkan 扩大程序等。
新个性
1. 短信更新改良
首先是聊天泡泡。与 Facebook 多年来在 Android 上提供的 Messenger 应用程序相似,Android 11 优化了短信性能,提供更加敌对的交互。同时,为了确保用户能尽快收到对方的音讯,Android 11 在告诉暗影(Notification Shade)中引入了一个专门的对话局部,它将提供对用户正在进行的任何对话的即时拜访。这一更新将有助于短信音讯从其余告诉中怀才不遇。
2. 电话号码相干权限
Android 11 更改了您的利用在读取电话号码时应用的与电话相干的权限。

其实就是两个 API:
TelecomManager 类中的 getLine1Number() 办法
TelecomManager 类中的 getMsisdn() 办法

也就是当用到这两个 API 的时候,原来的 READ_PHONE_STATE 权限不论用了,须要 READ_PHONE_NUMBERS 权限才行。
3. 当初须要 APK 签名计划 v2
对于以 Android 11(API 级别 30)为指标平台,且目前仅应用 APK 签名计划 v1 签名的利用,当初还必须应用 APK 签名计划 v2 或更高版本进行签名。用户无奈在搭载 Android 11 的设施上装置或更新仅通过 APK 签名计划 v1 签名的利用。

如果你的 targetSdkVersion 批改到 30,那么你就必须要加上 v2 签名才行。否则无奈装置和更新。
八:Android 12
Android 12 从新发现了代号为“Columbus”的性能,并且优化了触发问题,新的手势须要更加使劲敲击反面。新的双击反面手势能够截取屏幕截图、号召谷歌 Assistant、关上告诉栏、管制媒体播放或关上最近的应用程序列表。
1. AVIF 图像反对

  1. 为了为您提供更高的图像品质和更无效的压缩,Android 12 引入了对 AV1 图像文件格式(AVIF)的平台反对。AVIF 是用于应用 AV1 编码的图像和图像序列的容器格局。与其余古代图像格式一样,AVIF 利用了视频压缩中的帧内编码内容。与 JPEG 等较旧的图像格式相比,这能够显着进步雷同文件大小的图像品质。
    AVIF(18.2kB)JPEG(20.7kB)
    2. 前台服务优化
    前台服务是应用程序治理某些类型的面向用户工作的重要形式,然而如果适度应用,它们可能会影响性能,甚至导致应用程序中断。为了确保为用户带来更好的体验,对于以新平台为指标的利用,咱们将从后盾阻止前台服务启动。为了更轻松地从此模式过渡,咱们在 JobScheduler 中引入了一个新的加急作业,该作业取得了较高的过程优先级,网络拜访权限,并且能够在不思考节电或节电的状况下立刻运行。为了实现向后兼容,咱们还在最新版本的 Jetpack WorkManager 库中内置了加急作业。。另外,为了缩小用户的注意力,咱们当初将某些前台服务告诉的显示提早最多 10 秒钟。这使短暂的工作有机会在显示告诉之前实现

END: 你的无畏来源于无知

退出移动版