前言:
由于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'
}
具体截图:
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限制解决方案的有可能回报下面这种异常:
解决:
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()//保持这个放在底部
}
具体截图:
接着编译,
如果出现编译异常:
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'}
因为已经在配置文件中添加了第三方依赖,所以我们可以直接使用别人封装好的动态获取权限的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/
下载完之后根据他的接入文档重新接入一遍SDK就可以,这里就不详细描述了,毕竟我怎么写都没有别人的接入文档详细0.0
更新完个推SDK后,点击创建推送:
选择目标用户指定到你的测试机,发送通知,如果能成功接收到通知就是适配成功了。
完成适配后,使用Androidstudio3.2进行打包,我这里出现警告fastjson没有找到相关的类或接口。解决:更新fastjson依赖1.2.51版本,更新完注意把旧版的jar包删除,不然会报jar包重复,导致打包失败。
还要注意的是,8.0移除了静态广播,所以广播要改成动态注册!