Odpowiedzi:
Zadzwoń enabledRemoteNotificationsTypes
i sprawdź maskę.
Na przykład:
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone)
// blah blah blah
iOS8 i nowszy:
[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]
iOS 8
i wyższych jest złe, ponieważ sprawdza tylko, czy użytkownik zarejestrował się na zdalne powiadomienie. Zgodnie z dokumentacją:This method reflects only the successful completion of the remote registration process that begins when you call the registerForRemoteNotifications method. This method does not reflect whether remote notifications are actually available due to connectivity issues. The value returned by this method takes into account the user’s preferences for receiving remote notifications.
[[UIApplication sharedApplication] currentUserNotificationSettings];
problem quantumpotato:
Gdzie types
podano przez
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
można użyć
if (types & UIRemoteNotificationTypeAlert)
zamiast
if (types == UIRemoteNotificationTypeNone)
pozwoli ci sprawdzić tylko, czy powiadomienia są włączone (i nie martw się dźwiękami, odznakami, centrum powiadomień itp.). Pierwszy wiersz kodu ( types & UIRemoteNotificationTypeAlert
) powróci, YES
jeśli „Alarm Style” jest ustawiony na „Banery” lub „Alarmy” i NO
jeśli „Alarm Style” jest ustawiony na „Brak”, niezależnie od innych ustawień.
grantedSettings.types.contains(notificationType)
W najnowszej wersji iOS ta metoda jest obecnie przestarzała. Aby obsługiwać zarówno iOS 7, jak i iOS 8 użyj:
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;
}
UserNotifications
. Niestety nie mam teraz pełnej odpowiedzi.
Zaktualizowany kod dla 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()
}
Kod dla swift3.0, iOS10
let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications
if isRegisteredForRemoteNotifications {
// User is registered for notification
} else {
// Show alert user is not registered for notification
}
W systemie iOS9 swift 2.0 UIRemoteNotificationType jest przestarzały, użyj następującego kodu
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.
}
po prostu sprawdź, czy powiadomienia push są włączone
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
}
Poniżej znajdziesz pełny przykład, który obejmuje zarówno iOS8, jak i iOS7 (i niższe wersje). Należy pamiętać, że przed systemów iOS 8 nie można odróżnić „zdalnych powiadomień niepełnosprawnych” i „tylko View w lockscreen włączoną”.
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");
Swift 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
}
Wersja obserwowalna RxSwift na 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()
}
}
}
getNotificationSettings(...)
jest asynchroniczny, więc powrót do środka zostanie zignorowany
Próbując obsługiwać zarówno iOS8, jak i starsze, nie miałem szczęścia, używając isRegisteredForRemoteNotifications
Kevina. Zamiast tego użyłem currentUserNotificationSettings
, co działało świetnie w moich testach.
+ (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;
}
isEnabled = NO;
w twoich if
przypadkach nie jest potrzebny, ponieważ został zainicjowany jakoNO
Niestety żadne z tych rozwiązań nie rozwiązało problemu, ponieważ na koniec dnia interfejsów API poważnie brakuje, jeśli chodzi o dostarczanie odpowiednich informacji. Możesz zrobić kilka domysłów, jednak użycie currentUserNotificationSettings
(iOS8 +) po prostu nie jest wystarczające w obecnej formie, aby naprawdę odpowiedzieć na pytanie. Chociaż wiele rozwiązań tutaj sugeruje, że albo to alboisRegisteredForRemoteNotifications
raczej ostateczna odpowiedź, tak naprawdę nie jest.
Rozważ to:
z isRegisteredForRemoteNotifications
dokumentacją stwierdza:
Zwraca TAK, jeśli aplikacja jest obecnie zarejestrowana do zdalnych powiadomień, biorąc pod uwagę wszelkie ustawienia systemowe ...
Jeśli jednak rzucisz po prostu NSLog
delegata aplikacji, aby obserwować zachowanie, jasne jest, że nie zachowuje się tak, jak się spodziewamy. Odnosi się to bezpośrednio do aktywacji zdalnych powiadomień dla tej aplikacji / urządzenia. Raz aktywowane po raz pierwszy, zawsze wróci YES
. Nawet wyłączenie ich w ustawieniach (powiadomieniach) nadal spowoduje ich zwrócenie. YES
Dzieje się tak, ponieważ od iOS8 aplikacja może rejestrować się w celu otrzymywania powiadomień zdalnych, a nawet wysyłać je na urządzenie bez włączonego powiadomienia użytkownika, po prostu nie może generować alertów, Odznaki i dźwięk bez włączania go przez użytkownika. Ciche powiadomienia są dobrym przykładem czegoś, co możesz robić nawet po wyłączeniu powiadomień.
O ile currentUserNotificationSettings
wskazuje na jedną z czterech rzeczy:
Alerty są włączone Odznaki są włączone Dźwięk jest włączony Żadne nie są włączone.
Nie daje to absolutnie żadnych wskazówek na temat innych czynników ani samego przełącznika powiadomień.
Użytkownik może w rzeczywistości wyłączyć odznaki, dźwięk i alerty, ale nadal może wyświetlać się na ekranie blokady lub w centrum powiadomień. Ten użytkownik powinien nadal otrzymywać powiadomienia wypychane i widzieć je zarówno na ekranie blokady, jak iw centrum powiadomień. Mają włączoną funkcję powiadomień. ALE currentUserNotificationSettings
wróci: UIUserNotificationTypeNone
w takim przypadku. Nie świadczy to o rzeczywistych ustawieniach użytkowników.
Można zgadnąć kilka przypuszczeń:
isRegisteredForRemoteNotifications
tak NO
, możesz założyć, że to urządzenie nigdy nie zarejestrowało się pomyślnie dla zdalnych powiadomień.application:didRegisterUserNotificationSettings:
w tym momencie oddzwonienie zawierające ustawienia powiadomień użytkownika, ponieważ jest to pierwsza rejestracja użytkownika, ustawienia powinny wskazywać to, co użytkownik wybrał w ramach żądania zezwolenia. Jeśli ustawienia są równe czemuś innemu niż: UIUserNotificationTypeNone
to zezwolenie push zostało udzielone, w przeciwnym razie zostało odrzucone. Powodem tego jest to, że od momentu rozpoczęcia procesu zdalnej rejestracji użytkownik może jedynie zaakceptować lub odrzucić, przy czym początkowe ustawienia akceptacji są ustawieniami ustawionymi podczas procesu rejestracji.Aby uzyskać odpowiedź, może działać mniej więcej tak ...
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
switch (types) {
case UIRemoteNotificationTypeAlert:
case UIRemoteNotificationTypeBadge:
// For enabled code
break;
case UIRemoteNotificationTypeSound:
case UIRemoteNotificationTypeNone:
default:
// For disabled code
break;
}
edycja: To nie w porządku. ponieważ są to rzeczy nieco bitowe, nie będzie działać z przełącznikiem, więc przestałem używać:
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
UIRemoteNotificationType typesset = (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge);
if((types & typesset) == typesset)
{
CeldaSwitch.chkSwitch.on = true;
}
else
{
CeldaSwitch.chkSwitch.on = false;
}
Na iOS7 i wcześniej powinieneś rzeczywiście użyć enabledRemoteNotificationTypes
i sprawdzić, czy jest równy (lub nie jest równy w zależności od tego, czego chcesz) UIRemoteNotificationTypeNone
.
Jednak w przypadku iOS8 nie zawsze wystarczy sprawdzić tylko isRegisteredForRemoteNotifications
tyle stanów powyżej. Powinieneś również sprawdzić, czy application.currentUserNotificationSettings.types
jest równy (lub nie jest równy w zależności od tego, czego chcesz) UIUserNotificationTypeNone
!
isRegisteredForRemoteNotifications
może zwrócić wartość true, mimo że currentUserNotificationSettings.types
zwraca UIUserNotificationTypeNone
.
iOS8 + (CEL 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");
}
Tutaj otrzymujemy UIRemoteNotificationType od UIApplication. Reprezentuje stan powiadomienia wypychanego tej aplikacji w ustawieniu, niż można łatwo sprawdzić jej typ
Staram się wspierać system iOS 10 i nowsze wersje za pomocą rozwiązania dostarczonego przez @Shaheen Ghiassy, ale znajduję problem z deprywacją enabledRemoteNotificationTypes
. Tak więc rozwiązanie, które znalazłem, isRegisteredForRemoteNotifications
zamiast tego, enabledRemoteNotificationTypes
które jest przestarzałe w iOS 8. Poniżej znajduje się moje zaktualizowane rozwiązanie, które działało idealnie dla mnie:
- (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;
}
Możemy łatwo wywołać tę funkcję i uzyskać dostęp do jej Bool
wartości, a następnie przekonwertować ją na wartość ciągu:
NSString *str = [self notificationServicesEnabled] ? @"YES" : @"NO";
Mam nadzieję, że pomoże to również innym :) Szczęśliwego kodowania.
Chociaż odpowiedź Zac była całkowicie poprawna do iOS 7, zmieniła się od czasu pojawienia się iOS 8. Ponieważ enabledRemoteNotificationTypes został wycofany z iOS 8 i późniejszych. W systemie iOS 8 i nowszych musisz użyć isRegisteredForRemoteNotifications .
To rozwiązanie Swifty działało dobrze dla mnie ( iOS8 + ),
Metoda :
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)
}
}
}
Zastosowanie :
isNotificationEnabled { (isEnabled) in
if isEnabled{
print("Push notification enabled")
}else{
print("Push notification not enabled")
}
}
re:
to jest poprawne
if (types & UIRemoteNotificationTypeAlert)
ale przestrzeganie również jest poprawne! (ponieważ UIRemoteNotificationTypeNone ma wartość 0)
if (types == UIRemoteNotificationTypeNone)
patrz poniżej
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
Oto jak to zrobić w Xamarin.ios.
public class NotificationUtils
{
public static bool AreNotificationsEnabled ()
{
var settings = UIApplication.SharedApplication.CurrentUserNotificationSettings;
var types = settings.Types;
return types != UIUserNotificationType.None;
}
}
Jeśli wspierasz iOS 10+, korzystaj tylko z metody UNUserNotificationCenter.
W Xamarin wszystkie powyższe rozwiązania nie działają dla mnie. Właśnie tego używam:
public static bool IsRemoteNotificationsEnabled() {
return UIApplication.SharedApplication.CurrentUserNotificationSettings.Types != UIUserNotificationType.None;
}
Otrzymuje aktualizację na żywo także po zmianie statusu powiadomienia w Ustawieniach.
Pełny łatwy kod do kopiowania i wklejania zbudowany z rozwiązania @ ZacBowling ( https://stackoverflow.com/a/1535427/2298002 )
Spowoduje to również przejście użytkownika do ustawień aplikacji i umożliwi mu natychmiastowe włączenie
Dodałem również w rozwiązaniu do sprawdzania, czy usługi lokalizacyjne są włączone (i doprowadzają również do ustawień)
// 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!