2017-01-23 10 views
1

以前のiOSバージョンとiOS 10の両方で同時にプッシュ通知を正しく実装する方法についてAppleの正式なドキュメントが見つかりませんでした。また、私が見たような独立したチュートリアルも同じようにiOSバージョンをカバーしています。iOSバージョン9 + 10(およびおそらく8)のApple Push Notificationの実装方法は?

iOS 10の公式ドキュメントを参照してください。 Local and Remote Notifications Overview以前のiOSバージョンのサポートについてはコメントしていません。

とiOS 9のためのチュートリアル:コードを示してい

Push notifications are not working in iOS 9 :私は変更の人々について様々なstackoverflowのスレッドを参照してください Push Notifications Tutorial - Ray Wenderlich

とは、古いソリューションは、新しいバージョンで動作するように取得するためにしなければなりませんでした9.

didReceiveRemoteNotification not called , iOS 10


から6を処理するための

しかし、わからないことは、今日から(iOS 10を使用して)始まり、古いデバイスをサポートするのが正しいことです。 ** UPDATE ** App Storeでは、アプリケーションをダウンロードするデバイスのうち6%のみがios 9より古いと言われています。したがって、は、9 + 10をサポートする方が簡単な場合はそれを実行します。

(私はiOS 10の例から始めましたが、iOS 9.3のエミュレートされたデバイスですぐにクラッシュしましたが、iOS 10では問題なく動作します。私はそのコードを投稿することができましたが、間違った方向でこのスレッドをリードしていると思います.1030を含む複数のバージョンのiOSで "うまくいく"ものから始めたいと思っています。)

見つからない場合いくつかの解決策、私は異なるstackoverflowコードスニペットからコードを組み合わせ始める...しかし真剣に?おそらくすべてのiOS開発者がこの問題を抱えているように、私は何かが欠けているはずです。逆に


私は古い例で開始し、その後、それはiOSの10で動作するように取得するために変化に追従でき - それはiOSの10をフルに活用するのだろうか?

注:私はXamarin C#でプログラミングしていますが、Objective-CまたはSwiftの答えも同様に便利です。

+0

ToolmakerSteve、ローカル通知またはリモートが必要ですか?リモートの場合は、実際のデバイスを使用してテストする必要があります。 – aircraft

+0

@aircraftローカルとリモートの両方。私の会社には、iOS 10デバイスで動作するアプリストアにアプリがありますが、iOS 9.3デバイスではクラッシュします。はい、実際のデバイスでテストされています。 [残念なことに、難しい方法をテスト...]それがクラッシュしたローカルまたはリモートであるかどうかはまだ分かりません - 残念ながら私はこのコードを書いていない、私はすべてこれについて学んでいるので、私はアプリを修正することができます。 – ToolmakerSteve

+0

@aircraft .. iPhoneをjailbreakingせずに、iOS 10以前のバージョンに戻ることはもはや不可能であることを知りました。そうするつもりはないので、エミュレータでできるだけ多くのテストをしてから、iOS 9.3 – ToolmakerSteve

答えて

3

これはXamarin C#コードです(Objective-Cとは異なる構文と大文字小文字が使用されていますが、Objective-Cでは行単位で翻訳可能です)。

iOS 9.3とiOS 10.2の両方でテスト済みです。それは通知を受け取ることができるように上記のコードは、アプリケーションを初期化し

