APNS和Background Fetch相关问题总结

2 篇文章 0 订阅
2 篇文章 0 订阅

1.1 Normal Push Notification

1.1.1 概述

app获取deviceToken, 上报自己的服务端, 服务端维持一份用户ID->deviceToken的映射;用户退出登录时需要调用解绑接口,否则会出现当前用户收到发给其它用户的信息.
在这里插入图片描述
如何把消息推送到用户手机上:
在这里插入图片描述

1.1.2 deviceToken相关

  • iOS7之前,在iOS7之前单一环境下(Develop/Distribution)每一个设备一个DeviceToken;
  • iOS7+,单一环境下(Develop/Distribution),一个bundleId对应一个DeviceToken,app卸载后再重装deviceToken会发生改变;

1.1.3 推送feedback接口

APNS的feedback service会返回那些已经卸载的设备的deviceToken。对于这些token,下次就不用再发了。可以节省点资源。需要注意的是:feedback的接口读取一次,APNS就会清空它的列表,下次再读取时,返回的就是这两次读取之间这段时间新产生的deviceToken.

1.1.4 badge点击不消失的问题

如果推送到 APNs 时,Badge number 被指定为0 ,则可能出现 push消息在通知中心被点击后,尽管调用了 [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; 但 APNs 消息在通知中心不会被删除的情况。 这种情况可以按如下代码调用以清除通知中心的 push通知。

[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 1 ];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 0];

1.1.5 定制push notification的推送时间段

如果用户即想接收通知又不想接收其它不关注的通知, 可以对消息进行分类让用户进行定制.用户也可以设置接收通知的时间段,来避免被骚扰.

1.1.6 push notification的功能扩展

  • 可以对一些实时性较强消息推送过来之后,运用today扩展进行展示,比如一些热销或促销商品;
  • app未启动或者处于后台时收到推送进行相关资源下载,待app启动/回到前台时展示更新后的界面(详看silent push notification);
  • 可结合Apple Watch做相应的展示,一些物流消息的展示如果与Apple Watch配对的iphone处于黑屏状态下,则可在Watch上进行展示;

1.1.7 收不到push notification的情况总结

  • appID是否把push开关打开了;
  • 系统设置里面是否把相应app的通知开关关闭了;
  • appID是否是带"*"的;
  • 前后端证书appID和后端推送证书appID是否是同一个;
  • 前端环境和后端环境是否相同(同为developer或同为distribution);
  • 后端推送证书是否过期(有效期一般为一年);
  • 如果是拿不到deviceToken,并且IOS系统设置中通知开关部分打开,这时手动切换一下其它开关的状态,使其可接受到deviceToken(苹果的bug,一般是由于用户打开部分推送开关的情况下,把整个接受推送的开关关闭掉,然后卸载再重装app所致);
  • app在系统设置通知里关闭接受消息通知,这时如果再重新安装app,开关状态依旧关闭(ios8以上一个系统版本有这个问题);
  • 看看手机是否设置了代理,测试人员经常设置代理进行测试;
  • 后端推送数据包过大,IOS8之前推送支持256个字节,IOS8之后支持2K,这时候需要上报deviceToken时,把系统版本号也上报上去,便于推送时根据不同版本号进行不同长度的数据推送。
    在这里插入图片描述

1.1.8 测试工具

  • php推送脚本;
  • PushMeBaby;
  • SmartPush;

1.2 Silent Push Notification

1.2.1 概述

If your app’s server-based content changes infrequently, or at irregular intervals, you can use silent notifications to notify your app when new content is available. A silent notification is a remote notification that doesn't display an alert, play a sound, or badge your app’s icon. It wakes your app in the background and gives it time to initiate downloads from your server and update its content.
Important

The system treats silent notifications as low-priority. You can use them to refresh your app’s content, but the system doesn't guarantee their delivery. In addition, the delivery of silent notifications may be throttled if the total number becomes excessive. The actual number of silent notifications allowed by the system depends on current conditions, but don't try to send more than two or three silent notifications per hour.

1.2.2 开启Silent Remote Notifications

