背景
现在国内Android市场都要求targetSdkVersion 升级到26,否则不允许上架或者更新。主要要求是:2019年5月1日后,未达到要求的新应用,拒绝提交应用市场。2019年8月1日后,未达到要求的已上架应用,拒绝更新。因此就开始了升级的踩坑之旅。
1.相机拍照崩溃(Android7.0引入“私有目录被限制访问”,“StrictModeAPI政策”)
升级之后使用之前的方式打开系统相机的方式会产生崩溃。会报下面的错误
Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.ct.client/files/com.ct.client/camere/1547090088847.jpg exposed beyond app through ClipData.Item.getUri()
解决方法:
第一步:在AndroidManifest.xml清单文件中注册provider
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.wr.test.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
第二步:指定共享文件的目录,需要在res文件夹中新建xml目录,并且创建file_pathswen文件
<?xml version="1.0" encoding="utf-8"?>
<!-- path:需要临时授权访问的路径(.代表所有路径)
name:就是你给这个访问路径起个名字-->
<paths>
<external-path
name="files_root"
path="Android/data/com.wr.test/" />
<external-path
name="external_storage_root"
path=" " />
</paths>
path="",它代码根目录,也就是说你可以向其它的应用共享根目录及其子目录下任何一个文件了。如果你将path设为path="text",那么它代表着根目录下的text目录(/storage/emulated/0/text),如果你向其它应用分享text目录范围之外的文件是不行的。
第三步:
File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/"
+ SystemClock.currentThreadTimeMillis() + ".jpg");
imageUri = Uri.fromFile(fileUri);
Intent intentCamera = new Intent();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
imageUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileProvider", fileUri);//通过FileProvider创建一个content类型的Uri
intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文
}
intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
//将拍照结果保存至photo_file的Uri中,不保留在相册中
intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intentCamera, TAKE_PHOTO_REQUEST);
2.MODE_WORLD_READABLE模式废弃(SharedPreferences模式)
解决方法:
MODE_WORLD_READABLE 模式换成 MODE_PRIVATE
3. 8.0以上版本升级无法跳转安装页面(Android8.0强化了权限管理)
解决方法:
第一步:在manifast中新增权限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
第二步:把
Intent intent = new Intent(Intent.ACTION_VIEW)
换为
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
4.解析包安装失败
解决方法:
安装时把
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
这句话放在
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
前面
5.通知栏不显示(Android8.0引入了通知渠道)
解决方法:
String id = getApplicationContext().getPackageName();
String name = "name";
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW);
notificationManager.createNotificationChannel(mChannel);
notification = new Notification.Builder(getApplicationContext())
.setChannelId(id)
.setContentTitle(title)
.setContentText(content)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)//用户点击就自动消失
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher).build();
} else {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle(title)
.setContentText(content)
.setSmallIcon(R.mipmap.ic_launcher)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)//用户点击就自动消失
.setContentIntent(pendingIntent)
.setOngoing(true)
.setChannelId(id);//无效
notification = notificationBuilder.build();
}
notificationManager.notify(0, notification);
6.隐式广播限制(静态广播不可用)
安卓8.0对广播进行了限制接收广播消耗资源如果多个应用注册了系统广
播会持续消耗资源。
解决方法:
如果是注册系统广播不要在清单文件中注册了要根据自己的需要在代码中
注册比如少儿项目清单文件中注册了个像监听网络变化和投屏监听网络
的广播这些都可以在项目开启时动态注册
如果是自定义广播尽量也要动态注册如果实在需要静态注册可以尝试在
发送的时候携带intent.addFlags(0x01000000);
7.权限的动态申请(Android6.0引入的动态权限控制)
解决方法:
对运行时权限进行动态申请,建议使用easyPermission进行动态申请,也是Google官方建议使用的权限申请库。
easyPermission github地址
8..低电耗模式和应用待机模式限制
8.0系统待机一段时间后会进入低电量模式低电量模式下闹钟类AlarmManager功能会受到影响
解决方法:
设置闹钟时使用setInexactRepeating这个方法也是设置重复闹钟他会把几
个时间差不多的闹钟合并成一个执行相对来说更省电如果还是不行的话就要
申请电池白名单
PowerManagerpowerManager=(PowerManager)
activity.getSystemService(Context.POWER_SERVICE);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
//判断应用是否在去除低电耗的白名单中
if (!powerManager.isIgnoringBatteryOptimizations(activity.getPackageName())){
//申请白名单 ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS意图intent
Intentintent=new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
activity.startActivity(intent);
}
}
以上就是遇到的问题和解决方法。
本文参考文章
Android8.0适配——targetSdkVersion 23升级26遇到的坑
targetSdkVersion升级为26之后的适配