Android:檢查通知權(quán)限并跳轉(zhuǎn)到通知設(shè)置界面

聲明:該方案只對(duì)API19及以上版本有效

一械馆、目標(biāo)需求

最近項(xiàng)目中在完善推送功能胖眷,需要進(jìn)入APP時(shí)檢測(cè)一下是否開(kāi)啟了推送權(quán)限,如果沒(méi)有開(kāi)啟彈窗提醒霹崎,當(dāng)用戶點(diǎn)擊彈窗時(shí)直接跳轉(zhuǎn)到APP的通知設(shè)置界面珊搀,就像下面這種:

就是這種效果

二、需求實(shí)現(xiàn)

1尾菇、檢測(cè)是否開(kāi)啟通知權(quán)限

接到需求時(shí)一臉懵食棕,不知道咋實(shí)現(xiàn),先是一番搜索错沽,搜索后得知可以通過(guò)NotificationManagerCompat 中的 areNotificationsEnabled()來(lái)判斷是否開(kāi)啟通知權(quán)限簿晓。

查閱官方文檔可知 NotificationManagerCompatandroid.support.v4.app包中,是API 22.1.0 中加入的千埃。而 areNotificationsEnabled()則是在 API 24.1.0之后加入的憔儿。

注意:

areNotificationsEnabled 只對(duì) API 19 及以上版本有效,低于API 19 會(huì)一直返回true

2放可、跳轉(zhuǎn)到通知設(shè)置界面

假設(shè)沒(méi)有開(kāi)啟通知權(quán)限谒臼,點(diǎn)擊之后就需要跳轉(zhuǎn)到 APP的通知設(shè)置界面,對(duì)應(yīng)的Action是:Settings.ACTION_APP_NOTIFICATION_SETTINGS, 這個(gè)Action是 API 26 后增加的耀里。APP的通知設(shè)置界面如下圖:

APP的通知設(shè)置界面

如果在部分手機(jī)中無(wú)法精確的跳轉(zhuǎn)到 APP對(duì)應(yīng)的通知設(shè)置界面蜈缤,那么我們就考慮直接跳轉(zhuǎn)到 APP信息界面,對(duì)應(yīng)的Action是:Settings.ACTION_APPLICATION_DETAILS_SETTINGS冯挎。APP信息界面如下圖:

APP信息界面

3底哥、代碼實(shí)現(xiàn):

不多說(shuō)了,代碼其實(shí)很簡(jiǎn)單,注釋也很明了趾徽,直接上代碼:

(1)续滋、java版(使用了DataBinding-數(shù)據(jù)綁定)


/**
 * 作者:CnPeng
 * 時(shí)間:2018/7/11
 * 功用:檢測(cè)在設(shè)置中是否開(kāi)啟了APP的推送
 * 其他:
 *
 * 參考鏈接:
 * https://stackoverflow.com/questions/32366649/any-way-to-link-to-the-android-notification-settings-for-my-app
 * https://blog.csdn.net/ysy950803/article/details/71910806
 * https://juejin.im/post/5a2508656fb9a0450407b638
 */