在这里插入图片描述

1.2.3 Silent Notification Payload格式

{
   "aps" : {
      "content-available" : 1
   },
   "acme1" : "bar",
   "acme2" : 42
}

必须不能携带 alert、badge、sound,不然就不是静默推送了。

When an iOS device receives a silent notification, the system wakes your app in the background and calls the application:didReceiveRemoteNotification:fetchCompletionHandler: method of its app delegate. Your app has `30` seconds of wall-clock time to perform any tasks and call the provided completion handler. For more information, see Handling Notifications and Notification-Related Actions.

1.2.3 版本限制

  • iOS7+

1.2.4 payload大小限制

A basic remote notification payload includes Apple-defined keys and their custom values. You may also add custom keys and values specific to your notifications. Apple Push Notification service (APNs) refuses a notification if the total size of its payload exceeds the following limits:
For Voice over Internet Protocol (VoIP) notifications, the maximum payload size is 5 KB (5120 bytes).
For all other remote notifications, the maximum payload size is 4 KB (4096 bytes).

1.2.5 静默推送测试

版本app未启动app处于后台(包括挂起)app处于前台
8.3收不到能收到能收到
9.3.5收不到能收到能收到
10.3.3收不到能收到能收到
11.4.1XCode连调强杀能收到, 直接强杀收不到能收到能收到
12.1XCode连调强杀能收到, 直接强杀收不到能收到能收到

2.Background Fetch

2.1 概述

Background App Refresh lets your app run periodically in the background so that it can update its content. Apps that update their content frequently, such as news apps or social media apps, can use this feature to ensure that their content is always up to date. Downloading data in the background before it is needed minimizes the lag time in displaying that data when the user launches the app.

2.2 如何使用

To support Background App Refresh for your app, do the following:

  1.Enable the background fetch capability in your app ().

  2.Call the setMinimumBackgroundFetchInterval: method of UIApplication at launch time.

  3.Implement the application:performFetchWithCompletionHandler: method in your app delegate.
 

在这里插入图片描述

When the system calls your app delegate’s application:performFetchWithCompletionHandler: method, configure a NSURLSession object to download any new data.The system waits until network and power conditions are good, so you should be able to retrieve adequate amounts of data quickly. When you finish updating your app, call the completion handler and provide an accurate result of your outcome, which can include saying that no new data was available.

Important

Calling the completion handler in a timely manner, and with an accurate result, helps determine how much future execution time your app receives. If you take too long to update your app, the system may schedule your app less frequently in the future to save power.

2.3 后台执行顺序

应用程序可以从几个不同的触发点进入后台.系统事件可以让一个挂起的app进入后台或者让一个没有运行的app直接启动进入后台.当另一个app启动或者用户返回到主屏幕时可以让一个处于前台的app进入后台模式.

后台执行顺序图如下:

在这里插入图片描述
当一个后台事件到达app没有处于运行状态时,系统会按照如下顺序把app启动并直接移入后台:

  1. The system launches the app and follows the initialization sequence described in About the App Launch Sequence.

  2. UIKit calls the app delegate's applicationDidEnterBackground: method.

  3. UIKit delivers the event that caused the launch.

  4. The app's snapshot is taken.

  5. The app may be suspended again.

当app处于挂起状态时,当一个后台事件到达时,遵循如下顺序:

  1. The system resumes the app.

  2. UIKit calls the app delegate's applicationDidEnterBackground: method.

  3. UIKit delivers the event that caused the launch.

  4. The app's snapshot is taken.

  5. The app may be suspended again.

当另一个app启动或者用户返回到主屏幕,处于前台的app会进入后台模式,遵循如下顺序:

  1. The user exits the running app.

  2. UIKit calls the app delegate's applicationWillResignActive: method.

  3. UIKit calls the app delegate's applicationDidEnterBackground: method.

  4. The app's snapshot is taken.

  5. The app may be suspended again.

2.4 延长app后台执行时间

