didRegisterForRemoteNotificationsWithDeviceTokenが呼び出されない理由


89

アップルプッシュ通知サービスを実装したいアプリケーションを作っています。私はこのチュートリアルで与えられたステップバイステップの指示に従っています。

しかし、それでも、メソッドは呼び出されません。何が問題を引き起こしているのかわかりません。誰か助けてもらえますか?

    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 
        //NSString * token = [[NSString alloc] initWithData:deviceTokenencoding:NSUTF8StringEncoding];
        NSString *str = [NSString stringWithFormat:@"Device Token=%@",deviceToken];
        NSLog(@"Device Token:%@",str);

        //NSLog(@"Device token is called");
        //const void *devTokenBytes = [deviceToken bytes];
        //NSLog(@"Device Token");
    }

    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 
        NSString *str = [NSString stringWithFormat: @"Error: %@", err];
        NSLog(@"Error:%@",str);    
    }

他のコードを追加する必要がないだけで、それはリンクチェックstackoverflow.com/a/39849892/3269536
jenish

回答:


74

私は同じ問題を抱えていました:呼び出しregisterForRemoteNotificationTypes:は呼び出されずapplication:didRegisterForRemoteNotificationsWithDeviceToken:application:didFailToRegisterForRemoteNotificationsWithError:

私は最終的にAppleのテクニカルノートTN2265の助けを借りてこの問題を解決しました

これは私がしたことです:

まず、プッシュ通知に正しく登録していることを再確認しました、「aps-environment」キーのプロビジョニングプロファイルと.appファイル自体のコード署名の確認を含めを再確認しました。私はそれをすべて正しく設定しました。

次に、コンソールでプッシュ通知ステータスメッセージをデバッグする必要がありました(デバイスにPersistentConnectionLogging.mobileconfigプロビジョニングプロファイルをインストールして再起動する必要があります。「プッシュステータスメッセージの監視」のTN2265を参照してください)。apnsプロセスがタイマーを開始し、最小発火日を計算することに気付きました。これにより、TN2265に示されているように、この時点で通常表示されるプッシュ通知登録確認メッセージがAPNSによって抑制されていると思われます。

iOSでのプッシュ通知権限アラートのリセット

プッシュ対応アプリがプッシュ通知に初めて登録するとき、iOSはユーザーにそのアプリの通知を受信するかどうかを尋ねます。ユーザーがこのアラートに応答すると、デバイスが復元されるか、アプリが少なくとも1日アンインストールされない限り、アラートは再度表示されません。

アプリの初回実行をシミュレートする場合は、アプリを1日アンインストールしたままにしておくことができます。システムクロックを1日以上進め、デバイスを完全にオフにしてからオンに戻すことで、実際に1日待つことなく後者を実現できます。

そこで、デバイスからアプリを削除し、[設定]でiPhoneの日付を手動で変更し、デバイスを再起動して、アプリを再インストールしました。

次回私のコードが呼び出されたとき、registerForRemoteNotificationTypes期待どおりにコールバックを受け取りました。

これで問題は解決しました。それが役に立てば幸い。


1
私にとって重要な点は、別のマシンで古い開発証明書を使用していたことです。メインの開発用ラップトップから最新の証明書を転送すると、この問題が修正されました。
Markus Rautopuro 2014年

3
有効にした後、プロビジョニングプロファイルを再度生成するには、プッシュ通知が必要です。
トニー

3
こんにちは!これは古い投稿ですが、アプリのすべての通知設定をオフまたはオンにすると修正される場合があることがわかりました。前回didRegisterForRemoteNotificationsWithDeviceTokenが呼び出されたのを覚えているので、突然呼び出されませんでした。それが役に立てば幸い。
otakuProgrammer 2014

1
これは、別のリセット手順を追加することによってのみ機能します。1。アプリを削除する2.デバイスをリセットする3.時計を1日以上転送する4.デバイスを再度リセットする5.インストールすると、プッシュ通知アラートが表示されます
etayluz 2015年

Xcodeまたはデバイス自体のいずれかに、同じ開発プロビジョニングプロファイルの複数の「有効な」コピーがないことを確認することも重要です。おそらく、新しいAPN証明書を作成し、前の証明書の有効期限が切れた後にプロビジョニングプロファイルを再作成しました。古い開発プロファイルは引き続き開発プロファイルとして有効ですが、APNを有効にするのに十分ではありません。「有効なaps-entitlementblahblahがありません」に関する一般的なエラーが表示されます。
jaredsinclair 2015

66

iOS 8では、一部のメソッドが非推奨になりました。iOS 8との互換性については、以下の手順に従ってください

