Android:檢查通知權限并跳轉到通知設置界面

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

一、目標需求

最近項目中在完善推送功能,需要進入APP時檢測一下是否開啟了推送權限,如果沒有開啟彈窗提醒,當用戶點擊彈窗時直接跳轉到APP的通知設置界面,就像下面這種:

就是這種效果

二、需求實現(xiàn)

1、檢測是否開啟通知權限

接到需求時一臉懵,不知道咋實現(xiàn),先是一番搜索,搜索后得知可以通過NotificationManagerCompat 中的 areNotificationsEnabled()來判斷是否開啟通知權限。

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

注意:

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

2、跳轉到通知設置界面

假設沒有開啟通知權限,點擊之后就需要跳轉到 APP的通知設置界面,對應的Action是:Settings.ACTION_APP_NOTIFICATION_SETTINGS, 這個Action是 API 26 后增加的。APP的通知設置界面如下圖:

APP的通知設置界面

如果在部分手機中無法精確的跳轉到 APP對應的通知設置界面,那么我們就考慮直接跳轉到 APP信息界面,對應的Action是:Settings.ACTION_APPLICATION_DETAILS_SETTINGS。APP信息界面如下圖:

APP信息界面

3、代碼實現(xiàn):

不多說了,代碼其實很簡單,注釋也很明了,直接上代碼:

(1)、java版(使用了DataBinding-數據綁定)


/**
 * 作者:CnPeng
 * 時間:2018/7/11
 * 功用:檢測在設置中是否開啟了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
     * 時間:2018/7/12 上午8:02
     * 功用:初始化點擊事件
     * 說明:
     */
    private void initClickListener() {
        //CnPeng 2018/7/12 上午7:08 跳轉到通知設置界面
        mBinding.tvMsg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    // 根據isOpened結果,判斷是否需要提醒用戶跳轉AppInfo頁面,去打開App通知權限
                    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),是個特例,通知設置界面只能控制"允許使用通知圓點"——然而這個玩意并沒有卵用,我想對雷布斯說: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)異常則跳轉到應用設置界面:錘子堅果3——OC105 API25
                    Intent intent = new Intent();

                    //下面這種方案是直接跳轉到當前應用的設置界面。
                    //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
     * 時間:2018/7/12 上午9:02
     * 功用:檢查是否已經開啟了通知權限
     * 說明:
     */
    private void checkNotifySetting() {
        NotificationManagerCompat manager = NotificationManagerCompat.from(this);
        // areNotificationsEnabled方法的有效性官方只最低支持到API 19,低于19的仍可調用此方法不過只會返回true,即默認為用戶已經開啟了通知。
        boolean isOpened = manager.areNotificationsEnabled();

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

        } else {
            mBinding.tvMsg.setText("還沒有開啟通知權限,點擊去開啟");
        }
    }
}

(2)、kotlin版

/**
 * 作者:CnPeng
 * 時間:2018/7/12
 * 功用:檢查通知推送是否已經被打開
 * 其他:
 */
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
     * 時間:2018/7/12 下午3:43
     * 功用:檢查通知推送的開關狀態(tài)
     * 說明:
     */
    private fun checkPushSwitchStatus() {
        val notificationManager: NotificationManagerCompat = NotificationManagerCompat.from(this);
        val isOpend = notificationManager.areNotificationsEnabled()
        if (isOpend) {
            tv_msg.text = "通知權限已經被打開" +
                    "\n手機型號:${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 = "通知權限沒有被開啟,點擊去開啟"
        }

    }

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

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

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

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

                //其他低版本或者異常情況,走該節(jié)點。進入APP設置界面
                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包的版本

因為 NotificationManagerCompat 是 22.1.0才有的,其中的 areNotificaitonEnabled() 是 24.1.0 才有的,Settings.ACTION_APP_NOTIFICATION_SETTINGS 是 26 才有的,所以,為了保證這些內容在不同版本中生效,最好在 gradle文件中 support 的版本升級到最新。如:

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

B: 部分國產手機中沒有APP通知設置頁面

在部分國產手機系統(tǒng)中,Settings.ACTION_APPLICATION_DETAILS_SETTINGS對應的Activity是不存在的,比如:錘子堅果3——OC105 API25。

所以,在堅果3手機上,最終會走我們代碼中的 catch 節(jié)點,然后進入到 應用信息界面。

下面兩張圖分別是 錘子堅果3 手機的截圖。第一張是 設置--通知中心的界面,點擊之后只是一個開關的開啟和關閉,并沒有再進入詳細的通知設置界面。第二張是 應用管理--應用程序管理--應用信息界面, 點擊其中的 允許推送通知時也只是開關的開啟和關閉。

設置--通知中心
應用信息
C: 部分國產手機 APP通知設置界面中沒有開啟和關閉的操作

部分國產手機中 Settings.ACTION_APPLICATION_DETAILS_SETTINGS對應的Activity并不是我們期望的通知設置界面。比如,小米6。小米6中 Settings.ACTION_APPLICATION_DETAILS_SETTINGS對應的通知設置界面如下:


這完全不是我們需要的界面啊。。。里面并沒有我們想要的開關啊。而且,在小米6中 Settings.ACTION_APPLICATION_DETAILS_SETTINGS 對應的應用信息界面中,點擊其中的 通知管理 之后跳轉的也是上面圖中的樣子。

但是,如果我們手動的從 設置--通知和狀態(tài)欄--通知管理 進入我們應用的通知設置界面時,就可以正常的看到 允許通知的開關,如下圖:

對于小米6手機的這個情況,分析了一陣子之后還是沒找到解決辦法。本來想著通過log確認一下上圖中的界面到底是哪個Activity,但非常郁悶的是Log中只得到了com.android.settings/.SubSettings 這么一個地址,之前沒見過這個地址,然后繼續(xù)搜索。

在看完 https://www.cnblogs.com/Lefter/archive/2013/04/27/3048010.htmlhttps://blog.csdn.net/hfreeman2008/article/details/52778992 之后,明白了 .SubSettings 是干啥的了。也大致推斷出為啥在小米6上得不到我們想要的界面了——他們在定制系統(tǒng)時更改了通知設置界面對應的Fragment?。。?!

此時,真想對雷布斯說一句:I'm not ok!!!!

三、附錄

1、測試結果說明

手機型號 系統(tǒng)版本 測試結果
Vivo X9s 7.1.2 正常跳轉到通知設置界面
榮耀10 8.1.0 正常跳轉到通知設置界面
紅米note4x 7.0 正常跳轉到通知設置界面
Oppo R7 plus 5.0 正常跳轉到通知設置界面
ZTE BA910 5.1 正常跳轉到通知設置界面
Oppo R15 8.1.0 正常跳轉到通知設置界面
三星蓋樂世On5 7.1.1 正常跳轉到通知設置界面
360Vizza 7.1.1 正常跳轉到通知設置界面
魅族Mx3 4.4 進入APP設置界面
華為榮耀4X 4.4 進入APP設置界面
錘子堅果3 7.1.2 進入APP設置界面
小米6 8.0.0 進入的頁面中沒有通知開關?。。?!

2、參考鏈接

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

(2)SubSettings 和 Settings 的參考鏈接

3、文中代碼的GitHub地址

文中代碼分別對應下列倉庫中的:b_34_checkNotify、b_34_pushcheck
Java版:https://github.com/CnPeng/CnPengAndroid.git
Kotlin版:https://github.com/CnPeng/CnPengKotlin.git


本文到此結束,謝謝觀看!
如有不足,敬請指正!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容