AndroidP新特性适配处理

前言

Android 9 Pie终于面向全球发布,有道是“宜未雨而绸缪,毋临渴而掘井”,为了避免9.0更新将引发的一系列适配问题,我们需要提早了解一下9.0带来了哪些与开发者息息相关的影响。

Android P 模拟器搭建

目前AndroidP只在少数的几款手机上能够升级,如果暂时还不想购买手机,模拟器就会是最佳选择,首先在AndroidStudio的Tools目录下找到Android,点开目录下的AVD Manager。


AVD路径.png

在弹出的窗口中选择Craet Virtual Device按钮。根据提示下载API 28的SDK资源与Image资源等,下载速度较慢,最好准备好梯子。


下载API 28 资源.png

下载完之后别忘了更新gradle配置
    androidTargetSdkVersion = 28
    androidCompileSdkVersion = 28

限制非Activity场景启动Activity

从Android P开始,只有当Intent flag中指定了FLAG_ACTIVITY_NEW_TASK,才允许在非Activity场景启动Activity。如果不在Intent添加FLAG_ACTIVITY_NEW_TASK,将无法通过非Activity的Context启动一个Activity,并且会抛异常。
例如:


    @Override
    public void onCreate() {
        super.onCreate();
        Intent intent = new Intent(this, HomeActivity.class);
        //不加 FLAG_ACTIVITY_NEW_TASK 将抛出异常
        //intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

因为没有添加FLAG_ACTIVITY_NEW_TASK,当Service的onCreat方法执行的时候会抛出异常。


未添加FLAG_ACTIVITY_NEW_TASK异常.png

前台服务需要添加权限

在安卓P版本之后,必须要授予FOREGROUND_SERVICE权限,才能够使用前台服务,否则会抛出异常。
例如:

    @Override
    public void onCreate() {
        super.onCreate();
        String channelID = "1";
        String channelName = "channel_name";
        NotificationChannel channel = new NotificationChannel(channelID, channelName, NotificationManager.IMPORTANCE_HIGH);
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.createNotificationChannel(channel);
        Intent intent = new Intent(this, ForegroundActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
        Notification notification = new NotificationCompat.Builder(this)
                .setContentTitle("前台服务测试")
                .setContentText("前台服务需要增加 FOREGROUND_SERVICE 权限")
                .setChannelId(channelID)
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .setContentIntent(pi)
                .build();
        startForeground(1, notification);
    }

这是一个带Notification的简单前台服务, 如果我们没有在AndroidManifest中注册FOREGROUND_SERVICE权限,在Service启动的时候会抛出SecurityException异常。


缺少前台服务权限异常.png

对此,我们只需要在AndroidManifest添加对应的权限即可,这个权限是普通权限,不需要动态申请。

 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
前台服务权限.png

限制静态广播的接收

升级安卓P之后,隐式广播将会被全面禁止,在AndroidManifest中注册的Receiver将不能够生效,如果你的清单文件中有如下的监听器:

        <receiver android:name="com.yanghaoyi.receiver.UpdateReceiver">
            <intent-filter>
                <action android:name="com.yanghaoyi.action.ACTION_UPDATE" />
            </intent-filter>
        </receiver>

你需要移除上面的代码,并在应用中进行动态注册,例如:

    private void registerReceiver(){
        myReceiver = new MyReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(TOAST_ACTION);
        registerReceiver(myReceiver, intentFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myReceiver);
    }


非全屏透明Activity禁用设置orientation

非全屏透明页面不允许设置方向,否则会抛Caused by: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation异常,解决方案:android:windowIsTranslucent设置为false。

非 SDK 接口访问限制

在 Android P 版本中,谷歌加入了非 SDK 接口使用限制,无论是通过调用、反射还是JNI等方式,开发者都无法对非 SDK 接口进行访问,此接口的滥用将会带来严重的系统兼容性问题。 在开发过程中,开发者如果调用了非 SDK 接口,会导致应用出现crash,无法启动;或在运行过程中出现崩溃、闪退等现象;也可能导致应用功能不可用等严重兼容性问题,其影响范围波及所有调用此接口的应用。
那么什么是非SDK接口呢,所谓非SDK接口就是所有不能够在谷歌官网上查询到的接口,谷歌提供了查询接口的网站
https://developer.android.google.cn/reference/packages
非SDK接口的类型,分为三类
(1)Light grey list: targetSDK>=P时,警告;
(2)Dark grey list: targetSDK<P时,警告;>=p时,不允许调用;
(3)Black list:三方应用不允许调用。

非SDK接口分类.jpg

例如我们通过反射修改Dialog窗体的颜色:

        try {
            //通过反射的方式来更改dialog中文字大小、颜色
            Field mAlert = AlertDialog.class.getDeclaredField("mAlert");
            mAlert.setAccessible(true);
            Object mAlertController = mAlert.get(normalDialog);

            Field mMessage = mAlertController.getClass().getDeclaredField("mMessageView");
            mMessage.setAccessible(true);
            TextView mMessageView = (TextView) mMessage.get(mAlertController);
            mMessageView.setTextSize(23);
            mMessageView.setTextColor(Color.RED);
            Field mTitle = mAlertController.getClass().getDeclaredField("mTitleView");
            mTitle.setAccessible(true);
            TextView mTitleView = (TextView) mTitle.get(mAlertController);
            mTitleView.setTextSize(20);
            mTitleView.setTextColor(Color.RED);
        }catch (Exception e){
            Toast.makeText(NotSDKInterfaceActivity.this,e.getLocalizedMessage(),Toast.LENGTH_LONG).show();
        }

此方法在安卓P版本将不能够正常运行,会抛出NoSuchFieldException,对于诸如此类的调用官方private方法或者@hide方法,都将不能使用。


异常类型.png

刘海屏适配

谷歌P版本提供了统一的挖孔屏方案和三方适配挖孔屏方案:对于有状态栏的页面,不会受到挖孔屏特性的影响;全屏显示的页面,系统挖孔屏方案会对应用界面做下移避开挖孔区显示;已经适配的P的应用的全屏页面可以通过谷歌提供的适配方案使用挖孔区,真正做到全屏显示。


刘海屏.png

P版本三方适配挖孔屏方案:

  1. 新增挖孔屏挖孔尺寸和位置接口:
class WindowInsets {
  DisplayCutout getDisplayCutout();
}
class DisplayCutout {
  int getSafeInsetLeft();
  int getSafeInsetTop();
  int getSafeInsetRight();
  int getSafeInsetBottom();
  Region getBounds();
}

  1. 新窗口布局模式,允许应用程序请求是否在挖孔区域布局:
class WindowManager.LayoutParams {
  int layoutInDisplayCutoutMode;
  final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
  final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
  final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
}

  1. layoutInDisplayCutoutMode值说明:
    (1)LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:默认情况下,全屏窗口不会使用到挖孔区域,
    非全屏窗口可正常使用挖孔区域。
    (2)LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS:窗口声明使用挖孔区域
    (3)LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:窗口声明不使用挖孔区域

sensor和麦克风后台管控

限制sensor event向后台应用或服务的传输,对前台应用无影响;主要是考虑隐私原因,功耗不是主要动机;对应用来说是很大的变化。影响范围:应用处于idle和gone的状态就会被管控,切换到后台一分钟应用就会进入idle状态,但是有前台服务的不会进入idle状态。
问题定位,确认是不是该特性管控导致的:
(1)查看应用状态:adb shell dumpsys activity p com.sina.weibo ,然后搜索UID states查看UID的状态。
(2)查看应用有没有注册监听sensor情况:adb shell dumpsys sensorservice
适配方案:需要后台访问麦克风、sensor和camera的时候增加前台服务。如果满足以下任意条件,应用将被视为处于前台:
(1)具有可见 Activity(不管该 Activity 已启动还是已暂停)。
(2)具有前台服务。
(3)另一个前台应用已关联到该应用(不管是通过绑定到其中一个服务,还是通过使用其中一个内容提供程序)。 例如,如果另一个应用绑定到该应用的服务,那么该应用处于前台。

设备识别码

通过Build.SERIAL不再能够获取到真实数据,Build.serial:unknown,需要通过Build.getSerial()获取。同时需要用户授权READ_PHONE_STATE权限。

示例代码

GitHub完整示例代码

参考文献

(1) https://android.googlesource.com/platform/frameworks/base/+/android-p-preview-1
(2) https://source.android.com/source/downloading.html
(3)https://developer.android.com/preview/migration.html
(4)https://developer.android.com/preview/overview.html
(5)https://developer.android.com/preview/features.html
(6) https://developer.android.com/preview/download.html
(7) https://developer.huawei.com/consumer/cn/devservice/doc/50115

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容