public class CheckNotifyActivity extends AppCompatActivity {
    ActivityCheckNotifyBinding mBinding;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_check_notify);
        initClickListener();
    }

    @Override
    protected void onResume() {
        super.onResume();
        checkNotifySetting();
    }

    /**
     * 作者:CnPeng
     * 時(shí)間:2018/7/12 上午8:02
     * 功用:初始化點(diǎn)擊事件
     * 說(shuō)明:
     */
    private void initClickListener() {
        //CnPeng 2018/7/12 上午7:08 跳轉(zhuǎn)到通知設(shè)置界面
        mBinding.tvMsg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    // 根據(jù)isOpened結(jié)果,判斷是否需要提醒用戶跳轉(zhuǎn)AppInfo頁(yè)面孵奶,去打開(kāi)App通知權(quán)限
                    Intent intent = new Intent();
                    intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
                    //這種方案適用于 API 26, 即8.0(含8.0)以上可以用
                    intent.putExtra(EXTRA_APP_PACKAGE, getPackageName());
                    intent.putExtra(EXTRA_CHANNEL_ID, getApplicationInfo().uid);

                    //這種方案適用于 API21——25疲酌,即 5.0——7.1 之間的版本可以使用
                    intent.putExtra("app_package", getPackageName());
                    intent.putExtra("app_uid", getApplicationInfo().uid);

                    // 小米6 -MIUI9.6-8.0.0系統(tǒng),是個(gè)特例了袁,通知設(shè)置界面只能控制"允許使用通知圓點(diǎn)"——然而這個(gè)玩意并沒(méi)有卵用朗恳,我想對(duì)雷布斯說(shuō):I'm not ok!!!
                    //  if ("MI 6".equals(Build.MODEL)) {
                    //      intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                    //      Uri uri = Uri.fromParts("package", getPackageName(), null);
                    //      intent.setData(uri);
                    //      // intent.setAction("com.android.settings/.SubSettings");
                    //  }
                    startActivity(intent);
                } catch (Exception e) {
                    e.printStackTrace();
                    // 出現(xiàn)異常則跳轉(zhuǎn)到應(yīng)用設(shè)置界面:錘子堅(jiān)果3——OC105 API25
                    Intent intent = new Intent();

                    //下面這種方案是直接跳轉(zhuǎn)到當(dāng)前應(yīng)用的設(shè)置界面。
                    //https://blog.csdn.net/ysy950803/article/details/71910806
                    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                    Uri uri = Uri.fromParts("package", getPackageName(), null);
                    intent.setData(uri);
                    startActivity(intent);
                }
            }
        });
    }

    /**
     * 作者:CnPeng
     * 時(shí)間:2018/7/12 上午9:02
     * 功用:檢查是否已經(jīng)開(kāi)啟了通知權(quán)限
     * 說(shuō)明:
     */
    private void checkNotifySetting() {
        NotificationManagerCompat manager = NotificationManagerCompat.from(this);
        // areNotificationsEnabled方法的有效性官方只最低支持到API 19载绿,低于19的仍可調(diào)用此方法不過(guò)只會(huì)返回true僻肖,即默認(rèn)為用戶已經(jīng)開(kāi)啟了通知。
        boolean isOpened = manager.areNotificationsEnabled();

        if (isOpened) {
            mBinding.tvMsg.setText("通知權(quán)限已經(jīng)被打開(kāi)" +
                    "\n手機(jī)型號(hào):" + android.os.Build.MODEL +
                    "\nSDK版本:" + android.os.Build.VERSION.SDK +
                    "\n系統(tǒng)版本:" + android.os.Build.VERSION.RELEASE +
                    "\n軟件包名:" + getPackageName());

        } else {
            mBinding.tvMsg.setText("還沒(méi)有開(kāi)啟通知權(quán)限卢鹦,點(diǎn)擊去開(kāi)啟");
        }
    }
}

(2)臀脏、kotlin版

/**
 * 作者:CnPeng
 * 時(shí)間:2018/7/12
 * 功用:檢查通知推送是否已經(jīng)被打開(kāi)
 * 其他:
 */
public class PushCheckActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_push_check)

        initClickListener()
    }

    override fun onResume() {
        super.onResume()
        checkPushSwitchStatus()
    }

    /**
     * 作者:CnPeng
     * 時(shí)間:2018/7/12 下午3:43
     * 功用:檢查通知推送的開(kāi)關(guān)狀態(tài)
     * 說(shuō)明:
     */
    private fun checkPushSwitchStatus() {
        val notificationManager: NotificationManagerCompat = NotificationManagerCompat.from(this);
        val isOpend = notificationManager.areNotificationsEnabled()
        if (isOpend) {
            tv_msg.text = "通知權(quán)限已經(jīng)被打開(kāi)" +
                    "\n手機(jī)型號(hào):${android.os.Build.MODEL}" +
                    "\nSDK版本:${android.os.Build.VERSION.SDK_INT}" +
                    "\n系統(tǒng)版本:${android.os.Build.VERSION.RELEASE}" +
                    "\n軟件包名:${getPackageName()}"
        } else {
            tv_msg.text = "通知權(quán)限沒(méi)有被開(kāi)啟,點(diǎn)擊去開(kāi)啟"
        }

    }

    private fun initClickListener() {
        tv_msg.setOnClickListener {
            val intent: Intent = Intent()
            try {
                intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS

                //8.0及以后版本使用這兩個(gè)extra.  >=API 26
                intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
                intent.putExtra(Settings.EXTRA_CHANNEL_ID, applicationInfo.uid)

                //5.0-7.1 使用這兩個(gè)extra.  <= API 25, >=API 21
                intent.putExtra("app_package", packageName)
                intent.putExtra("app_uid", applicationInfo.uid)

                startActivity(intent)
            } catch (e: Exception) {
                e.printStackTrace()

                //其他低版本或者異常情況冀自,走該節(jié)點(diǎn)揉稚。進(jìn)入APP設(shè)置界面
                intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                intent.putExtra("package", packageName)

                //val uri = Uri.fromParts("package", packageName, null)
                //intent.data = uri
                startActivity(intent)
            }
        }
    }
}

