AndroidP新特性適配處理

前言

Android 9 Pie終于面向全球發(fā)布,有道是“宜未雨而綢繆糟描,毋臨渴而掘井”偎球,為了避免9.0更新將引發(fā)的一系列適配問(wèn)題,我們需要提早了解一下9.0帶來(lái)了哪些與開(kāi)發(fā)者息息相關(guān)的影響瓣履。

Android P 模擬器搭建

目前AndroidP只在少數(shù)的幾款手機(jī)上能夠升級(jí),如果暫時(shí)還不想購(gòu)買手機(jī)练俐,模擬器就會(huì)是最佳選擇袖迎,首先在AndroidStudio的Tools目錄下找到Android,點(diǎn)開(kāi)目錄下的AVD Manager腺晾。


AVD路徑.png

在彈出的窗口中選擇Craet Virtual Device按鈕燕锥。根據(jù)提示下載API 28的SDK資源與Image資源等,下載速度較慢悯蝉,最好準(zhǔn)備好梯子归形。


下載API 28 資源.png

下載完之后別忘了更新gradle配置
    androidTargetSdkVersion = 28
    androidCompileSdkVersion = 28

限制非Activity場(chǎng)景啟動(dòng)Activity

從Android P開(kāi)始,只有當(dāng)Intent flag中指定了FLAG_ACTIVITY_NEW_TASK鼻由,才允許在非Activity場(chǎng)景啟動(dòng)Activity暇榴。如果不在Intent添加FLAG_ACTIVITY_NEW_TASK厚棵,將無(wú)法通過(guò)非Activity的Context啟動(dòng)一個(gè)Activity,并且會(huì)拋異常跺撼。
例如:


    @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);
    }

因?yàn)闆](méi)有添加FLAG_ACTIVITY_NEW_TASK窟感,當(dāng)Service的onCreat方法執(zhí)行的時(shí)候會(huì)拋出異常。


未添加FLAG_ACTIVITY_NEW_TASK異常.png

前臺(tái)服務(wù)需要添加權(quán)限

在安卓P版本之后歉井,必須要授予FOREGROUND_SERVICE權(quán)限柿祈,才能夠使用前臺(tái)服務(wù),否則會(huì)拋出異常哩至。
例如:

    @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("前臺(tái)服務(wù)測(cè)試")
                .setContentText("前臺(tái)服務(wù)需要增加 FOREGROUND_SERVICE 權(quán)限")
                .setChannelId(channelID)
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .setContentIntent(pi)
                .build();
        startForeground(1, notification);
    }

這是一個(gè)帶Notification的簡(jiǎn)單前臺(tái)服務(wù)躏嚎, 如果我們沒(méi)有在AndroidManifest中注冊(cè)FOREGROUND_SERVICE權(quán)限,在Service啟動(dòng)的時(shí)候會(huì)拋出SecurityException異常菩貌。


缺少前臺(tái)服務(wù)權(quán)限異常.png

對(duì)此卢佣,我們只需要在AndroidManifest添加對(duì)應(yīng)的權(quán)限即可,這個(gè)權(quán)限是普通權(quán)限箭阶,不需要?jiǎng)討B(tài)申請(qǐng)虚茶。

 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
前臺(tái)服務(wù)權(quán)限.png

限制靜態(tài)廣播的接收

升級(jí)安卓P之后,隱式廣播將會(huì)被全面禁止仇参,在AndroidManifest中注冊(cè)的Receiver將不能夠生效嘹叫,如果你的清單文件中有如下的監(jiān)聽(tīng)器:

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

你需要移除上面的代碼,并在應(yīng)用中進(jìn)行動(dòng)態(tài)注冊(cè)诈乒,例如:

    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禁用設(shè)置orientation

非全屏透明頁(yè)面不允許設(shè)置方向罩扇,否則會(huì)拋Caused by: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation異常,解決方案:android:windowIsTranslucent設(shè)置為false怕磨。

非 SDK 接口訪問(wèn)限制

在 Android P 版本中喂饥,谷歌加入了非 SDK 接口使用限制,無(wú)論是通過(guò)調(diào)用肠鲫、反射還是JNI等方式员帮,開(kāi)發(fā)者都無(wú)法對(duì)非 SDK 接口進(jìn)行訪問(wèn),此接口的濫用將會(huì)帶來(lái)嚴(yán)重的系統(tǒng)兼容性問(wèn)題导饲。 在開(kāi)發(fā)過(guò)程中捞高,開(kāi)發(fā)者如果調(diào)用了非 SDK 接口,會(huì)導(dǎo)致應(yīng)用出現(xiàn)crash帜消,無(wú)法啟動(dòng)棠枉;或在運(yùn)行過(guò)程中出現(xiàn)崩潰浓体、閃退等現(xiàn)象泡挺;也可能導(dǎo)致應(yīng)用功能不可用等嚴(yán)重兼容性問(wèn)題,其影響范圍波及所有調(diào)用此接口的應(yīng)用命浴。
那么什么是非SDK接口呢娄猫,所謂非SDK接口就是所有不能夠在谷歌官網(wǎng)上查詢到的接口贱除,谷歌提供了查詢接口的網(wǎng)站
https://developer.android.google.cn/reference/packages
非SDK接口的類型,分為三類
(1)Light grey list: targetSDK>=P時(shí)媳溺,警告月幌;
(2)Dark grey list: targetSDK<P時(shí),警告悬蔽;>=p時(shí)扯躺,不允許調(diào)用;
(3)Black list:三方應(yīng)用不允許調(diào)用蝎困。

