targetSdkVersion升級(jí)到28一些修改的地方(持續(xù)更新)

前言

Google Play應(yīng)用市場(chǎng)對(duì)于應(yīng)用的targetSdkVersion有了更為嚴(yán)格的要求凿叠。從 2018 年 8 月 1 日起戈抄,所有向 Google Play 首次提交的新應(yīng)用都必須針對(duì) Android 8.0 (API 等級(jí) 26) 開(kāi)發(fā)族阅; 2018 年 11 月 1 日起认臊,所有 Google Play 的現(xiàn)有應(yīng)用更新同樣必須針對(duì) Android 8.0扳炬。轉(zhuǎn)載請(qǐng)注明來(lái)源「Bug總柴」

以下記錄了我們升級(jí)targetSdkVersion的坑以及解決辦法之碗,希望對(duì)各位開(kāi)發(fā)者有幫助蝙眶。

錯(cuò)誤1. java.lang.IllegalStateException: Not allowed to start service Intent {}: app is in background uid UidRecord{}

原因分析

從Android8.0開(kāi)始,系統(tǒng)會(huì)對(duì)后臺(tái)執(zhí)行進(jìn)行限制褪那。初步判斷由于我們應(yīng)用在Application的onCreate過(guò)程中使用了IntentService來(lái)后臺(tái)初始化一些任務(wù)幽纷,這個(gè)時(shí)候被系統(tǒng)認(rèn)為是應(yīng)用還處于后臺(tái),從而報(bào)出了java.lang.IllegalStateException錯(cuò)誤博敬。

解決辦法

解決后臺(tái)服務(wù)的限制友浸,首先想到的辦法是將服務(wù)變成前臺(tái)服,隨即我們又遇到了另一個(gè)問(wèn)題偏窝,見(jiàn)錯(cuò)誤2

錯(cuò)誤2. android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{}

原因分析

見(jiàn)Android8.0行為變更收恢。新的 Context.startForegroundService() 函數(shù)將啟動(dòng)一個(gè)前臺(tái)服務(wù)。現(xiàn)在祭往,即使應(yīng)用在后臺(tái)運(yùn)行伦意,系統(tǒng)也允許其調(diào)用 Context.startForegroundService()。不過(guò)硼补,應(yīng)用必須在創(chuàng)建服務(wù)后的五秒內(nèi)調(diào)用該服務(wù)的 startForeground() 函數(shù)驮肉。

解決辦法

在后臺(tái)服務(wù)啟動(dòng)執(zhí)行執(zhí)行之后,通過(guò)Service.startForeground()方法傳入notification變成前臺(tái)服務(wù)已骇。需要注意的是從Android8.0開(kāi)始离钝,Notification必須制定Channel才可以正常彈出通知票编,如果創(chuàng)建Notification Channels詳見(jiàn)這里

由于我們的初衷是在啟動(dòng)程序的過(guò)程中后臺(tái)進(jìn)行一些初始化奈辰,這種前臺(tái)給用戶帶來(lái)感知的效果并不是我們所希望的,因此我們考慮可以采用另一個(gè)后臺(tái)執(zhí)行任務(wù)的方法乱豆。這里官方推薦使用JobScheduler奖恰。由于我們引入了ktx以及WorkManager,這里我們采用了OneTimeWorkRequest來(lái)實(shí)現(xiàn)宛裕。具體實(shí)現(xiàn)如下:

class InitWorker : Worker(){
    override fun doWork(): Result {
        // 把耗時(shí)的啟動(dòng)任務(wù)放在這里

        return Result.SUCCESS
    }
}

然后在Applicaiton的onCreate中調(diào)用

val initWork = OneTimeWorkRequestBuilder<InitWorker>().build()
WorkManager.getInstance().enqueue(initWork)

來(lái)執(zhí)行后臺(tái)初始化工作

錯(cuò)誤3. java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/ProtocolVersion; Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.http.ProtocolVersion"