4、踩坑記錄

A: com.android.support包的版本

因?yàn)?NotificationManagerCompat 是 22.1.0才有的熬粗,其中的 areNotificaitonEnabled() 是 24.1.0 才有的搀玖,Settings.ACTION_APP_NOTIFICATION_SETTINGS 是 26 才有的,所以驻呐,為了保證這些內(nèi)容在不同版本中生效灌诅,最好在 gradle文件中 support 的版本升級(jí)到最新。如:

implementation 'com.android.support:appcompat-v7:27.1.1'

B: 部分國(guó)產(chǎn)手機(jī)中沒(méi)有APP通知設(shè)置頁(yè)面

在部分國(guó)產(chǎn)手機(jī)系統(tǒng)中含末,Settings.ACTION_APPLICATION_DETAILS_SETTINGS對(duì)應(yīng)的Activity是不存在的猜拾,比如:錘子堅(jiān)果3——OC105 API25。

所以佣盒,在堅(jiān)果3手機(jī)上挎袜,最終會(huì)走我們代碼中的 catch 節(jié)點(diǎn),然后進(jìn)入到 應(yīng)用信息界面肥惭。

下面兩張圖分別是 錘子堅(jiān)果3 手機(jī)的截圖盯仪。第一張是 設(shè)置--通知中心的界面,點(diǎn)擊之后只是一個(gè)開(kāi)關(guān)的開(kāi)啟和關(guān)閉蜜葱,并沒(méi)有再進(jìn)入詳細(xì)的通知設(shè)置界面全景。第二張是 應(yīng)用管理--應(yīng)用程序管理--應(yīng)用信息界面, 點(diǎn)擊其中的 允許推送通知時(shí)也只是開(kāi)關(guān)的開(kāi)啟和關(guān)閉牵囤。

設(shè)置--通知中心
應(yīng)用信息
C: 部分國(guó)產(chǎn)手機(jī) APP通知設(shè)置界面中沒(méi)有開(kāi)啟和關(guān)閉的操作

部分國(guó)產(chǎn)手機(jī)中 Settings.ACTION_APPLICATION_DETAILS_SETTINGS對(duì)應(yīng)的Activity并不是我們期望的通知設(shè)置界面爸黄。比如滞伟,小米6。小米6中 Settings.ACTION_APPLICATION_DETAILS_SETTINGS對(duì)應(yīng)的通知設(shè)置界面如下:


這完全不是我們需要的界面啊馆纳。诗良。汹桦。里面并沒(méi)有我們想要的開(kāi)關(guān)啊鲁驶。而且,在小米6中 Settings.ACTION_APPLICATION_DETAILS_SETTINGS 對(duì)應(yīng)的應(yīng)用信息界面中舞骆,點(diǎn)擊其中的 通知管理 之后跳轉(zhuǎn)的也是上面圖中的樣子钥弯。

但是,如果我們手動(dòng)的從 設(shè)置--通知和狀態(tài)欄--通知管理 進(jìn)入我們應(yīng)用的通知設(shè)置界面時(shí)督禽,就可以正常的看到 允許通知的開(kāi)關(guān)脆霎,如下圖:

對(duì)于小米6手機(jī)的這個(gè)情況,分析了一陣子之后還是沒(méi)找到解決辦法狈惫。本來(lái)想著通過(guò)log確認(rèn)一下上圖中的界面到底是哪個(gè)Activity睛蛛,但非常郁悶的是Log中只得到了com.android.settings/.SubSettings 這么一個(gè)地址,之前沒(méi)見(jiàn)過(guò)這個(gè)地址胧谈,然后繼續(xù)搜索忆肾。

