Android版本适配

389 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

Android 8

权限

在Android 8之前,如果一个应用申请运行时权限并且用户授予其权限,那么Android系统会将该权限同组的其他权限也一并授予应用。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

//申请读权限
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, requestCode);

比如上面我们只是申请了SD卡的读取权限,但是一旦用户授予了该权限,我们的APP也会同时具有SD卡的写权限(WRITE_EXTERNAL_STORAGE),而对于针对 Android 8.0 的应用,此行为已被纠正,Android系统只会授予明确申请的权限。

广播

移除掉了所有的隐式广播,对于针对 Android 8.0 的应用,我们需要使用显示广播进行注册。

透明主题的Activity

在做一些支付回调的界面的时候,我们喜欢将Activity主题设置为透明,但是在targetSdk=27,Android系统版本为8.0的手机上会出现一个bug。

java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation

只有不透明的全屏Activity可以自主设置界面方向。要解决这个问题,我们要么舍弃透明效果,要么去掉screenOrientation属性。

安装APK

Android 8.0去除了“允许未知来源”选项,如果我们的APP有安装apk的功能,就需要在AndroidManifest.xml文件中添加安装未知来源应用的权限。

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

这样APP在安装apk的时候会自动询问用户并完成授权。

如果APP是应用商店类的,我们希望在安装之前就引导用户完成授权,这时候可以先检测是否具有安装权限。如果没有直接跳转权限界面,引导用户开启权限。

boolean hasPermission = getPackageManager().canRequestPackageInstalls()

canRequestPackageInstalls()方法返回是否具有安装apk的权限。

Uri uri = Uri.parse("package:" + this.getPackageName());
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, uri);
startActivityForResult(intent, 100);

如果没有权限,就跳转至“安装未知应用”权限界面,引导用户开启权限。

通知栏

Android 8.0 引入了通知渠道,每个通知都需要配置渠道id和渠道名称,这样可以方便用户单独去关闭某个通知。

在8.0之前使用NotificationCompat.Builder就可以创建通知然后使用NotificationManager显示出来。

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(MainActivity.this)
        .setContentTitle("title")  
        .setContentText("content")
        .setWhen(System.currentTimeMillis())  
        .setSmallIcon(R.mipmap.ic_launcher)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher)) .build();
manager.notify(1,notification);

但是在8.0开始,我们还需要设置渠道的id和渠道的名称,然后在使用NotificationCompat.Builder创建通知的时候使用该渠道显示通知。

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "channel_chat";
String channelName = "name";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
notificationManager.createNotificationChannel(channel); 
Notification notification = new Notification.Builder(MainActivity.this, channelId)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                    .setContentTitle("title")
                    .setContentText("content")
                    .build();
notificationManager.notify(1, notification);