原因分析

Android P Developer Preview的bug

解決辦法

在AndroidManifest.xml文件中<Application>標(biāo)簽里面加入

<uses-library android:name="org.apache.http.legacy" android:required="false"/>

錯(cuò)誤4. java.io.IOException: Cleartext HTTP traffic to dict.youdao.com not permitted

原因分析

從Android 6.0開(kāi)始引入了對(duì)Https的推薦支持瑟啃,與以往不同,Android P的系統(tǒng)上面默認(rèn)所有Http的請(qǐng)求都被阻止了揩尸。

<application android:usesCleartextTraffic=["true" | "false"]>

原本這個(gè)屬性的默認(rèn)值從true改變?yōu)閒alse

解決辦法

解決的辦法簡(jiǎn)單來(lái)說(shuō)可以通過(guò)在AnroidManifest.xml中的application顯示設(shè)置

<application android:usesCleartextTraffic="true">

更為根本的解決辦法是修改應(yīng)用程序中Http的請(qǐng)求為Https蛹屿,當(dāng)然這也需要服務(wù)端的支持。

錯(cuò)誤5. android.os.FileUriExposedException file exposed beyond app through Intent.getData()

原因分析

主要原因是7.0系統(tǒng)對(duì)file uri的暴露做了限制岩榆,加強(qiáng)了安全機(jī)制错负。詳見(jiàn):官方文檔
代碼里出現(xiàn)問(wèn)題的原因是,在需要安裝應(yīng)用的時(shí)候?qū)⑾螺d下來(lái)的安裝包地址傳給了application/vnd.android.package-archive的intent

解決辦法

使用FileProvider
具體代碼可參考這篇文章
簡(jiǎn)單說(shuō)明就是要在AndroidManifest里面聲明FileProvider勇边,并且在xml中聲明需要使用的uri路徑

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.fileProvider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
</provider>

對(duì)應(yīng)的xml/file_paths中指定需要使用的目錄

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="download"
        path="yddownload"/>
</paths>

錯(cuò)誤6. java.lang.SecurityException: Failed to find provider ** for user 0; expected to find a valid ContentProvider for this authority

原因分析

target到android8.0之后對(duì)ContentResolver.notifyChange() 以及 registerContentObserver(Uri, boolean, ContentObserver)做了限制犹撒,官方解釋在這里

解決辦法

參考文章
簡(jiǎn)單來(lái)說(shuō)解決的辦法就是創(chuàng)建一個(gè)contentprovider,并在AndroidManifest里面注冊(cè)的provider的authority聲明為registerContentObserver中uri的authority就可以了粒褒。

<provider
        android:name=".download.DownloadUriProvider"
        android:authorities="${applicationId}"
        android:enabled="true"
        android:exported="false"/>
public class DownloadUriProvider extends ContentProvider {
    public DownloadUriProvider() {
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        return null;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        return 0;
    }
}

錯(cuò)誤7. notification沒(méi)有顯示

原因分析

如果targetsdkversion設(shè)定為26或以上识颊,開(kāi)始要求notification必須知道channel,具體查閱這里奕坟。

解決辦法

在notify之前先創(chuàng)建notificationChannel

private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = "下載提醒";
        String description = "顯示下載過(guò)程及進(jìn)度";
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(DOWNLOAD_CHANNEL_ID, name, importance);
        channel.setDescription(description);
        mNotificationManager.createNotificationChannel(channel);
    }
}

錯(cuò)誤8. 在AndroidManifest中注冊(cè)的receiver不能收到廣播

原因分析

針對(duì)targetsdkversion為26的應(yīng)用祥款,加強(qiáng)對(duì)匿名receiver的控制,以至于在manifest中注冊(cè)的隱式receiver都失效月杉。具體見(jiàn)官方原文

解決辦法

將廣播從在AndroidManifest中注冊(cè)移到在Activity中使用registerReceiver注冊(cè)

