targetSdkVersion升級(jí)為26之后的適配

1俯萎、權(quán)限的動(dòng)態(tài)申請(qǐng)
這個(gè)是targetSdkVersion為23時(shí),對(duì)于一些比較危險(xiǎn)的權(quán)限运杭,需要?jiǎng)討B(tài)申請(qǐng)夫啊,網(wǎng)上很多資料,庫(kù)也很多辆憔。
2撇眯、隨著Android版本越來(lái)越高,Android對(duì)隱私的保護(hù)力度也越來(lái)越大虱咧。
比如:Android6.0引入的動(dòng)態(tài)權(quán)限控制(Runtime Permissions)熊榛,
Android7.0又引入“私有目錄被限制訪問(wèn)”,“StrictMode API 政策”腕巡。
這些更改在為用戶帶來(lái)更加安全的操作系統(tǒng)的同時(shí)也為開(kāi)發(fā)者帶來(lái)了一些新的任務(wù)玄坦。如何讓你的APP能夠適應(yīng)這些改變而不是crash,是擺在每一位Android開(kāi)發(fā)者身上的責(zé)任绘沉。
“私有目錄被限制訪問(wèn)“ 是指在Android7.0中為了提高私有文件的安全性煎楣,面向 Android N 或更高版本的應(yīng)用私有目錄將被限制訪問(wèn)。這點(diǎn)類(lèi)似iOS的沙盒機(jī)制车伞。
" StrictMode API 政策" 是指禁止向你的應(yīng)用外公開(kāi) file:// URI择懂。 如果一項(xiàng)包含文件 file:// URI類(lèi)型 的 Intent 離開(kāi)你的應(yīng)用,應(yīng)用失敗另玖,并出現(xiàn) FileUriExposedException 異常困曙。
接下來(lái)就用FileProvider來(lái)解決這一問(wèn)題
1)在AndroidManifest.xml清單文件中注冊(cè)provider

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.dh.test.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
  </provider>

2)在項(xiàng)目的res文件夾下新建xml文件夾,然后新建filepaths.xml日矫,名字要與清單文件中的一致

android:resource="@xml/filepaths"

3)編寫(xiě)filepaths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--
    <files-path name="name" path="path" /> 對(duì)應(yīng)Context.getFilesDir() + “/path/”赂弓,即/data/data/<package-name>/files/text/绑榴。
    -->
    <!--<files-path-->
        <!--name="my_files"-->
        <!--path="text/" />-->
    <!--
    <cache-path name="name" path="path" /> 對(duì)應(yīng)Context.getCacheDir() + “/path/”哪轿,即/data/data/<package-name>/cache/text/。
    -->
    <!--<cache-path-->
        <!--name="my_cache"-->
        <!--path="text/" />-->
    <!--
    <external-path name="name" path="path" /> 對(duì)應(yīng)Environment.getExternalStorageDirectory() + “/path/”翔怎,即/storage/emulated/0/path/
    -->
    <external-path
        name="myFile"
        path="" />
</paths>

path=""窃诉,它代碼根目錄杨耙,也就是說(shuō)你可以向其它的應(yīng)用共享根目錄及其子目錄下任何一個(gè)文件了。
如果你將path設(shè)為path="text"飘痛,那么它代表著根目錄下的text目錄(/storage/emulated/0/text)珊膜,如果你向其它應(yīng)用分享text目錄范圍之外的文件是不行的。
4)代碼修改宣脉,以版本更新為例:

 Intent installIntent = new Intent(Intent.ACTION_VIEW);
        installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        if (Utils.isAndroid7()) { //判讀版本是否在7.0以上
            //參數(shù)1 上下文, 參數(shù)2 Provider主機(jī)地址 和清單文件中保持一致   參數(shù)3  共享的文件
            Uri apkUri = FileProvider.getUriForFile(context,"com.dh.test.fileprovider", file);
            //添加這一句表示對(duì)目標(biāo)應(yīng)用臨時(shí)授權(quán)該Uri所代表的文件installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            installIntent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
installIntent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
        }
        context.startActivity(installIntent);

