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" />
</provider>

参数解释:

  • 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/>

7.多进程使用WebView时不支持同时从多个进程使用具有相同数据目录的WebView

解决方法:

多进程时在Applicationd类的onCreate或者onBaseContextAttached方法中加入


public void onBaseContextAttached(Context base) {
    super.onBaseContextAttached(base);
    initWebViewDataDirectory(this);
}
 
/**
* 得到进程名称
* @param context
* @return
*/
public static String getProcessName(Context context) {
    try {
            if (context == null) 
                return null;
            ActivityManager manager = (ActivityManager)
            context.getSystemService(Context.ACTIVITY_SERVICE);
            for (ActivityManager.RunningAppProcessInfo processInfo : 
                manager.getRunningAppProcesses()) {
                if (processInfo.pid == android.os.Process.myPid()) {
                    return processInfo.processName;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    return null;
}
 
/**
* 为webView设置目录后缀
* @param context
*/
@RequiresApi(api = Build.VERSION_CODES.P)
public static void initWebViewDataDirectory(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        String processName = getProcessName(context);
        if (!context.getPackageName().equals(processName)) {//判断是否是默认进程名称
            WebView.setDataDirectorySuffix(processName);
        }
    }

六: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秒钟。这使短暂的任务有机会在显示通知之前完成

猜你喜欢

转载自blog.csdn.net/z936689039/article/details/121619575