我正在寻找一种方法来确定用户是否通过设置启用或禁用了我的应用程序的推送通知。
19 回答
打电话enabledRemoteNotificationsTypes
检查口罩。
例如:
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone)
// blah blah blah
iOS8及以上:
[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]
量子土豆的问题:
由哪里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 开始,不推荐使用 swift 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
}
适用于 iOS10+ 的 RxSwift Observable 版本:
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
像 Kevin 建议的那样使用运气。相反,我使用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
并检查它是否等于(或不等于,取决于您想要的) to UIRemoteNotificationTypeNone
。
然而对于 iOS8 来说,仅仅检查上面的状态并不总是足够的isRegisteredForRemoteNotifications
。您还应该检查是否application.currentUserNotificationSettings.types
等于(或不等于,具体取决于您想要的)UIUserNotificationTypeNone
!
isRegisteredForRemoteNotifications
即使currentUserNotificationSettings.types
返回也可能返回 true UIUserNotificationTypeNone
。
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;
}
}];
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types & UIRemoteNotificationTypeAlert)
// blah blah blah
{
NSLog(@"Notification Enabled");
}
else
{
NSLog(@"Notification not enabled");
}
这里我们从 UIApplication 获取 UIRemoteNotificationType。它表示设置中此应用程序的推送通知状态,您可以轻松检查其类型
我尝试使用@Shaheen Ghiassy 提供的解决方案支持 iOS 10 及更高版本,但发现了剥夺问题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";
希望它也能帮助其他人:) 快乐的编码。
尽管 Zac 的答案在 iOS 7 之前是完全正确的,但自从 iOS 8 到来后它已经发生了变化。因为从 iOS 8 开始已弃用enabledRemoteNotificationTypes 。对于 iOS 8 及更高版本,您需要使用isRegisteredForRemoteNotifications。
- 对于 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 中,以上所有解决方案都对我不起作用。这是我改用的:
public static bool IsRemoteNotificationsEnabled() {
return UIApplication.SharedApplication.CurrentUserNotificationSettings.Types != UIUserNotificationType.None;
}
在您更改“设置”中的通知状态后,它也会获得实时更新。
这是在 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 方法。
从@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!