1.登録通知

if([[UIDevice currentDevice] systemVersion].floatValue >= 8.0)
{
    UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];    
}
else
{
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound|UIRemoteNotificationTypeBadge)];
}

2.新しい2つのメソッドを追加します

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
    //register to receive notifications
    [application registerForRemoteNotifications];
}

//For interactive notification only
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
{
    //handle the actions
    if ([identifier isEqualToString:@"declineAction"]){
    }
    else if ([identifier isEqualToString:@"answerAction"]){
    }
}

注:iOS 8では、didRegisterForRemoteNotificationsWithDeviceTokenおよびに加えて、上記の2つの新しい方法が必要です。didReceiveRemoteNotification..Otherwiseのデリゲートメソッドが呼び出されることはありません。

参照:リモート通知iOS 8


1
これらの2つの新しいメソッドをAppdelegate.mに含める必要がありますか?
イーサンパーカー

-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {//通知を受信するための登録[applicationregisterForRemoteNotifications]; 以下を追加すると危険です。電話がクラッシュし、この時点で出荷時設定にリセットすることすらできません。
ジョン

あなたがここに行き着くなら、これはおそらくあなたが探している答えです。奇妙なことに、私がこれらのメソッドの1つを追加せずに、デリゲートが今日早く呼び出されました。今は両方が必要なようです。
2015

私のアプリはこの行でクラッシュします[application registerForRemoteNotifications];
smithyy 2015

26

ではiOSの8、異なっプッシュ通知へのアクセスを要求することに加えて、あなたはまた違っ登録する必要があります。

アクセスのリクエスト:

if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
    // iOS 8
    UIUserNotificationSettings* settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
    // iOS 7 or iOS 6
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}

登録済みデバイスの処理:

// New in iOS 8
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    [application registerForRemoteNotifications];
}

// iOS 7 or iOS 6
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    // Send token to server
}

非常に役に立ちました。通知が壊れた理由がわかりませんでした。
GoldenJoe 2014年

4
iOS 8でトークンを取得するにはどうすればよいですか?
yossi 2014年

@Yossiは、次の「トークン」変数に格納されますapplication:didRegisterForRemoteNotificationsWithDeviceToken:
Kyle Clegg

私のアプリはこの行でクラッシュします[applicationregisterForRemoteNotifications];
smithyy 2015

13

シミュレータではリモート通知はサポートされていないことに注意してください。したがって、シミュレーターでアプリを実行すると、didRegisterForRemoteNotificationsWithDeviceTokenは呼び出されません。


@hochl:質問に具体的に答えるように、答えを更新しました。
エリック

1
didFailToRegisterForRemoteNotificationsWithErrorも呼び出されないことに注意してください。実際、[設定]でアプリのプッシュ通知を無効にした場合(デバイスまたはシミュレーターのいずれでも)、どちらの通知も呼び出されません。Appleはこれをエラーとは見なしていないようですstackoverflow.com/questions/9199935/…–
Zack Morris

12

必ずコードを呼び出してください(サポートされている通知の種類に応じて更新してください)

[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];

プロビジョニングプロファイルでAPNSが有効になっています。APNSを有効にした後、プロビジョニングプロファイルを再ダウンロードする必要がある場合があります。問題が発生してエラーが発生した場合は、Entitlements.plistを作成し、ビルドの種類に応じて値が「development」または「production」のキー「aps-environment」を追加する必要があります(通常、このキーと値のペアはプロビジョニングプロファイルに含まれていますが、Xcodeがそれらを混乱させることがあります)。


注:「プロビジョニングプロファイルはAPNS対応です。」プロジェクトツリー>機能>プッシュ通知をオンに設定する必要がありますの上部をクリックします。
trevorgrayson 2016

6

以前にプロビジョニングプロファイルを使用してAppleプッシュ通知サービスを有効にして構成した場合は、プロビジョニングプロファイルを再度ダウンロードする必要があります。

XcodeOrganizerおよびiPhone / iPadからプロビジョニングプロファイルを削除します。に移動Settings -> General -> Profiles -> [Your provisioning] -> Removeます。

ダウンロードした新しいプロビジョニングプロファイルをインストールします。次に、XCodeからプロジェクトをクリーンアップして実行します。今didRegisterForRemoteNotificationsWithDeviceToken呼び出されるべきです。


それは私のために働きます。アプリのAPNを登録した認証とプロビジョニングを選択しただけです。
lee 2014年

iphone(ios9)からすべてのプロビジョニングプロファイルを削除し、デバイストークンが受信された後、これを修正するために4時間かかります(私は多くを学びますが)。ありがとう
Shobhakar Tiwari 2015

