适配Android6.0到8.0详细过程——小白教程

前言:

由于GooglePlay在2018年11月1日开始上架项目要求targetSdkVersion在26以上,因此只能版本适配了。我的项目版本是22,也就是Android5.1,之前也没有做过版本适配,只能一边查资料一边摸索着搞,如果有不对的地方,或者有更好的解决方案,欢迎联系指出!

准备工作:

要适配Android8.0首先要先把AndroidStudio升级到AndroidStudio3.0以上版本。

打开project.properties,设置

target=android-26

打开配置文件build.gradle,修改targetSdkVersion,compileSdkVersion为26以上,更新gradle版本为最新版本,我这里更新的是gradle:3.2.1

具体如下:

compileSdkVersion 26
targetSdkVersion 26

dependencies {
    classpath
'com.android.tools.build:gradle:3.2.1'
}

具体截图:

适配Android6.0到8.0详细过程——小白教程_第1张图片

适配Android6.0到8.0详细过程——小白教程_第2张图片

buildToolsVersion 会在更新gradle时自动更新成28.0.3 或更新版本。

=========分割线==============

如果有用到代码混淆的话,可能回遇到下面这个异常:

更新前代码:

    buildTypes {

release {

            // 是否进行混淆

            minifyEnabled false

            zipAlignEnabled true

            shrinkResources true

            // 混淆文件的位置

proguardFiles getDefaultProguardFile('proguard-project.txt'), 'proguard-project.txt'

            buildConfigField "boolean", "LOG_DEBUG", "false"

        }    debug {

            buildConfigField "boolean", "LOG_DEBUG", "true"

        }

}

更新后报出异常:

User supplied default proguard base extension name is unsupported

解决:

proguardFile ('TIS-SmarthomeV5.0.3/.../proguard-project.txt')

异常:Removing unused resources requires unused code shrinking to be turned on.

解决:

minifyEnabled true  //这里原本是false改成true

如果不使用代码混淆:

// 是否进行混淆

minifyEnabled false
zipAlignEnabled false

shrinkResources false

=======分割线========

编译,根据错误提示,如果之前是用compile的,把compile改成implementation,testCompile改成testImplementation, instrumentTest改成androidTest。

另外如果项目有使用到multidex 突破64k限制解决方案的有可能回报下面这种异常:

适配Android6.0到8.0详细过程——小白教程_第3张图片

解决:

implementation 'com.android.support:multidex:1.0.3'

把依赖改成最新版,我这里是改成1.0.3,然后就能解决Failed to resolve: multidex这个异常了。

接着下面那个异常是这样解决的:

修改项目根目录的那个build.gradle文件中repositories, 保持google()在第一位置:
allprojects {
    repositories {
        google()//
保持这个放在顶部
        mavenCentral()
        maven {
            url "https://jitpack.io"
        }
        maven{
            url 'https://maven.google.com'
        }
        jcenter()//
保持这个放在底部
    }

具体截图:

适配Android6.0到8.0详细过程——小白教程_第4张图片

接着编译,

如果出现编译异常:

Please correct the above warnings first.

看Messages 视图提示,可以在你的混淆文件proguard-rules.pro里面添加下面这句代码屏蔽警告:

-ignorewarnings

继续编译,有可能会出现v4jar包keyeventcompat不存在的异常:

Error:(30, 31) 错误: 找不到符号
符号:    KeyEventCompat

位置: 程序包 android.support.v4.view

解决:

KeyEventCompat类被取消了 hasNoModifiers方法已经被KeyEvent实现了

报错:

if (KeyEventCompat.hasNoModifiers(event)) {

    handled = arrowScroll(FOCUS_FORWARD);

} else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) {

    handled = arrowScroll(FOCUS_BACKWARD);

}

改成:

 

if (event.hasNoModifiers()) {

    handled = arrowScroll(FOCUS_FORWARD);

} else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {

    handled = arrowScroll(FOCUS_BACKWARD);

}

=======================分割线======================

完成以上操作可以成功编译运行之后,开始先适配6.0的动态权限:

Android6.0开始,官方对权限的要求越来越严格,所以一些危险权限需要在程序中动态获取,让用户点击允许权限才能获取,普通权限和以前没区别,可以直接在清单文件里面配置获取。而危险权限在清单文件里面配置了,如果用户没有点击允许一样是获取不到的。具体哪些是危险权限,哪些是普通权限可以自己在网上查一下,这里就不详细说了。

首先在build.gradle中的dependencies里面添加第三方权限工具,这里使用闫振杰封装的第三方依赖:

dependencies {implementation 'com.yanzhenjie:permission:2.0.0-rc4'}

适配Android6.0到8.0详细过程——小白教程_第5张图片

因为已经在配置文件中添加了第三方依赖,所以我们可以直接使用别人封装好的动态获取权限的API。一般来说,在打开程序的主activity那里我们就要向用户申请权限了,在MainActivity的onCreate()方法里面申请,代码如下:

