确定 iPhone 上用户是否启用了推送通知
-
20-09-2019 - |
题
我正在寻找一种方法来确定用户是否通过设置启用或禁用了我的应用程序的推送通知。
解决方案
呼叫enabledRemoteNotificationsTypes
并检查掩模。
例如:
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone)
// blah blah blah
和iOS8上以上:
[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]
其他提示
quantumpotato的问题:
其中types
由
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
可以使用
if (types & UIRemoteNotificationTypeAlert)
代替
的if (types == UIRemoteNotificationTypeNone)
将允许你检查的通知只是否已启用(不要担心的声音,徽章,通知中心等)。如果“警报类型”被设置为“无”,如果“警报类型”被设置为“旗”或“警报”,和types & UIRemoteNotificationTypeAlert
代码(YES
)的所述第一线将返回NO
,而不论其他设置。
在的iOS的最新版本此方法现在已经过时。同时支持的iOS 7和iOS 8使用:
UIApplication *application = [UIApplication sharedApplication];
BOOL enabled;
// Try to use the newer isRegisteredForRemoteNotifications otherwise use the enabledRemoteNotificationTypes.
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
{
enabled = [application isRegisteredForRemoteNotifications];
}
else
{
UIRemoteNotificationType types = [application enabledRemoteNotificationTypes];
enabled = types & UIRemoteNotificationTypeAlert;
}
有swift4.0的更新代码,iOS11 强>
import UserNotifications
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else { return }
//Not authorised
UIApplication.shared.registerForRemoteNotifications()
}
<强>代码swift3.0,iOS10 强>
let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications
if isRegisteredForRemoteNotifications {
// User is registered for notification
} else {
// Show alert user is not registered for notification
}
从iOS9,迅速2.0 UIRemoteNotificationType已过时,使用下面的代码
let notificationType = UIApplication.shared.currentUserNotificationSettings!.types
if notificationType == UIUserNotificationType.none {
// Push notifications are disabled in setting by user.
}else{
// Push notifications are enabled in setting by user.
}
只需查看推送通知是否启用
if notificationType == UIUserNotificationType.badge {
// the application may badge its icon upon a notification being received
}
if notificationType == UIUserNotificationType.sound {
// the application may play a sound upon a notification being received
}
if notificationType == UIUserNotificationType.alert {
// the application may display an alert upon a notification being received
}
下面你会发现一个涵盖iOS8上和iOS7(和更低版本),一个完整的例子。请注意,之前iOS8上不能区分“远程通知禁止”和“唯一的查看锁屏中的的启用。”
BOOL remoteNotificationsEnabled = false, noneEnabled,alertsEnabled, badgesEnabled, soundsEnabled;
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
// iOS8+
remoteNotificationsEnabled = [UIApplication sharedApplication].isRegisteredForRemoteNotifications;
UIUserNotificationSettings *userNotificationSettings = [UIApplication sharedApplication].currentUserNotificationSettings;
noneEnabled = userNotificationSettings.types == UIUserNotificationTypeNone;
alertsEnabled = userNotificationSettings.types & UIUserNotificationTypeAlert;
badgesEnabled = userNotificationSettings.types & UIUserNotificationTypeBadge;
soundsEnabled = userNotificationSettings.types & UIUserNotificationTypeSound;
} else {
// iOS7 and below
UIRemoteNotificationType enabledRemoteNotificationTypes = [UIApplication sharedApplication].enabledRemoteNotificationTypes;
noneEnabled = enabledRemoteNotificationTypes == UIRemoteNotificationTypeNone;
alertsEnabled = enabledRemoteNotificationTypes & UIRemoteNotificationTypeAlert;
badgesEnabled = enabledRemoteNotificationTypes & UIRemoteNotificationTypeBadge;
soundsEnabled = enabledRemoteNotificationTypes & UIRemoteNotificationTypeSound;
}
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
NSLog(@"Remote notifications enabled: %@", remoteNotificationsEnabled ? @"YES" : @"NO");
}
NSLog(@"Notification type status:");
NSLog(@" None: %@", noneEnabled ? @"enabled" : @"disabled");
NSLog(@" Alerts: %@", alertsEnabled ? @"enabled" : @"disabled");
NSLog(@" Badges: %@", badgesEnabled ? @"enabled" : @"disabled");
NSLog(@" Sounds: %@", soundsEnabled ? @"enabled" : @"disabled");
<强>夫特3 + 强>
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().getNotificationSettings(completionHandler: { (settings: UNNotificationSettings) in
// settings.authorizationStatus == .authorized
})
} else {
return UIApplication.shared.currentUserNotificationSettings?.types.contains(UIUserNotificationType.alert) ?? false
}
RxSwift可观察版为iOS10 +:
import UserNotifications
extension UNUserNotificationCenter {
static var isAuthorized: Observable<Bool> {
return Observable.create { observer in
DispatchQueue.main.async {
current().getNotificationSettings(completionHandler: { (settings: UNNotificationSettings) in
if settings.authorizationStatus == .authorized {
observer.onNext(true)
observer.onCompleted()
} else {
current().requestAuthorization(options: [.badge, .alert, .sound]) { (granted, error) in
observer.onNext(granted)
observer.onCompleted()
}
}
})
}
return Disposables.create()
}
}
}
在试图支持iOS8上,下,我没有使用isRegisteredForRemoteNotifications
凯文建议多少运气。相反,我用currentUserNotificationSettings
,这在我的测试伟大的工作。
+ (BOOL)notificationServicesEnabled {
BOOL isEnabled = NO;
if ([[UIApplication sharedApplication] respondsToSelector:@selector(currentUserNotificationSettings)]){
UIUserNotificationSettings *notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
if (!notificationSettings || (notificationSettings.types == UIUserNotificationTypeNone)) {
isEnabled = NO;
} else {
isEnabled = YES;
}
} else {
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert) {
isEnabled = YES;
} else{
isEnabled = NO;
}
}
return isEnabled;
}
不幸的是,这些解决方案都没有提供 真的 解决问题是因为归根结底,API 在提供相关信息方面严重缺乏。您可以使用以下方法进行一些猜测 currentUserNotificationSettings
(iOS8+)目前的形式不足以真正回答这个问题。尽管这里的很多解决方案似乎都表明要么这样要么 isRegisteredForRemoteNotifications
是一个更明确的答案,但实际上不是。
考虑一下:
和 isRegisteredForRemoteNotifications
文档指出:
如果应用程序当前注册了远程通知,则返回 YES,考虑到任何系统范围的设置...
但是,如果你简单地抛出一个 NSLog
进入您的应用程序委托来观察行为,很明显,这并不像我们预期的那样工作。它实际上直接与已为此应用程序/设备激活的远程通知相关。一旦第一次激活,这将始终返回 YES
. 。即使在设置(通知)中关闭它们仍然会导致此返回 YES
这是因为,从 iOS8 开始,应用程序可能会注册远程通知,甚至在用户未启用通知的情况下发送到设备,只是在用户未打开通知的情况下,它们可能不会执行警报、徽章和声音。无声通知是一个很好的例子,说明即使通知关闭,您也可以继续执行某些操作。
据,直到...为止 currentUserNotificationSettings
它表明以下四件事之一:
警报是在徽章上发出的声音,就在不在。
这绝对不会向您提供有关其他因素或通知开关本身的任何指示。
用户实际上可以关闭徽章、声音和警报,但仍然在锁屏或通知中心显示。该用户应该仍然可以接收推送通知,并且能够在锁定屏幕和通知中心看到它们。他们打开了通知开关。但 currentUserNotificationSettings
将返回: UIUserNotificationTypeNone
在这种情况下。这并不真正代表用户的实际设置。
人们可以做出一些猜测:
- 如果
isRegisteredForRemoteNotifications
是NO
那么您可以假设该设备从未成功注册远程通知。 - 第一次注册远程通知后回调
application:didRegisterUserNotificationSettings:
此时包含用户通知设置,因为这是用户第一次注册该设置 应该 指示用户根据权限请求选择的内容。如果设置等于以下内容以外的任何内容:UIUserNotificationTypeNone
然后授予推送权限,否则拒绝。原因是,从您开始远程注册过程的那一刻起,用户只能接受或拒绝,接受的初始设置是您在注册过程中设置的设置。
要完成的答案,它可以工作这样的事情...
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
switch (types) {
case UIRemoteNotificationTypeAlert:
case UIRemoteNotificationTypeBadge:
// For enabled code
break;
case UIRemoteNotificationTypeSound:
case UIRemoteNotificationTypeNone:
default:
// For disabled code
break;
}
编辑:这是不对的。因为这些是逐位的东西,它不会与开关工作,所以我使用该结束:
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
UIRemoteNotificationType typesset = (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge);
if((types & typesset) == typesset)
{
CeldaSwitch.chkSwitch.on = true;
}
else
{
CeldaSwitch.chkSwitch.on = false;
}
有关iOS7和之前你确实应该使用enabledRemoteNotificationTypes
并检查它是否等于(或取决于你想要什么不相等)UIRemoteNotificationTypeNone
。
然而,对于iOS8上它是的不始终足以仅与isRegisteredForRemoteNotifications
尽可能多的状态检查上面。您也应该检查是否application.currentUserNotificationSettings.types
等于(或取决于你想要的东西不等于)UIUserNotificationTypeNone
!
isRegisteredForRemoteNotifications
可能会返回真实的,即使currentUserNotificationSettings.types
回报UIUserNotificationTypeNone
。
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
// blah blah blah
{
NSLog(@"Notification Enabled");
}
else
{
NSLog(@"Notification not enabled");
}
在这里,我们得到的UIApplication的UIRemoteNotificationType。它代表的这个应用程序的推送通知的状态下设置,比你可以容易地检查它的类型
我尝试支持的iOS 10和上述使用溶液通过@Shaheen Ghiassy提供,但发现剥夺问题enabledRemoteNotificationTypes
。所以,我觉得用isRegisteredForRemoteNotifications
代替enabledRemoteNotificationTypes
其弃用的iOS 8的解决方案下面是我更新的解决方案,完美地为我工作:
- (BOOL)notificationServicesEnabled {
BOOL isEnabled = NO;
if ([[UIApplication sharedApplication] respondsToSelector:@selector(currentUserNotificationSettings)]){
UIUserNotificationSettings *notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
if (!notificationSettings || (notificationSettings.types == UIUserNotificationTypeNone)) {
isEnabled = NO;
} else {
isEnabled = YES;
}
} else {
if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications]) {
isEnabled = YES;
} else{
isEnabled = NO;
}
}
return isEnabled;
}
我们可以很容易地调用此函数和要访问其Bool
值,并通过此可以将其转换成字符串值:
NSString *str = [self notificationServicesEnabled] ? @"YES" : @"NO";
希望这会帮助别人太:) 快乐的编码。
iOS8上+(目标C)
#import <UserNotifications/UserNotifications.h>
[[UNUserNotificationCenter currentNotificationCenter]getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
switch (settings.authorizationStatus) {
case UNAuthorizationStatusNotDetermined:{
break;
}
case UNAuthorizationStatusDenied:{
break;
}
case UNAuthorizationStatusAuthorized:{
break;
}
default:
break;
}
}];
尽管 Zac 的答案在 iOS 7 之前是完全正确的,但自从 iOS 8 出现以来,情况发生了变化。因为 启用远程通知类型 从 iOS 8 开始已弃用。对于 iOS 8 及更高版本,您需要使用 已注册远程通知.
- 对于 iOS 7 及之前版本 --> 使用enabledRemoteNotificationTypes
- 对于 iOS 8 及更高版本 --> 使用 isRegisteredForRemoteNotifications。
此的 SWIFTY 强>解决方案工作良好,对我(的 iOS8上+ 强>),
方式强>:
func isNotificationEnabled(completion:@escaping (_ enabled:Bool)->()){
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().getNotificationSettings(completionHandler: { (settings: UNNotificationSettings) in
let status = (settings.authorizationStatus == .authorized)
completion(status)
})
} else {
if let status = UIApplication.shared.currentUserNotificationSettings?.types{
let status = status.rawValue != UIUserNotificationType(rawValue: 0).rawValue
completion(status)
}else{
completion(false)
}
}
}
<强>用法强>:
isNotificationEnabled { (isEnabled) in
if isEnabled{
print("Push notification enabled")
}else{
print("Push notification not enabled")
}
}
重新:
这是正确的
if (types & UIRemoteNotificationTypeAlert)
但下面是正确的呢! (如UIRemoteNotificationTypeNone是0)
if (types == UIRemoteNotificationTypeNone)
看到以下
NSLog(@"log:%d",0 & 0); ///false
NSLog(@"log:%d",1 & 1); ///true
NSLog(@"log:%d",1<<1 & 1<<1); ///true
NSLog(@"log:%d",1<<2 & 1<<2); ///true
NSLog(@"log:%d",(0 & 0) && YES); ///false
NSLog(@"log:%d",(1 & 1) && YES); ///true
NSLog(@"log:%d",(1<<1 & 1<<1) && YES); ///true
NSLog(@"log:%d",(1<<2 & 1<<2) && YES); ///true
下面是如何在Xamarin.ios做到这一点。
public class NotificationUtils
{
public static bool AreNotificationsEnabled ()
{
var settings = UIApplication.SharedApplication.CurrentUserNotificationSettings;
var types = settings.Types;
return types != UIUserNotificationType.None;
}
}
如果要支持的iOS 10+仅去与UNUserNotificationCenter方法。
在Xamarin,所有上述解决方案不为我工作。 这是我用,而不是:
public static bool IsRemoteNotificationsEnabled() {
return UIApplication.SharedApplication.CurrentUserNotificationSettings.Types != UIUserNotificationType.None;
}
它得到一个实时更新你已经修改了通知状态中的设置也经过。
全便于复制和粘贴代码@ ZacBowling的解决方案( https://stackoverflow.com/a/1535427/2298002建一>)
这也将带给用户您的应用程序设置,并允许他们立即启用
我还添加在溶液中为如果启动位置服务(和带来设置以及)检查
// check if notification service is enabled
+ (void)checkNotificationServicesEnabled
{
if (![[UIApplication sharedApplication] isRegisteredForRemoteNotifications])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Notification Services Disabled!"
message:@"Yo don't mess around bro! Enabling your Notifications allows you to receive important updates"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Settings", nil];
alertView.tag = 300;
[alertView show];
return;
}
}
// check if location service is enabled (ref: https://stackoverflow.com/a/35982887/2298002)
+ (void)checkLocationServicesEnabled
{
//Checking authorization status
if (![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Location Services Disabled!"
message:@"You need to enable your GPS location right now!!"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Settings", nil];
//TODO if user has not given permission to device
if (![CLLocationManager locationServicesEnabled])
{
alertView.tag = 100;
}
//TODO if user has not given permission to particular app
else
{
alertView.tag = 200;
}
[alertView show];
return;
}
}
// handle bringing user to settings for each
+ (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0)// Cancel button pressed
{
//TODO for cancel
}
else if(buttonIndex == 1)// Settings button pressed.
{
if (alertView.tag == 100)
{
//This will open ios devices location settings
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=LOCATION_SERVICES"]];
}
else if (alertView.tag == 200)
{
//This will open particular app location settings
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
else if (alertView.tag == 300)
{
//This will open particular app location settings
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
}
}
GLHF!