3

私は間違いを犯し、ここに私を導く実装の詳細を見落としました。私は私が私が持っていたので、空想を取得し、アプリケーションのオンボーディングプロセスの後半でプッシュ通知をユーザーに尋ねることを試みたregisterForRemoteNotificationTypesdidRegisterForRemoteNotificationsWithDeviceTokendidFailToRegisterForRemoteNotificationsWithErrorカスタムUIViewの中ですべてを。

修正:didRegisterForRemoteNotificationsWithDeviceTokendidFailToRegisterForRemoteNotificationsWithErrorUIApplicationDelegateYourAppDelegate.m)がトリガされます。

今は当たり前のようですね。


はい、メソッドはにある必要がありますAppDelegate。私がこの単純な答えで過去数時間を無駄にしたとは信じられません
チェンでさえ2016

3

インターネット接続がオンになっていることを確認してください。インターネットに接続しているため、仕事の通知を受け取るのに何時間もかかりました。


3

既存のアプリIDにプッシュを追加した場合は、プロビジョニングプロファイルを再生成してください。そうしないと、プロファイルはアプリIDでのプッシュの有効化について認識しません。


3

これを試してみてください、

最初の一歩

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

上記の方法で以下のコードを追加します

 UIApplication *application = [UIApplication sharedApplication];
 if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge
                                                                                     |UIUserNotificationTypeSound
                                                                                     |UIUserNotificationTypeAlert) categories:nil];
[application registerUserNotificationSettings:settings];
 } 
 else {
      UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
     }

第二段階

以下のコードを追加機能

 #ifdef __IPHONE_8_0
   - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
   {
  //register to receive notifications
  [application registerForRemoteNotifications];
  }

 - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler
  {
    //handle the actions
    if ([identifier isEqualToString:@"declineAction"]){
    }
   else if ([identifier isEqualToString:@"answerAction"]){
   }
}
 #endif

以下の機能でデバイストークンを取得します

 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 

詳細な回答については、こちらを参照してください

これが誰かの助けになることを願っています。


2
-​(BOOL)application:(UIApplication​*)application​ didFinishLaunchingWithOptions:(NSDictionary​*)launchOptions​{​​​​ ​​​​ ​​​​//​Override​point​for​customization​after​application​launch.
​​​​//​Add​the​view​controller’s​view​to​the​window​and​display. ​​​​[window​addSubview:viewController.view]; ​​​​[window​makeKeyAndVisible];
NSLog(@”Registering for push notifications...”);
 [[UIApplication sharedApplication]
registerForRemoteNotificationTypes: (UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound)]; 
​​​​returnYES;
}


- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
}
NSString *str = [NSString stringWithFormat:@”Device Token=%@”,deviceToken];
NSLog(@”%@”, str);


- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSString *str = [NSString stringWithFormat: @”Error: %@”, err]; NSLog(@”%@”, str);
}


- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
}
for (id key in userInfo) { NSLog(@”key: %@, value: %@”, key, [userInfo objectForKey:key]);
}

2

デバイストークンを取得するための最小限の要件:

アプリID、プロビジョニング、証明書などを構成する必要がないため、デリゲートメソッドdidRegisterForRemoteNotificationsWithDeviceTokenを取得するためのコード署名が設定されていません。

Xcode 7でデフォルト設定のシングルビュー用の新しいiOSプロジェクトを作成し、Apple DevPortalで構成されていないcom.mycompany.pushtestのようなランダムなバンドルIDを指定しました。

次のコードを使用して、Wi-FiにインターネットアクセスできるiPadのdidRegisterForRemoteNotificationsWithDeviceTokenメソッドでデバイストークンを取得してます。デバイスが接続されており、xcodeから直接アプリを実行し、xcodeのコンソールで値を表示しています。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   

{  
    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)])  
    {  
        UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound);  
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes categories:nil];  
        [application registerUserNotificationSettings:settings];  
        [application registerForRemoteNotifications];  
    }  
    else  
    {  
        // Register for Push Notifications, if running iOS version < 8  
        [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];  
    }  
    return YES;  
}  


- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"Error: %@", error.description);
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSLog(@"didRegisterForRemoteNotificationsWithDeviceToken: %@", deviceToken);
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    NSLog(@"NotificationSettings: %@", notificationSettings);
}

1

最近、私もこの問題に直面しています。ドキュメントに従ってすべてを実行しましたが、デリゲートメソッドが呼び出されませんでした。最後に、ネットワークに問題があるという投稿が1つありました。その後、ネットワークを変更しましたが、正常に動作しています。したがって、APNSをブロックできるネットワークはほとんどないため、ネットワークにも注意してください。


