聲明:該方案只對(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)限簿晓。
查閱官方文檔可知 NotificationManagerCompat 在 android.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è)置界面如下圖:
如果在部分手機(jī)中無(wú)法精確的跳轉(zhuǎn)到 APP對(duì)應(yīng)的通知設(shè)置界面蜈缤,那么我們就考慮直接跳轉(zhuǎn)到 APP信息界面,對(duì)應(yīng)的Action是:Settings.ACTION_APPLICATION_DETAILS_SETTINGS
冯挎。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)閉牵囤。
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.html 和 https://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è)置的參考鏈接
- 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
(2)SubSettings 和 Settings 的參考鏈接
- https://www.cnblogs.com/Lefter/archive/2013/04/27/3048010.html
- https://blog.csdn.net/hfreeman2008/article/details/52778992
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)指正徽诲!