非SDK接口分類.jpg

例如我們通過(guò)反射修改Dialog窗體的顏色:

        try {
            //通過(guò)反射的方式來(lái)更改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版本將不能夠正常運(yùn)行,會(huì)拋出NoSuchFieldException禾乘,對(duì)于諸如此類的調(diào)用官方private方法或者@hide方法澎埠,都將不能使用。


異常類型.png

劉海屏適配

谷歌P版本提供了統(tǒng)一的挖孔屏方案和三方適配挖孔屏方案:對(duì)于有狀態(tài)欄的頁(yè)面始藕,不會(huì)受到挖孔屏特性的影響蒲稳;全屏顯示的頁(yè)面,系統(tǒng)挖孔屏方案會(huì)對(duì)應(yīng)用界面做下移避開(kāi)挖孔區(qū)顯示伍派;已經(jīng)適配的P的應(yīng)用的全屏頁(yè)面可以通過(guò)谷歌提供的適配方案使用挖孔區(qū)江耀,真正做到全屏顯示。


劉海屏.png

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

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

  1. 新窗口布局模式拙已,允許應(yīng)用程序請(qǐng)求是否在挖孔區(qū)域布局:
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值說(shuō)明:
    (1)LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:默認(rèn)情況下决记,全屏窗口不會(huì)使用到挖孔區(qū)域,
    非全屏窗口可正常使用挖孔區(qū)域倍踪。
    (2)LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS:窗口聲明使用挖孔區(qū)域
    (3)LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:窗口聲明不使用挖孔區(qū)域

sensor和麥克風(fēng)后臺(tái)管控

限制sensor event向后臺(tái)應(yīng)用或服務(wù)的傳輸系宫,對(duì)前臺(tái)應(yīng)用無(wú)影響;主要是考慮隱私原因建车,功耗不是主要?jiǎng)訖C(jī)扩借;對(duì)應(yīng)用來(lái)說(shuō)是很大的變化。影響范圍:應(yīng)用處于idle和gone的狀態(tài)就會(huì)被管控缤至,切換到后臺(tái)一分鐘應(yīng)用就會(huì)進(jìn)入idle狀態(tài)潮罪,但是有前臺(tái)服務(wù)的不會(huì)進(jìn)入idle狀態(tài)。
問(wèn)題定位领斥,確認(rèn)是不是該特性管控導(dǎo)致的:
(1)查看應(yīng)用狀態(tài):adb shell dumpsys activity p com.sina.weibo 嫉到,然后搜索UID states查看UID的狀態(tài)。
(2)查看應(yīng)用有沒(méi)有注冊(cè)監(jiān)聽(tīng)sensor情況:adb shell dumpsys sensorservice
適配方案:需要后臺(tái)訪問(wèn)麥克風(fēng)月洛、sensor和camera的時(shí)候增加前臺(tái)服務(wù)何恶。如果滿足以下任意條件,應(yīng)用將被視為處于前臺(tái):
(1)具有可見(jiàn) Activity(不管該 Activity 已啟動(dòng)還是已暫停)嚼黔。
(2)具有前臺(tái)服務(wù)细层。
(3)另一個(gè)前臺(tái)應(yīng)用已關(guān)聯(lián)到該應(yīng)用(不管是通過(guò)綁定到其中一個(gè)服務(wù)惜辑,還是通過(guò)使用其中一個(gè)內(nèi)容提供程序)。 例如疫赎,如果另一個(gè)應(yīng)用綁定到該應(yīng)用的服務(wù)盛撑,那么該應(yīng)用處于前臺(tái)。

設(shè)備識(shí)別碼

通過(guò)Build.SERIAL不再能夠獲取到真實(shí)數(shù)據(jù)捧搞,Build.serial:unknown抵卫,需要通過(guò)Build.getSerial()獲取。同時(shí)需要用戶授權(quán)READ_PHONE_STATE權(quán)限胎撇。

示例代碼

GitHub完整示例代碼

參考文獻(xiàn)

(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陌僵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子创坞,更是在濱河造成了極大的恐慌碗短,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件题涨,死亡現(xiàn)場(chǎng)離奇詭異偎谁,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)纲堵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門巡雨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人席函,你說(shuō)我怎么就攤上這事铐望。” “怎么了茂附?”我有些...
    開(kāi)封第一講書人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵正蛙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我营曼,道長(zhǎng)乒验,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任蒂阱,我火速辦了婚禮锻全,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘录煤。我一直安慰自己鳄厌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布妈踊。 她就那樣靜靜地躺著了嚎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪响委。 梳的紋絲不亂的頭發(fā)上新思,一...
    開(kāi)封第一講書人閱讀 52,158評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音赘风,去河邊找鬼夹囚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛邀窃,可吹牛的內(nèi)容都是我干的荸哟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼瞬捕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鞍历!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起肪虎,我...
    開(kāi)封第一講書人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤劣砍,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后扇救,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體刑枝,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年迅腔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了装畅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片银受。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡并徘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出剂癌,到底是詐尸還是另有隱情锌雀,我是刑警寧澤蚂夕,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站腋逆,受9級(jí)特大地震影響双抽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜闲礼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一牍汹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧柬泽,春花似錦慎菲、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至第煮,卻和暖如春解幼,著一層夾襖步出監(jiān)牢的瞬間抑党,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工撵摆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留底靠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓特铝,卻偏偏與公主長(zhǎng)得像暑中,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鲫剿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容