延长你的app后台执行时间可以保证你有足够的时间来执行重要任务.当app进入后台模式时,系统调用app的代理的applicationDidEnterBackground:方法.该方法有5s的时间来执行任务并返回.该方法返回之后,系统马上会把app置于挂起状态.对于大部分app来说5s足够来处理任何重要的任务,但是如果你需要更多时间,可以请求UIKit来延长你的app的运行时间.

通过调用beginBackgroundTaskWithName:expirationHandler:来延长你的app运行时间.通过调用该方法可以给你额外的时间来处理重要任务(通过backgroundTimeRemaining属性来查看还剩多少时间).一旦你的任务完成了,立刻调用endBackgroundTask:来通知系统你已经处理完成.如果你不及时结束任务,系统会终止app的运行.

func sendDataToServer( data : NSData ) {
   // Perform the task on a background queue.
   DispatchQueue.global().async {
      // Request the task assertion and save the ID.
      self.backgroundTaskID = UIApplication.shared.
                 beginBackgroundTask (withName: "Finish Network Tasks") {
         // End the task if time expires.
         UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
         self.backgroundTaskID = UIBackgroundTaskInvalid
      }
            
      // Send the data synchronously.
      self.sendAppDataToServer( data: data)
            
      // End the task assertion.
      UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
      self.backgroundTaskID = UIBackgroundTaskInvalid
   }
}
Note

The beginBackgroundTaskWithName:expirationHandler: method cannot be called from an app extension. To request extra execution time from your app extension, call the performExpiringActivityWithReason:usingBlock: method of NSProcessInfo instead.

2.5 如何模拟Background Fetch

  • XCode运行程序后, 在Debug->Simulate Background Fetch.(模拟app在前台和后台时)
  • Product->Scheme->Edit scheme 在Debug模式选中Options,点选Launch due to a background fetch event.(模拟App没有启动的情况)

2.6 其它

  • 设置->通用->后台应用程序刷新 中显示了打开后台应用刷新的应用.在代码中我们可以通过[UIApplication sharedApplication].backgroundRefreshStatus == UIBackgroundRefreshStatusAvailable来进行相应的判断;
A restricted user, such as one who is managed under parental controls, can't enable Background App Refresh.

Background App Refresh is disabled automatically when a device is operating in low-power mode. When this happens, the time available for performing background tasks is reduced to save power.

  • 版本要求: iOS 7.0+, tvOS 11.0+;

  • 后台操作时的时间要求30s,如果不及时调用completionHandler,app将会被杀死.后台操作耗时越长,app被调用的频率将会降低;
    - (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;

    When this method is called, your app has up to 30 seconds of wall-clock time to perform the download operation and call the specified completion handler block. In practice, your app should call the completion handler block as soon as possible after downloading the needed data. If you do not call the completion handler in time, your app is terminated. More importantly, the system uses the elapsed time to calculate power usage and data costs for your app’s background downloads. If your app takes a long time to call the completion handler, it may be given fewer future opportunities to fetch data in the future. For more information about supporting background fetch operations, see Background Execution in App Programming Guide for iOS.
    
  • application: performFetchWithCompletionHandler;调用频次:

    1. [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum]; 时间间隔可以自定义.

    2. 和网络和电量状态有关;

    3. 后台操作耗时越长,调用频率会降低;

参考链接:
1.https://developer.apple.com/documentation/uikit/core_app/managing_your_app_s_life_cycle/preparing_your_app_to_run_in_the_background/extending_your_app_s_background_execution_time?language=objc

2.https://developer.apple.com/documentation/uikit/core_app/managing_your_app_s_life_cycle/preparing_your_app_to_run_in_the_background/about_the_background_execution_sequence?language=objc

3.https://developer.apple.com/documentation/uikit/core_app/managing_your_app_s_life_cycle/responding_to_the_launch_of_your_app/about_the_app_launch_sequence?language=objc

4.https://developer.apple.com/documentation/uikit/core_app/managing_your_app_s_life_cycle/preparing_your_app_to_run_in_the_background/updating_your_app_with_background_app_refresh

5.https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623125-application?changes=latest_minor&language=objc

6.https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification

7.https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_updates_to_your_app_silently

8.https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1

9.https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值