簡體   English   中英

UIBackgroundRefreshStatusDenied 未發送靜默推送通知,但應用程序在前台

[英]Silent push notification not delivered with UIBackgroundRefreshStatusDenied but app in foreground

使用UIBackgroundRefreshStatusAvailable ,我的應用程序按預期接收靜默推送通知,無論是在后台還是在前台。

此功能的名稱——后台應用程序刷新——向我表明它在禁用時不會影響前台應用程序的行為。

不幸的是,我的應用程序在前台時沒有收到靜默推送通知,后台應用程序刷新被禁用,即UIBackgroundRefreshStatusDenied

我沒有使用用戶可見的推送通知,因此不涉及UNUserNotificationCenter等。

是否可以在禁用后台應用刷新的情況下接收靜默推送通知,即UIBackgroundRefreshStatusDenied

Objective-C,Xcode 11.3.1,部署目標 iOS 10.3。 安裝了 iOS 12.4.5 的 iPhone 6。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [application registerForRemoteNotifications];
    return YES;
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    // not called when app in foreground but bg app refresh turned off
}

這是啟用 bg 應用刷新時收到的didReceiveRemoteNotification的示例userInfo dict:

{
aps =     {
    "content-available" = 1;
};
ck =     {
    ce = 2;
    cid = "iCloud.de.udo-thiel.DiskBench";
    ckuserid = "_56bd97c2eb1e52d09756163efaab6b02";
    nid = "e70e4a8d-d77b-4315-8b3e-d9de229cf083";
    qry =         {
        dbs = 2;
        fo = 2;
        rid = "Res-iPad 2-16";
        sid = "public-results2";
        zid = "_defaultZone";
        zoid = "_defaultOwner";
    };
};

}

這是一個有趣的問題,因為它基本上解決了命名這個相當復雜的功能的問題。

總之,恐怕答案是否定的。 雖然我自己不必處理這個問題,但我在同一個 position 中目睹了許多其他人。

對我來說,將整個“靜默遠程通知功能”視為與應用程序處於前台或后台的關系較小,而與“遠程應用程序輸入”的關系更大:

如果它被激活,即你有UIBackgroundRefreshStatusAvailable ,你的服務器可以靜默地發送它,在這種情況下,消息會做出反應。 基本上,服務器以與用戶點擊類似的方式提供輸入(盡管顯然是通過不同的調用函數)。 無論應用程序是在前台還是后台,都會發生這種輸入。

如果該功能處於非活動狀態,即您有UIBackgroundRefreshStatusDeniedUIBackgroundRefreshStatusRestricted ,則整個功能都已關閉 這意味着這種接收輸入的方式不起作用, application:didReceiveRemoteNotification:fetchCompletionHandler:根本沒有被調用。 誠然,這個方法名稱比 state 枚舉案例更好地反映了這個問題。


兩種解決方法

  1. 最明顯的一個:在applicationDidBecomeActive:applicationWillResignActive:中注冊和注銷遠程通知。 不幸的是,這可能會變得很難看,因為它會導致您的服務器為用戶不斷更改令牌,但是如果您想不惜一切代價避免在后台收到通知,請使用 go 這種方式。
  2. 注冊一次通知,確實讓您的邏輯處理前台后台的通知,就像您(似乎)已經做的那樣,但只需讓它在后台時忽略通知(使用UIApplication.shared.applicationState )。 從技術上講,這會“浪費”一些運行時間,因為您的應用程序可能會被喚醒,然后不會做任何有意義的事情,但我認為這還不錯。

我自己會選擇 go 和選項 2,因為我很少看到在后台收到無聲通知會很痛苦的情況。

一般來說,我不會做任何依賴於啟用通知(后台或前台)的事情。 換句話說:是的,如果我的應用程序在前台並且我需要對服務器上發生的事情做出反應,恐怕我需要“檢查”所述服務器,即以某種形式從中提取。

或者我會根據情況通知用戶他們應該啟用它,否則應用程序將沒有多大意義......嗯......


作為旁注:是的,Apple SDK 有點混淆命名和解釋所有不同的背景事物和通知。 甚至應用程序 state 本身(活動、非活動、背景、前景、暫停......)也比名稱看起來更復雜。 我認為其原因本質上是歷史性的。 在我們完全沒有后台模式和通知之前,人們只是輪詢數據以獲得“無聲前台通知”之類的東西,基本上就是你想要的東西。 所以最終他們希望在應用程序不在前台時也能做到這一點,大聲要求后台執行。 Apple 並不想無限制地授予這一點,所以通知概念發展緩慢,但由於它有點相關,“背景”一詞潛入其中(此外,我們也有背景獲取......),甚至如果它不一定有意義。 人們也可能會爭辯說它仍然是有效的,因為它對於應用程序處於后台/暫停時更為重要。 在前台獲得靜默通知”的用例仍然可以通過簡單的輪詢來涵蓋(盡管我同意這很丑陋),並且如果您使用推送,也可以在后台獲取這些通知。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM