2017-01-23 3 views
1

Я не нашел официального документа Apple, в котором обсуждается правильное внедрение push-уведомления одновременно для старых версий iOS, а также для iOS 10. И независимые обучающие программы, которые я видел, также охватывают одну версию iOS.Как реализовать уведомления Apple Push для версий iOS 9 + 10 (и, возможно, 8)?

Я вижу этот официальный документ для iOS 10: Local and Remote Notifications Overview Но он не комментирует поддержку предыдущих версий iOS.

И учебник для прошивки 9: Push Notifications Tutorial - Ray Wenderlich

И я вижу различные StackOverflow темы об изменениях людей должны был сделать, чтобы получить свои старые решения, чтобы работать на более новые версии:

Push notifications are not working in iOS 9 который не показывает код для обработки 6 - 9.

didReceiveRemoteNotification not called , iOS 10


НО, что я не вижу, это то, что правильно делать, начиная с сегодняшнего дня (с iOS 10), но также поддерживая старые устройства. ** UPDATE ** App Store говорит, что только 6% устройств, загружающих приложения, старше, чем ios 9, поэтому , если проще просто поддерживать 9 + 10, я просто сделаю это.

(Я попытался начать с примера iOS 10, но он сразу же врезался на эмулированное устройство iOS 9.3, хотя он отлично работает в iOS 10. Поэтому я пришел к выводу, что я должен начинать с информации о правильной настройке для разных Я мог бы опубликовать этот код, но я думаю, что это ведет к неправильному направлению. Я бы предпочел начать с того, что «должно» работать с несколькими версиями iOS, включая 10.)

Если я не нахожу какое-то решение, я начну комбинировать код из разных фрагментов кода stackoverflow ... но серьезно? Мне, должно быть, что-то не хватает, поскольку, по-видимому, у каждого разработчика iOS есть эта проблема.


Наоборот, я мог бы начать с более старого примера, а затем следить за изменениями, чтобы получить, чтобы работать с прошивкой 10 - но что в полной мере воспользоваться прошивкой 10?

ПРИМЕЧАНИЕ: Я программирую на Xamarin C#, но ответ Objective-C или Swift так же полезен.

+0

ToolmakerSteve, вы хотите локальное уведомление или удаленное устройство? если вы используете дистанционное управление, вы должны использовать реальное устройство для тестирования. – aircraft

+0

@aircraft Как локальный, так и удаленный. У моей компании есть приложение в магазине приложений, которое работает на устройствах iOS 10, но падает на устройствах iOS 9.3. Так что да, он был протестирован на реальных устройствах. [К сожалению, протестирован жесткий путь ...] Не знаю, был ли это локальный или удаленный сбой, к сожалению, я не писал этот код, я просто узнаю обо всем этом, поэтому я могу исправить приложение. – ToolmakerSteve

+0

@aircraft .. и просто узнал, что больше не возможно вернуться к версиям до iOS 10 без джейлбрейка моего iPhone. Не желая этого делать, чтобы как можно больше тестировать эмулятор, вы отправите версию TestFlight кому-то с 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 --------------------- 
    // ------------------------------------------------------- 
} 

Приведенный выше код инициализирует ваше приложение таким образом, что он может получать уведомления.

ВАЖНО: Вам также необходимо установить соответствующие разрешения для своего приложения; см. документы Apple или ссылки, упомянутые в вопросе.И вам нужен этот файл:

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> выше, должны содержать либо "развитие" или "производства". (Я не знаю, что значение нашего приложения все еще говорит о «развитии» здесь: я не изучил, что построено, чтобы увидеть, будет ли оно автоматически изменено на «производство» Xcode перед отправкой в ​​Apple. Согласно https://stackoverflow.com/a/40857877/199364, он делает это.)


Затем вам нужно код отправить [например, ваше приложение сообщает вашему серверу, чтобы уведомить устройства ваших друзей о том, что вы сейчас делаете] и получите локальное или удаленное уведомление. Этот код в нашем приложении сочетается с нашими конкретными действиями и категориями уведомлений; У меня нет времени для получения краткой версии для публикации здесь. Подробные сведения см. В документах Apple или ссылках, упомянутых в исходном вопросе.

Вот основные методы (Добавить в class AppDelegate выше), чтобы получить уведомления:

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 выше) ; некоторые из них могут быть специфическими для FCM:

ApplicationReceivedRemoteMessage 
ReceivedRemoteNotification 
WillPresentNotification 
PerformFetch (for background notifications) 
HandleAction 
Смежные вопросы