錯(cuò)誤9. 無(wú)法通過(guò)“application/vnd.android.package-archive” action安裝應(yīng)用

原因分析

targetsdkversion大于25必須聲明REQUEST_INSTALL_PACKAGES權(quán)限刃跛,見(jiàn)官方說(shuō)明:
REQUEST_INSTALL_PACKAGES

解決辦法

在AndroidManifest中加入

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

錯(cuò)誤10. java.lang.RuntimeException: Unable to start activity ComponentInfo{xxxActivity}: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation

原因分析

targetsdk26以上,對(duì)于透明主題的activity不能夠通過(guò)manifest設(shè)定android:screenOrientation苛萎。
具體分析見(jiàn)這里

解決辦法

檢查報(bào)錯(cuò)的Activity是否在AndroidManifest中聲明了
奠伪,若有需要將其去除。

所有影響checklist

Andriod版本適配 check list

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末首懈,一起剝皮案震驚了整個(gè)濱河市绊率,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌究履,老刑警劉巖滤否,帶你破解...
    沈念sama閱讀 193,812評(píng)論 5 459
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異最仑,居然都是意外死亡藐俺,警方通過(guò)查閱死者的電腦和手機(jī)炊甲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 81,626評(píng)論 2 371
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)欲芹,“玉大人卿啡,你說(shuō)我怎么就攤上這事×飧福” “怎么了颈娜?”我有些...
    開(kāi)封第一講書(shū)人閱讀 141,144評(píng)論 0 319
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)浙宜。 經(jīng)常有香客問(wèn)我官辽,道長(zhǎng),這世上最難降的妖魔是什么粟瞬? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 52,052評(píng)論 1 263
  • 正文 為了忘掉前任同仆,我火速辦了婚禮,結(jié)果婚禮上裙品,老公的妹妹穿的比我還像新娘俗批。我一直安慰自己,他們只是感情好市怎,可當(dāng)我...
    茶點(diǎn)故事閱讀 60,925評(píng)論 4 355
  • 文/花漫 我一把揭開(kāi)白布扶镀。 她就那樣靜靜地躺著,像睡著了一般焰轻。 火紅的嫁衣襯著肌膚如雪臭觉。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 46,035評(píng)論 1 272
  • 那天辱志,我揣著相機(jī)與錄音蝠筑,去河邊找鬼。 笑死揩懒,一個(gè)胖子當(dāng)著我的面吹牛什乙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播已球,決...
    沈念sama閱讀 36,461評(píng)論 3 381
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼臣镣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了智亮?” 一聲冷哼從身側(cè)響起忆某,我...
    開(kāi)封第一講書(shū)人閱讀 35,150評(píng)論 0 253
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阔蛉,沒(méi)想到半個(gè)月后弃舒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 39,413評(píng)論 1 290
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 34,501評(píng)論 2 307
  • 正文 我和宋清朗相戀三年聋呢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了苗踪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 36,277評(píng)論 1 325
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡削锰,死狀恐怖通铲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情器贩,我是刑警寧澤颅夺,帶...
    沈念sama閱讀 32,159評(píng)論 3 312
  • 正文 年R本政府宣布,位于F島的核電站磨澡,受9級(jí)特大地震影響碗啄,放射性物質(zhì)發(fā)生泄漏质和。R本人自食惡果不足惜稳摄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 37,528評(píng)論 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望饲宿。 院中可真熱鬧厦酬,春花似錦、人聲如沸瘫想。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 28,868評(píng)論 0 17
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)国夜。三九已至减噪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間车吹,已是汗流浹背筹裕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 30,143評(píng)論 1 250
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窄驹,地道東北人朝卒。 一個(gè)月前我還...
    沈念sama閱讀 41,407評(píng)論 2 341
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像乐埠,于是被迫代替她去往敵國(guó)和親抗斤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 40,615評(píng)論 2 335

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