@Override
    public void onCreate(Bundle savedInstanceState) {
        getWindow().requestFeature(Window.FEATURE_NO_TITLE);//设置无标题
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_smartbus);

  	//写你自己的初始化布局…
    
   
        //获取外部存储权限和地理位置权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { //版本在23及以上
            AndPermission.with(this).permission(Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE,
                    Permission.ACCESS_FINE_LOCATION, Permission.ACCESS_COARSE_LOCATION).onGranted(new Action() {
                @Override
                public void onAction(List permissions) {
                    //TODO
			//成功获取权限后要做的操作
                         }
            }).onDenied(new Action() {
                @Override
                public void onAction(List permissions) {
//用户拒绝权限,toast提示用户如果不允许权限有部分功能将无法使用
                    Toast.makeText(HomepageActivity.this,
                            "Rejection may result in some functionality being unavailable.",
                            Toast.LENGTH_SHORT).show();
                }
            }).start();

        }else{//低于6.0版本的
          //TODO
        }
    }

 

如果还需要其他危险权限可以直接在这里后面添加: AndPermission.with(this).permission(Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE,
                   
Permission.ACCESS_FINE_LOCATION, Permission.ACCESS_COARSE_LOCATION,

…..

)

而其他危险权限,例如相机权限,发送短信权限,可以在需要用到的地方再申请,因为一开始向用户申请太多权限的话,用户体验不是那么好。

例如,可以在打开相机的回调那里动态申请相机权限:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){//如果当前Android版本是6.0以上的
                    AndPermission.with(SettingActivity.this).permission(Permission.CAMERA).onGranted(new Action() {
                        @Override
                        public void onAction(List permissions) {
                    //用户允许权限,启用相机
                            
                    intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    intent.putExtra(MediaStore.EXTRA_OUTPUT,
                        Uri.fromFile(new File(getExternalFilesDir("TIS-Smarthome/"), "photo_BgImage.png")));
                    startActivityForResult(intent, GET_BACKGROUND_PHOTOZOOM);
                        }
                    }).onDenied(new Action() {
                        @Override
                        public void onAction(List permissions) {
                    //用户拒绝权限,toast提示拒绝权限将使某些功能无法使用
                            Toast.makeText(SettingActivity.this,
                                    "Rejection may result in some functionality being unavailable.",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }).start();
                }else {
                    //6.0以下的,直接启动相机
                    intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    intent.putExtra(MediaStore.EXTRA_OUTPUT,
                        Uri.fromFile(new File(getExternalFilesDir("TIS-Smarthome/"), "photo_BgImage.png")));
                    startActivityForResult(intent, GET_BACKGROUND_PHOTOZOOM);
                }

" TIS-Smarthome/"是项目名称,"photo_BgImage.png"是拍照存放的图片名称,也就是外部存储到你手机哪里,保存成什么名字的图片。

适配Android7.0

前面添加了两个危险权限之后,如果你的应用有使用相机功能,你会发现在应用中打开相机就闪退。因为Android官方在7.0对私有目录访问进行了限制,这里我们可以使用FileProvider来解决。(当然你得先申请了相机权限,不会申请的参照上面的代码在启动相机前申请。)

首先在清单文件AndroidManifest.xml的application标签下添加:




        
        
            

        

...

 

Provider标签部分,file_paths是我们指定的文件目录,所以需要在res文件夹下的xml文件目录下新建file_paths.xml,然后编写代码:



    
        
    

正常来说这样已经可以在7.0系统里正常调起相机了,但是有的手机在7.0之后你的APP就算有权限,给出一个URI之后手机也认为你没有权限,这个问题的解决方法是,在MyApplication的onCreate()方法中添加以下代码:

   /*2018.10.16 相机打不开问题*/
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)//如果当前Android版本大于7.0
        { StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
            StrictMode.setVmPolicy(builder.build());
        }

适配Android8.0

Android8.0主要是适配通知栏和图标。我这边只做了通知栏的适配。

由于我负责的项目是使用第三方个推的,所以适配Android8.0只需要更新个推到最新版GETUI_ANDROID_SDK_2.12.5.0就可以了。先到个推官网下载最新的个推SDKhttp://docs.getui.com/getui/version/

适配Android6.0到8.0详细过程——小白教程_第6张图片

下载完之后根据他的接入文档重新接入一遍SDK就可以,这里就不详细描述了,毕竟我怎么写都没有别人的接入文档详细0.0

更新完个推SDK后,点击创建推送:

适配Android6.0到8.0详细过程——小白教程_第7张图片

选择目标用户指定到你的测试机,发送通知,如果能成功接收到通知就是适配成功了。

完成适配后,使用Androidstudio3.2进行打包,我这里出现警告fastjson没有找到相关的类或接口。解决:更新fastjson依赖1.2.51版本,更新完注意把旧版的jar包删除,不然会报jar包重复,导致打包失败。

还要注意的是,8.0移除了静态广播,所以广播要改成动态注册!

 

你可能感兴趣的:(Android,适配Android8.0)