1

最も厄介な3時間を無駄にした後、問題を修正する手順は次のとおりです。

  1. アプリを削除します

  2. デバイスをリセットする

  3. 再実行

それはうまくいった


0

私は電話のすべてのデータをリセットして削除したので、これは私に起こりました(開発者の電話を使用したかった)。これにより、電話を再度セットアップした後、APNがまったく接続できなくなりました。

私はいろいろなことを試しましたが、それを修正した唯一のことは、新しいSIMカードの下でキャリアで動作するように電話を設定することでした。

このリンクは、何が起こっているのかについてのより多くのヒントを提供します:https//developer.apple.com/library/ios/technotes/tn2265/_index.html

APNは、wifiではなくキャリア/タワーを介して優先的に接続しようとしているとのことです。Wi-Fiネットワークのポート5223をブロックしているルーターで問題が発生している可能性もありますが、グローバルリセットが発生する前日に正常に機能したため、疑わしいです。


0

私にとって解決したのは、ビルド設定とコード署名セクションで、コード署名IDとプロビジョニングプロファイルを手動で選択することでした。どうやら自動設定が正しい設定を取得していなかったため、アプリが適切に承認されていませんでした。


0

アプリのプッシュメッセージをシャットダウンした場合、

appdidRegisterForRemoteNotificationsWithDeviceTokenが呼び出されることはありません


0

また、Applehttps://developer.apple.com/system-status/でシステムステータスを確認することを忘れないでください

上記のすべての解決策を試しましたが、最終的にはAPNSサービスがダウンしたことが原因でした。翌日、すべてが期待どおりに再び機能していました。

また、コールバックメソッドにタイプミスがあります。

- (void)application:(UIApplication *)appdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

Rupeshが指摘したように、正しいメソッド名は次のとおりです。

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

それがおそらくあなたがあなたのケースでトークンを受け取ったことがない理由です!


実際にはメソッド名が正しくありません。次のようになります-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceTokenパラメーターの間にスペースがあります
Rupesh

ありがとう、あなたのコメントを含むように答えを更新しました。これがOPの問題の解決策であることは間違いありませんが、わからない場合があります。
ブレット

0

didFinishLaunchingWithOptionsからregisterForNotificationsメソッドを呼び出す必要があります。

 func registerForNotifications(){

        if #available(iOS 10.0, *) {

            let center = UNUserNotificationCenter.current()
            center.delegate = self
            center.requestAuthorization(options:[.alert,.sound,.badge]) { (granted, error) in
                if granted{
                    UIApplication.shared.registerForRemoteNotifications()
                }else{

                    print("Notification permission denied.")

                }
            }

        } else {

            // For iOS 9 and Below
            let type: UIUserNotificationType = [.alert,.sound,.badge];
            let setting = UIUserNotificationSettings(types: type, categories: nil);
            UIApplication.shared.registerUserNotificationSettings(setting);
            UIApplication.shared.registerForRemoteNotifications()
        }
    }

 func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

        let token = String(format: "%@", deviceToken as CVarArg).trimmingCharacters(in: CharacterSet(charactersIn: "<>")).replacingOccurrences(of: " ", with: "")
        print(token)

    }


extension AppDelegate : UNUserNotificationCenterDelegate{

    @available(iOS 10.0, *)

    func userNotificationCenter(_ center: UNUserNotificationCenter,  willPresent notification: UNNotification, withCompletionHandler   completionHandler: @escaping (_ options:   UNNotificationPresentationOptions) -> Void) {
        print("Handle push from foreground”)

        let info = ((notification.request.content.userInfo as NSDictionary).value(forKey: "aps") as! NSDictionary)
        if let type = info.value(forKey: "type") as? Int{
            if type == 0 {  

         // notification received ,Handle your notification here

            }
        }
    }

    @available(iOS 10.0, *)

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        print("Handle push from background or closed")

        let info = ((response.notification.request.content.userInfo as NSDictionary).value(forKey: "aps") as! NSDictionary)
        if let type = info.value(forKey: "type") as? Int{
            if type == 0 {   

            // notification received ,Handle your notification here
            }
        }
    }
}

0

プッシュ通知のコールバックが、私が含めたサードパーティのライブラリ、つまりFirebaseによってハイジャックされるという別の問題がありました。これらのライブラリは、プッシュ通知コールバックメソッドをスウィズルしてコールバックを取得します。

これが誰かを助けることを願っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.