现在一些新的手机系统基本都达到了8.0系统,9.0系统也即将上市,以前大家开发时使用的SDK都是26以下版本,所以还没有涉及到适配问题。但是根据最新应用市场要求,以后上传的apk的sdk必须都得是26以上才可以,TargetSdkVersion对开发者来说,指的是应用在开发阶段能够支持到的目标系统版本。
应用在运行时,系统会检查其TargetSdkVersion配置,如果当前系统版本低于或等于此项配置,表示应用开发者已经在当前系统上进行了全面的测试,无需做任何兼容性处理。如果当前系统版本高于此项配置,表示此应用开发时没有在当前系统版本上进行测试,这时系统就会执行一系列的兼容性策略。
建议开发者将TargetSdkVersion 配置成26,这会显著提升应用安全性以及性能并全面改善用户体验。
而8.0系统还是有一些不同的地方,如果不注意将会出现闪退的情况,所以我们还是很有必要总结一下Android 8.0的适配问题。
1、运行权限适配
在Android8.0之前,权限申请时可以根据权限组进行申请,就是你申请了写权限,则系统会默认申请读权限。但是8.0以后则需要将两个权限都在androidMaifest中进行申请了。
2、通知适配
Android 8.0以后增加了渠道功能,用户可以对通知增加渠道描述,如果没有添加渠道,可能通知不会弹出来,最新添加渠道方式如下:
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
//分组(可选)
//groupId要唯一
String groupId = "group_001";
NotificationChannelGroup group = new NotificationChannelGroup(groupId, "广告");
//创建group
notificationManager.createNotificationChannelGroup(group);
//channelId要唯一
String channelId = "channel_001";
NotificationChannel adChannel = new NotificationChannel(channelId,
"推广信息", NotificationManager.IMPORTANCE_DEFAULT);
//补充channel的含义(可选)
adChannel.setDescription("推广信息");
//将渠道添加进组(先创建组才能添加)
adChannel.setGroup(groupId);
//创建channel
notificationManager.createNotificationChannel(adChannel);
//创建通知时,标记你的渠道id
Notification notification = new Notification.Builder(MainActivity.this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentTitle("一条新通知")
.setContentText("这是一条测试消息")
.setAutoCancel(true)
.build();
notificationManager.notify(1, notification);
}
}
3、悬浮窗适配
使用 SYSTEM_ALERT_WINDOW 权限的应用无法再使用以下窗口类型来在其他应用和系统窗口上方显示提醒窗口:
TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR
相反,应用必须使用名为 TYPE_APPLICATION_OVERLAY 的新窗口类型。
也就是说需要在之前的基础上判断一下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
}else {
mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
}
4、安装APK
Android 8.0去除了“允许未知来源”选项,所以如果我们的App有安装App的功能(检查更新之类的),那么会无法正常安装。
首先在AndroidManifest文件中添加安装未知来源应用的权限:
这样系统会自动询问用户完成授权。当然你也可以先使用 canRequestPackageInstalls()查询是否有此权限,如果没有的话使用Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES这个action将用户引导至安装未知应用权限界面去授权。
private static final int REQUEST_CODE_UNKNOWN_APP = 100;
private void installAPK(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
boolean hasInstallPermission = getPackageManager().canRequestPackageInstalls();
if (hasInstallPermission) {
//安装应用
} else {
//跳转至“安装未知应用”权限界面,引导用户开启权限
Uri selfPackageUri = Uri.parse("package:" + this.getPackageName());
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, selfPackageUri);
startActivityForResult(intent, REQUEST_CODE_UNKNOWN_APP);
}
}else {
//安装应用
}
}
//接收“安装未知应用”权限的开启结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_UNKNOWN_APP) {
installAPK();
}
}
5、SharedPreferences闪退
8.0以后不能使用这个获取SharedPreferences read = getSharedPreferences(RELEASE_POOL_DATA, MODE_WORLD_READABLE),会闪退,修改成MODE_PRIVATE。
6、 SecurityException的闪退
问题原因:项目使用了ActiveAndroid,在 8.0 或 8.1 系统上使用 26 或以上的版本的 SDK 时,调用 ContentResolver 的 notifyChange 方法通知数据更新,或者调用 ContentResolver 的 registerContentObserver 方法监听数据变化时,会出现上述异常。
解决方案:
(1)在清单文件配置
7、广播最好动态注册,大部分广播不知道静态注册
1,在需要监听的页面进行动态注册
IntentFilter filter = new IntentFilter();
filter.addAction(GUANGBO);
mUpdateAppReceiver = new UpdateAppReceiver();
registerReceiver(mUpdateAppReceiver, filter);
2,在页面销毁的时候(onDestory())记得取消监听
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mUpdateAppReceiver);
}
8、自适应图标
可以设计多个图层来显示图标的动态显示效果
在以前的 Android 版本中,图标大小定义为 48 x 48 dp。现在你必须按照以下的规范定义你的图层大小:
首先你需要在 Application 标签中加入 Android:icon 属性,定义你的 icon 图标。其次如果你需要创建一个原型的 icon,你还需要加入 Android:roundIcon 属性。
接下来,你需要 res/mipmap-anydpi/ic_launcher.xml 文件中定义您的图层。在 选项中加入您的前景和背景图层。