3车柠、通知Notification
Android8.0其中一項(xiàng)行為變更是Notification,Android 8.0 引入了通知渠道塑猖,其允許您為要顯示的每種通知類(lèi)型創(chuàng)建用戶可自定義的渠道竹祷。用戶界面將通知渠道稱(chēng)之為通知類(lèi)別。targeSdk升級(jí)到26之后羊苟,所有的通知的實(shí)現(xiàn)都需要提供通知渠道塑陵,如果不提供通知渠道的話,所有通知在8.0系統(tǒng)上面都不能正常展示蜡励。

private NotifyManager() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 NotificationChannel channel =
                    new NotificationChannel("channel_id1", "channel_name1", NotificationManager.IMPORTANCE_DEFAULT);
            channel.enableVibration(true);
//            channel.setShowBadge(true); //是否在久按桌面圖標(biāo)時(shí)顯示此渠道的通知
            //是否在桌面icon右上角展示小紅點(diǎn)
//            channel.enableLights(true);
//            Uri mUri = Settings.System.DEFAULT_NOTIFICATION_URI;
//            channel.setSound(mUri, Notification.AUDIO_ATTRIBUTES_DEFAULT);
//            NotificationManager notifyManager = (NotificationManager) MyApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
            getManager().createNotificationChannel(channel);

        }
    }

public void sendNotification(String title, String content) {
        //獲取NotificationManager實(shí)例
//        NotificationManager notifyManager = (NotificationManager) MyApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
        //實(shí)例化NotificationCompat.Builde并設(shè)置相關(guān)屬性
        Notification notification = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Notification.Builder builder = new Notification.Builder(MyApplication.getInstance(), channelId);
            //設(shè)置小圖標(biāo)
            builder.setSmallIcon(R.mipmap.ic_launcher)
                    //設(shè)置通知標(biāo)題
                    .setContentTitle(title)
                    //設(shè)置通知內(nèi)容
                    .setContentText(content)
                    .setAutoCancel(true);//用戶觸摸時(shí)令花,自動(dòng)關(guān)閉
            notification = builder.build();
        } else {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(MyApplication.getContext())
                    //點(diǎn)擊通知后自動(dòng)清除
                    .setAutoCancel(true)
                    //設(shè)置小圖標(biāo)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    //設(shè)置通知標(biāo)題
                    .setContentTitle(title)
                    //設(shè)置通知內(nèi)容
                    .setContentText(content);
//                .setDefaults(Notification.DEFAULT_SOUND);// 設(shè)置通知響應(yīng)方式  ;
//        .setContentIntent(mainPendingIntent);
            //設(shè)置通知時(shí)間,默認(rèn)為系統(tǒng)發(fā)出通知的時(shí)間凉倚,通常不用設(shè)置
            //.setWhen(System.currentTimeMillis());
            //通過(guò)builder.build()方法生成Notification對(duì)象,并發(fā)送通知,id=1
            notification = builder.build();
            //這通知的其他屬性兼都,比如:聲音和振動(dòng)
            notification.defaults |= Notification.DEFAULT_SOUND;
            notification.defaults |= Notification.DEFAULT_VIBRATE;
            notification.flags |= Notification.FLAG_AUTO_CANCEL;
        }
        getManager().notify(count, notification);
        count++;
    }

4、8.0上版本升級(jí)無(wú)法跳轉(zhuǎn)安裝頁(yè)面
Android 8.0強(qiáng)化了權(quán)限管理稽寒,變得更加安全俯抖。在Android 8.0以前,只要在設(shè)置中打開(kāi)允許未知應(yīng)用的安裝瓦胎,則所有的未知來(lái)源應(yīng)用都可以被安裝芬萍,如此設(shè)計(jì)雖然方便,但是若被引誘安裝了惡意軟件搔啊,安裝"未知來(lái)源"的應(yīng)用有可能會(huì)對(duì)手機(jī)系統(tǒng)帶來(lái)潛在的危害柬祠;
而在Android 8.0的系統(tǒng)中,未知來(lái)源應(yīng)用權(quán)限的開(kāi)關(guān)被移除掉了负芋,取而代之的是未知來(lái)源應(yīng)用的管理列表漫蛔,如果你想要安裝某個(gè)被自己所信任的開(kāi)發(fā)者的app,則需要在每一次都手動(dòng)授權(quán)"安裝未知應(yīng)用"的許可。
坑就在這里了旧蛾,下面是解決辦法:
1)清單文件中添加

