Android适配

Posted by Haiden on April 12, 2019

一 屏幕适配

1 单位

1)、px:屏幕上绝对像素

2)、dpi(像素密度): 屏幕上单位面积内的像素数点,就是每英寸多少点。

3)、屏幕物理尺寸: 屏幕对角线的尺寸。单位是英寸。

4)、ppi:PPI就是计算机屏幕上每英寸可以显示的像素点的数量。因此,在电子屏幕显示中提到的ppi和dpi是一样的,可认为dpi=ppi。

不同手机屏幕大小对应的屏幕像素密度关系表:

5)、密度无关像素(dp 或 dip): 可以保证在不同屏幕像素密度的设备上显示相同的效果。

dp与px的转换:

px= dp *(dpi/160)

6)、独立比例像素(sp):用sp设置文字大小

2 具体屏幕适配

2.1 屏幕尺寸适配

1)布局适配:使用相对布局、根据屏幕的配置来加载相应的UI布局(使用限定符)

2)布局组件适配:使得布局组件自适应屏幕尺寸。使用”wrap_content”、”match_parent”和”weight“来控制视图组件的宽度和高度。

3)图片资源适配:使得图片资源在不同屏幕密度上显示相同的像素效果。(可以用.9图片)

2.2 屏幕密度适配

1)布局控件适配:使用 密度无关像素 ( dp ) 或 独立比例像素( sp ) 作为计量单位。或使用像素作为计量单位,采用百分比布局。

2)图片资源适配:使得图片资源在不同屏幕密度上显示相同的像素效果。

二 版本适配

2.1 Android 4.4版本以上的 API 对应表。

平台版本 API 级别 VERSION_CODE
Android 9 28 Pi
Android 8.1 27 Oreo
Android 8.0 26 Oreo
Android 7.1 25 Nougat
Android 7.0 24 Nougat
Android 6.0 23 Marshmallow
Android 5.1 22 LOLLIPOP_MR1
Android 5.0 21 LOLLIPOP
Android 4.4W 20 KITKAT_WATCH
Android 4.4 19 KITKAT

2.2 Android版本主要新特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
5.0 更新内容
	ui风格:material design
	由Dalvik转用ART(Android Runtime)编译
	V7中引入CardView和RecycleView等新控件
	支持64位系统

6.0 更新内容
	应用权限管理 
	Doze休眠机制 
	移除对Apache HTTP client的支持

7.0 更新内容
	通知消息归拢 
	通知栏快捷回复
	改进的Doze休眠机制 
	加入原生分屏多任务功能,多任务快速切换
	引入全新的JIT编译器

8.0 更新内容
	画中画功能
	后台进程限制
	分屏 
	
9.0 更新内容
使用 WiFi RTT 进行室内定位
凹口屏幕的支持
消息通知的改进
多摄像头 API

2.3 API接口方法变更

比如Notification类在不同版本的差异。下面列举一下,详细的查看官网Notification

EXTRA_LARGE_ICON:在API级别26中已弃用。使用getLargeIcon(),它支持更多种图标源。

EXTRA_SMALL_ICON:在API级别26中已弃用。使用getSmallIcon(),它支持更多种图标源。

FLAG_HIGH_PRIORITY:在api16被弃用,请使用正数priority值替代。

2.4 Android6.0的动态权限

在Android6.0(API23)开始需要动态申请权限,需要手动申请的危险权限有9组(短信、电话、联系人、存储、位置、麦克风、日历、相机)。

所属权限组 权限
短信 SEND_SMS、RECEIVE_SMS、READ_SMS、RECEIVE_WAP_PUSH、RECEIVE_MMS
电话 READ_PHONE_STATE、CALL_PHONE、READ_CALL_LOG、WRITE_CALL_LOG、ADD_VOICEMAIL、USE_SIP、PROCESS_OUTGOING_CALLS
联系人 READ_CONTACTS、WRITE_CONTACTS、GET_ACCOUNTS
存储 READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE
位置 ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION
麦克风 RECORD_AUDIO
日历 READ_CALENDAR、WRITE_CALENDAR
相机 CAMERA
传感器 BODY_SENSORS

2.5 Android6.0申请动态权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//在清单文件也加上CAMERA权限 6.0 以下需要
//<uses-permission android:name="android.permission.CAMERA" />

// 定义请求码
public static final int CAMERA_OK = 1;

//判断版本号
if (Build.VERSION.SDK_INT>22){  
	 //动态申请拍照权限
   if (ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)
        != PackageManager.PERMISSION_GRANTED){
           //先判断有没有权限 ,没有就在这里进行权限的申请
           requestPermissions(new String[]{Manifest.permission.CAMERA}, CAMERA_OK);       
    }else {
            //已经获取到摄像头权限了
            toSomeThing...
    }
}else {
      //这个说明系统版本在6.0之下
      toSomeThing...
}

//在Activity中重写权限获取方法:
/**
* 权限操作结果处理
*/
@Override
public void onRequestPermissionsResult(int requestCode,
                       String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case CAMERA_OK: 
            if (grantResults.length > 0 && grantResults[0]
                         == PackageManager.PERMISSION_GRANTED) {
                 //用户已授权
                toSomeThing...
            } else {
                //用户拒绝权限
                .... 
            }
            break;
        }
    }
}

2.6 Android7.0 文件权限

私有文件的文件权限更改,尝试传递 file://URI 会触发 FileUriExposedException。分享私有文件内容的推荐方法是使用FileProvider。

FileProvider类使用

2.6.1 在manifest中添加Provider
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<manifest>
    ...
    <application>
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.mydomain.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            ...
        </provider>
        ...
    </application>
</manifest>
2.6.2 创建一个xml文件,比如file_paths.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="my_images" path="images/"/>
    ...
</paths>

路径说明

<files-path name="name" path="path/" />   
   <!--等同于Context.getFilesDir()下面的path文件夹的所有文件--> 

<cache-path name="name" path="path/" />  
   <!--等同于Context.getCacheDir()下面的path文件夹--> 

<external-path name="name" path="path/" /> 
   <!--等同于Environment.getExternalStorageDirectory()下面的path文件夹--> 

<external-files-path name="name" path="path/" /> 
   <!--等同于 Context#getExternalFilesDir(String)下面子文件path文件夹--> 

<external-cache-path name="name" path="path/" /> 
   <!--相当于 Context.getExternalCacheDir()下边的path文件夹--> 
2.6.3 添加路径信息到provier
1
2
3
4
5
6
7
8
9
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.mydomain.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>
2.6.4 在代码中使用
1
2
3
File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);

2.8 Android8.0版本

安装apk权限:在 Android 8.0 中,安装未知应用权限提高了安装未知来源应用时的安全性。此权限与其他运行时权限一样,会与应用绑定。

1
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

三 ROM适配

主要是适配手机厂商对于ROM的改动。如:

1.沉浸式状态栏适配

2.屏幕角标的实现

3.屏幕圆角实现和适配