// "UIApplicationDelegate" is for "local" notifications, 
// "IUNUserNotificationCenterDelegate, IMessagingDelegate" for "remote" notifications. 
public class AppDelegate : UIApplicationDelegate, 
    IUNUserNotificationCenterDelegate, IMessagingDelegate 
{ 
    ... 
    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) 
    { 
     ... 
     RegisterForOurRemoteNotifications(this); 
     RegisterForOurLocalNotifications(); 
     ... 
    } 
    ... 

    // --- Comment out if not using Google FCM. --- 
    public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) 
    { 
     //base.RegisteredForRemoteNotifications(application, deviceToken); 
     Firebase.InstanceID.InstanceId.SharedInstance.SetApnsToken(deviceToken, 
                    Firebase.InstanceID.ApnsTokenType.Sandbox); 
    } 

    ... 
    // ----- "static"; Could be in another class. ----- 

    // These flags are for our convenience, so we know initialization was done. 
    static bool IsRegisteredForNotifications; 
    static bool IsRegisteredForRemoteNotifications; 
    // Optional - true when we are using Google "Firebase Cloud Messaging". 
    static bool HasFCM; 

    public static void RegisterForOurRemoteNotifications(AppDelegate del) 
    { 
     // Google "Firebase Cloud Messaging" (FCM) Monitor token generation 
     // (Uncomment, if you are using FCM for notifications.) 
     //InstanceId.Notifications.ObserveTokenRefresh(TokenRefreshNotification); 

     if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0)) { 
      // iOS 10 or later 
      var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound; 
      UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) => { 
       Console.WriteLine(granted); 
      }); 

      // For iOS 10 display notification (sent via APNS) 
      UNUserNotificationCenter.Current.Delegate = del; 

      // For iOS 10 data message (sent via Google FCM). 
      // (Uncomment, if you are using FCM for notifications.) 
      // TBD: If NOT using FCM, you may need some other lines of code here. 
      //Messaging.SharedInstance.RemoteMessageDelegate = del; 

     } else { 
      // iOS 9 or before 
      var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound; 
      var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null); 
      UIApplication.SharedApplication.RegisterUserNotificationSettings(settings); 
     } 

     UIApplication.SharedApplication.RegisterForRemoteNotifications(); 
     IsRegisteredForRemoteNotifications = true; 

     // Uncomment if using Google "Firebase Cloud Messaging" (FCM). 
     //TokenRefreshNotification(null, null); 
     //if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0)) // Needed to call this twice on iOS 9 for some reason. 
     // TokenRefreshNotification(null, null); 


     UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval(UIApplication.BackgroundFetchIntervalMinimum); 
    } 

    public static void RegisterForOurLocalNotifications() 
    {    
     // --- Our app's notification actions. --- 
     UNNotificationAction followAction = UNNotificationAction.FromIdentifier("follow", PS.LocalizedString("Follow"), UNNotificationActionOptions.None); 
     UNNotificationAction likeAction = UNNotificationAction.FromIdentifier("like", PS.LocalizedString("Like"), UNNotificationActionOptions.None); 
     // ... 

     // --- Our app's notification categories --- 
     UNNotificationCategory followCategory = UNNotificationCategory.FromIdentifier("followCategory", new UNNotificationAction[] { followAction, likeAction }, 
                       new string[] { }, UNNotificationCategoryOptions.None); 
     // ... 

     // --- All of the app's categories from above --- 
     var categories = new UNNotificationCategory[] { followCategory /*, ...*/ }; 


     // --- Same for all apps --- 
     UIUserNotificationSettings settings = UIUserNotificationSettings.GetSettingsForTypes(
                UIUserNotificationType.Alert | 
                UIUserNotificationType.Badge | 
                UIUserNotificationType.Sound 
      , new NSSet(categories)); 
     UIApplication.SharedApplication.RegisterUserNotificationSettings(settings); 


     if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0)) { 
      UNUserNotificationCenter.Current.SetNotificationCategories(new NSSet<UNNotificationCategory>(categories)); 

      UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert | UNAuthorizationOptions.Sound | UNAuthorizationOptions.Badge, 
                    (result, err) => { 
                     Console.WriteLine(result.ToString()); 
                    }); 
     } 

     IsRegisteredForNotifications = true; 
    } 
} 


    // ------------------------------------------------------- 
    // --- These are for Google "Firebase Cloud Messaging" --- 
    // (Comment out if not using FCM.) 

    public static string Token; 

    static void TokenRefreshNotification(object sender, NSNotificationEventArgs e) 
    { 
     // This method will be fired every time a new token is generated, including the first 
     // time. So if you need to retrieve the token as soon as it is available this is where that 
     // should be done. 
     //var refreshedToken = InstanceId.SharedInstance.Token; 

     ConnectToFCM(UIApplication.SharedApplication.KeyWindow.RootViewController); 

     // TODO: If necessary send token to application server. 
    } 


    public static void ConnectToFCM(UIViewController fromViewController) 
    { 
     Messaging.SharedInstance.Connect(error => { 
      if (error != null) { 
       Helper.logD("Unable to connect to FCM", error.LocalizedDescription); 
      } else { 
       //var options = new NSDictionary(); 
       //options.SetValueForKey(DeviceToken, Constants.RegisterAPNSOption); 
       //options.SetValueForKey(new NSNumber(true), Constants.APNSServerTypeSandboxOption); 

       //InstanceId.SharedInstance.GetToken("", InstanceId.ScopeFirebaseMessaging 
       Token = InstanceId.SharedInstance.Token; 

       Console.WriteLine($"Token: {InstanceId.SharedInstance.Token}"); 
       HasFCM = true; 
      } 
     }); 
    } 
    // ------------------ End Google FCM --------------------- 
    // ------------------------------------------------------- 
} 

:「ローカル」と「リモート」の通知を初期化するために

重要:また、アプリケーションに適切なアクセス許可を設定する必要があります。アップルのドキュメント、または質問に記載されているリンクを参照してください。

Entitlements.plist:上記

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
<plist version="1.0"> 
<dict> 
    <key>aps-environment</key> 
    <string>development</string> 
</dict> 
</plist> 

<string> "開発" 又は "製造" のいずれかを含める必要がありますそして、あなたはこのファイルを必要としています。 (Appleの意義はまだ「開発」と言っていますが、Appleに提出する前にXcodeが自動的に「制作」に変更されているかどうかは検証されていません。https://stackoverflow.com/a/40857877/199364によるとします。 )


は、その後、あなたが送っにコードを必要とする [例えばあなたのアプリはあなたの現在のことをあなたの友人のデバイスに通知するようあなたのサーバーに伝えます] ローカルまたはリモート通知を受け取ります。そのコードは、私たちのアプリでは、私たちの特定の通知アクションとカテゴリと組み合わされています。私はここに投稿するための簡潔なバージョンを抽出する時間がありません。詳細については、Appleのドキュメント、または元の質問に記載されているリンクを参照してください。あなたが/上書きまたは実装する必要がある場合があります

public override void ReceivedLocalNotification(UIApplication application, UILocalNotification notification) 
    { 
     ... 
    } 

    public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler) 
    { 
     ... 
    } 


    [Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")] 
    public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler) 
    { 
     ... 
    } 

他の方法(上記class AppDelegateに宣言されているインタフェースを参照してください):ここでは

に不可欠な方法は、(上記class AppDelegateに追加)通知を受信して​​います; FCMに固有のものもあります:

ApplicationReceivedRemoteMessage 
ReceivedRemoteNotification 
WillPresentNotification 
PerformFetch (for background notifications) 
HandleAction 
関連する問題