<!--android8.0版本更新跳轉(zhuǎn)安裝頁(yè)面 -->
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

2)代碼:

 Intent installIntent = new Intent(Intent.ACTION_VIEW);
        installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        if (Utils.isAndroid7()) { //判讀版本是否在7.0以上
            //參數(shù)1 上下文, 參數(shù)2 Provider主機(jī)地址 和清單文件中保持一致   參數(shù)3  共享的文件
            Uri apkUri = FileProvider.getUriForFile(context,"com.dh.test.fileprovider", file);
            //添加這一句表示對(duì)目標(biāo)應(yīng)用臨時(shí)授權(quán)該Uri所代表的文件installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            installIntent.setDataAndType(apkUri, "application/vnd.android.package-archive");
      //兼容8.0
            if (Utils.isAndroid8()) {
                boolean hasInstallPermission = context.getPackageManager().canRequestPackageInstalls();
                if (!hasInstallPermission) {
                    startInstallPermissionSettingActivity(context);
                    return;
                }
            }
        } else {
installIntent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
        }
        context.startActivity(installIntent);
/**
     * 跳轉(zhuǎn)到設(shè)置-允許安裝未知來(lái)源-頁(yè)面
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void startInstallPermissionSettingActivity(final Context context) {
        //注意這個(gè)是8.0新API
        Uri packageURI = Uri.parse("package:" + context.getPackageName());
        Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      context.startActivity(intent);
    }

當(dāng)用戶打開(kāi)了允許安裝未知應(yīng)用后莽龟,返回再次點(diǎn)擊安裝按鈕,就可以跳轉(zhuǎn)到安裝頁(yè)面了锨天。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末毯盈,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子病袄,更是在濱河造成了極大的恐慌搂赋,老刑警劉巖赘阀,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異脑奠,居然都是意外死亡基公,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)宋欺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)轰豆,“玉大人,你說(shuō)我怎么就攤上這事齿诞∶胱桑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵掌挚,是天一觀的道長(zhǎng)雨席。 經(jīng)常有香客問(wèn)我,道長(zhǎng)吠式,這世上最難降的妖魔是什么陡厘? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮特占,結(jié)果婚禮上糙置,老公的妹妹穿的比我還像新娘。我一直安慰自己是目,他們只是感情好谤饭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著懊纳,像睡著了一般揉抵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嗤疯,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天冤今,我揣著相機(jī)與錄音,去河邊找鬼茂缚。 笑死戏罢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的脚囊。 我是一名探鬼主播龟糕,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼悔耘!你這毒婦竟也來(lái)了讲岁?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎催首,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體泄鹏,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡郎任,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了备籽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舶治。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖车猬,靈堂內(nèi)的尸體忽然破棺而出霉猛,到底是詐尸還是另有隱情,我是刑警寧澤珠闰,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布惜浅,位于F島的核電站,受9級(jí)特大地震影響伏嗜,放射性物質(zhì)發(fā)生泄漏坛悉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一承绸、第九天 我趴在偏房一處隱蔽的房頂上張望裸影。 院中可真熱鬧,春花似錦军熏、人聲如沸轩猩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)均践。三九已至,卻和暖如春摩幔,著一層夾襖步出監(jiān)牢的瞬間浊猾,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工热鞍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留葫慎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓薇宠,卻偏偏與公主長(zhǎng)得像偷办,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子澄港,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,185評(píng)論 25 707
  • 用兩張圖告訴你椒涯,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 12,732評(píng)論 2 59
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程回梧,因...
    小菜c閱讀 6,426評(píng)論 0 17
  • 我也知道废岂, 河里有只白鵝祖搓, 它嘗不出蔥油餅的滋味。 我也知道湖苞, 枝丫上有枚枇杷拯欧, 它聽(tīng)不到果兒落水的咕咚聲。 我也...
    于凡塵發(fā)現(xiàn)真我閱讀 294評(píng)論 0 1
  • 參加21天愛(ài)上寫(xiě)作活動(dòng),到今天堅(jiān)持寫(xiě)下了十七篇文章了隆箩。 這中間该贾,因?yàn)楣ぷ骷彝サ拿β担罡忻刻鞎r(shí)間緊迫捌臊,寫(xiě)下的一些文...
    玲瓏小記閱讀 354評(píng)論 1 0