在看完 https://www.cnblogs.com/Lefter/archive/2013/04/27/3048010.htmlhttps://blog.csdn.net/hfreeman2008/article/details/52778992 之后,明白了 .SubSettings 是干啥的了菱肖。也大致推斷出為啥在小米6上得不到我們想要的界面了——他們?cè)诙ㄖ葡到y(tǒng)時(shí)更改了通知設(shè)置界面對(duì)應(yīng)的Fragment?透浴!N惹俊场仲!

此時(shí),真想對(duì)雷布斯說(shuō)一句:I'm not ok!!!!

三退疫、附錄

1渠缕、測(cè)試結(jié)果說(shuō)明

手機(jī)型號(hào) 系統(tǒng)版本 測(cè)試結(jié)果
Vivo X9s 7.1.2 正常跳轉(zhuǎn)到通知設(shè)置界面
榮耀10 8.1.0 正常跳轉(zhuǎn)到通知設(shè)置界面
紅米note4x 7.0 正常跳轉(zhuǎn)到通知設(shè)置界面
Oppo R7 plus 5.0 正常跳轉(zhuǎn)到通知設(shè)置界面
ZTE BA910 5.1 正常跳轉(zhuǎn)到通知設(shè)置界面
Oppo R15 8.1.0 正常跳轉(zhuǎn)到通知設(shè)置界面
三星蓋樂(lè)世On5 7.1.1 正常跳轉(zhuǎn)到通知設(shè)置界面
360Vizza 7.1.1 正常跳轉(zhuǎn)到通知設(shè)置界面
魅族Mx3 4.4 進(jìn)入APP設(shè)置界面
華為榮耀4X 4.4 進(jìn)入APP設(shè)置界面
錘子堅(jiān)果3 7.1.2 進(jìn)入APP設(shè)置界面
小米6 8.0.0 進(jìn)入的頁(yè)面中沒(méi)有通知開(kāi)關(guān)!0薄:纸 !

2澜汤、參考鏈接

(1)通知設(shè)置的參考鏈接

(2)SubSettings 和 Settings 的參考鏈接

3蚜迅、文中代碼的GitHub地址

文中代碼分別對(duì)應(yīng)下列倉(cāng)庫(kù)中的:b_34_checkNotify、b_34_pushcheck
Java版:https://github.com/CnPeng/CnPengAndroid.git
Kotlin版:https://github.com/CnPeng/CnPengKotlin.git


本文到此結(jié)束俊抵,謝謝觀看谁不!
如有不足,敬請(qǐng)指正徽诲!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末刹帕,一起剝皮案震驚了整個(gè)濱河市吵血,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌偷溺,老刑警劉巖蹋辅,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異挫掏,居然都是意外死亡侦另,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門尉共,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)褒傅,“玉大人,你說(shuō)我怎么就攤上這事袄友〉钔校” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵剧蚣,是天一觀的道長(zhǎng)支竹。 經(jīng)常有香客問(wèn)我,道長(zhǎng)鸠按,這世上最難降的妖魔是什么礼搁? 我笑而不...
    開(kāi)封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮待诅,結(jié)果婚禮上叹坦,老公的妹妹穿的比我還像新娘。我一直安慰自己卑雁,他們只是感情好募书,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著测蹲,像睡著了一般莹捡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扣甲,一...
    開(kāi)封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天篮赢,我揣著相機(jī)與錄音,去河邊找鬼琉挖。 笑死启泣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的示辈。 我是一名探鬼主播寥茫,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼矾麻!你這毒婦竟也來(lái)了纱耻?” 一聲冷哼從身側(cè)響起芭梯,我...
    開(kāi)封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弄喘,沒(méi)想到半個(gè)月后玖喘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蘑志,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年累奈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卖漫。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡费尽,死狀恐怖赠群,靈堂內(nèi)的尸體忽然破棺而出羊始,到底是詐尸還是另有隱情,我是刑警寧澤查描,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布突委,位于F島的核電站,受9級(jí)特大地震影響冬三,放射性物質(zhì)發(fā)生泄漏匀油。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一勾笆、第九天 我趴在偏房一處隱蔽的房頂上張望敌蚜。 院中可真熱鬧,春花似錦窝爪、人聲如沸弛车。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纷跛。三九已至,卻和暖如春邀杏,著一層夾襖步出監(jiān)牢的瞬間贫奠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工望蜡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留唤崭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓脖律,卻偏偏與公主長(zhǎng)得像谢肾,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子状您,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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