iOSプッシュモバイルメッセージの背後にあるテクノロジー

著者:allenzzhao、IEGオペレーターTencent開発エンジニア

私たちはほぼ毎日ニュースプッシュを使用していますが、iOSのニュースプッシュがどのように実装されているか知っていますか?この記事では、プッシュ許可の申請、ローカルおよびリモートのメッセージプッシュ、アプリによるプッシュメッセージの処理など、複数のステップからiOSでのメッセージプッシュのワークフローについて詳しく説明します。

1。概要

メッセージプッシュは、アプリがユーザーに情報を配信するための重要な方法です。アプリが実行されているかどうかに関係なく、ユーザーが通知権限を開いている限り、ユーザーはプッシュメッセージを受信できます。開発者は、iOSシステムメソッドを呼び出すことでローカルメッセージプッシュを開始できます。たとえば、最も一般的なアラームクロックアプリケーションであるアプリは、ローカルに保存されたアラームクロック情報に基づいてローカル通知を直接開始できるため、ネットワークがない場合でも、アラームリマインダーを受信できます。

リモートメッセージプッシュの場合、ビジネスサーバーはメッセージコンテンツを固定形式でApple Push Notitficationサービス(APN)に送信し、AppleのAPNサーバーを介してユーザーのデバイスにプッシュします。たとえば、Tencent Newsは、現在の状況や最新ニュースをユーザーにプッシュできます。 QQメールボックスは、ユーザーに新しいメールリマインダーを受信するようにプッシュできます。ゲームアプリは、この方法でプレーヤーに新しいゲームのメリットを通知できます。重要な情報を時間内にユーザーに通知するだけでなく、プッシュメッセージを介してユーザーにアプリを開くか起動するように促すこともできます。アプリの使用率。タイトル、コンテンツ、プロンプトサウンド、コーナー番号などの固定プッシュパラメータに加えて、開発者はプッシュメッセージにカスタムパラメータを追加することもできます。これにより、ユーザーはプッシュメッセージをクリックしたときに、関連するニュース、メール、または福祉のページに直接移動できるため、より良い情報が得られます。ユーザーエクスペリエンスとページの露出。


2.XCode構成

メッセージプッシュ関連機能を使用する前に、まずプッシュ機能をサポートする証明書を準備する必要があります。個々の開発者は、Tencent CloudのTPNSドキュメント参照して、Apple DeveloperCenterでプッシュ証明書を構成およびエクスポートできます。

さらに、XCodeのプロジェクト構成のSigning&Capabilities構成でメッセージプッシュ権限を増やす必要があります。操作が完了すると、Xcodeはプロジェクトのエンタイトルメントファイルを自動的に生成または更新し、図に示すようにAPS環境フィールドを追加します。

3.メッセージプッシュ許可を申請します

ローカルプッシュであろうとリモートプッシュであろうと、プッシュする前にまずユーザーにプッシュ許可を申請する必要があり、ユーザーが許可された後にのみプッシュメッセージを受信できます。

AppleはiOS10にUserNotificationsフレームワークを導入し、プッシュ関連機能をカプセル化およびアップグレードしました。UIApplicationが以前に実行できたいくつかの基本的なローカルおよびリモートメッセージプッシュ機能に加えて、プッシュメッセージとカスタム通知UIの撤回または変更も追加しました。 、プッシュメッセージフロントディスプレイおよびその他の機能。iOS10以降では、開発者がrequestAuthorizationWithOptions:completionHandler:メソッドを使用して、ユーザーからのメッセージプッシュ許可を申請することをお勧めします。このメソッドでは、アラート(メッセージのタイトル、テキストなど)を含むプッシュ許可を説明するUNAuthorizationOptionsタイプパラメーターを指定する必要があります。 )、サウンド(メッセージプロンプトトーン)、バッジ(アプリの右上隅に表示されるコーナーラベル);このメソッドのcompletionHandlerコールバックメソッドでgrantedパラメーターを使用して、ユーザーが承認を許可したかどうかを判断することもできます。関連するコードは次のとおりです。

#import <UserNotifications/UserNotifications.h>
……
[[UNUserNotificationCenter currentNotificationCenter]
requestAuthorizationWithOptions:UNAuthorizationOptionSound|UNAuthorizationOptionAlert|UNAuthorizationOptionBadge
completionHandler:^(BOOL granted, NSError * _Nullable error) {
    if(granted){
        //用户允许了推送权限申请
    }else{
        //用户拒绝了推送权限申请
    }
}];

iOS9では、UIApplicationのregisterUserNotificationSettingsメソッドを直接使用できます。このメソッドでは、サウンド、アラート、バッジなどのパラメーターも構成する必要がありますが、ユーザーが承認をクリックしたか拒否したかを判断するためのコールバックメソッドは提供されません。関連するコードは次のとおりです。

[[UIApplication sharedApplication] registerUserNotificationSettings:
 [UIUserNotificationSettings settingsForTypes:
  (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
                                   categories:nil]];

UserNotificationsまたはUIApplicationのプッシュ権限の申請方法にかかわらず、上記のユーザー承認を申請するためのシステムポップアップウィンドウは1回だけ表示されます。iOSはアプリのユーザーの承認ステータスを記録し、ユーザーからの承認を繰り返し申請することはありません。メッセージプッシュはアプリの重要な機能であり、優れた操作方法でもあるため、多くのアプリは起動後にメッセージプッシュの承認ステータスを確認します。ユーザーがメッセージプッシュの許可を拒否した場合でも、一定の頻度でユーザーに通知します。 、次に、iOS設定センターでアプリのプッシュ権限をオンにします。関連するコードは次のとおりです。

if(@available(iOS 10.0,*)){
    [[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
        if (UNAuthorizationStatusDenied == settings.authorizationStatus) {
            //用户拒绝消息推送,弹窗提示引导用户去系统设置中进行授权
            UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"未打开推送功能" message:@"请在设备的\"设置-App-通知\"选项中,允许通知" preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction* action){
                [alert dismissViewControllerAnimated: YES completion: nil];
            }];
            UIAlertAction* ok = [UIAlertAction actionWithTitle:@"去设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
                [alert dismissViewControllerAnimated: YES completion: nil];
                NSURL * url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                if([[UIApplication sharedApplication] canOpenURL:url])
                {
                    NSURL*url =[NSURL URLWithString:UIApplicationOpenSettingsURLString];
                    [[UIApplication sharedApplication] openURL:url];
                }
            }];
            [alert addAction: cancel];
            [alert addAction: ok];
            [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alert animated: YES completion: nil];
        }
    }];
}else{
    UIUserNotificationSettings *setting = [[UIApplication sharedApplication] currentUserNotificationSettings];
    if (UIUserNotificationTypeNone == setting.types) {
        //用户拒绝消息推送,处理方式同上
    }
}

4.ローカルプッシュ


iOS10では、UserNotificationsフレームワークは、メッセージプッシュのタイトル、コンテンツ、プロンプトサウンド、コーナーテーブル、およびその他のコンテンツを記述するUNMutableNotificationContentオブジェクトを提供し、UNNotificationTriggerオブジェクトは、メッセージプッシュのプッシュ時間戦略を記述し、UNNotificationRequestオブジェクトはプッシュコンテンツと時間を統合します。各Requestオブジェクトは、プッシュコンテンツを識別するためのIDで構成する必要があり、UNUserNotificationCenterは、このIDを介してすべての要求を管理(追加、削除、クエリ、および変更を含む)します。UNNotificationTriggerには、4つのサブカテゴリがあります。つまり、メッセージのプッシュスルー時間を制御するUNTimeIntervalNotificationTrigger、メッセージのプッシュスルー日付を制御するUNCalendarNotificationTrigger、地理的な場所を介したメッセージのプッシュを制御するUNLocationNotificationTrigger、およびUNPushNotificationTriggerリモートメッセージプッシュオブジェクトです。関連するコードは次のとおりです。

//推送内容
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = @"推送标题";
content.body = @"推送内容";
content.sound = [UNNotificationSound defaultSound];//默认提示音
//日期推送,今日15:53:00推送本地消息
NSDateComponents* date = [[NSDateComponents alloc] init];
date.hour = 15;
date.minute = 53;
UNCalendarNotificationTrigger* calendarTrigger = [UNCalendarNotificationTrigger
       triggerWithDateMatchingComponents:date repeats:NO];
//倒计时推送,2s后推送本地消息
UNTimeIntervalNotificationTrigger *intervalTrigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:2 repeats:NO];
UNNotificationRequest* request = [UNNotificationRequest
       requestWithIdentifier:@"testId" content:content trigger:calendarTrigger];
//将推送请求添加到管理中心才会生效
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
   if (error != nil) {
       NSLog(@"%@", error.localizedDescription);
   }
}];

iOS9では、UIApplicationは2つのローカルメッセージプッシュメソッドpresentLocalNotificationNowとscheduleLocalNotificationを提供します。これらはそれぞれ、固定日付による即時プッシュとプッシュを表します。UILocalNotificationは、メッセージの内容とプッシュのタイミングも記述します。サンプルコードは、2秒後にプッシュされるローカルメッセージです。soundName属性は、メッセージのプロンプトトーンを説明するために使用されます。ユーザーは、プロンプトトーンをカスタマイズするか(オーディオファイルをインストールパッケージにパックする必要があります)、デフォルトのプロンプトミュージックを使用できます。repeatInterval属性とrepeatCalendar属性は別々に使用されます。時差と日付に応じて、プロンプト操作を繰り返します。関連するコードは次のとおりです。

UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:2];
notification.alertTitle = @"推送标题";
notification.alertBody = @"推送内容";
//notification.soundName = UILocalNotificationDefaultSoundName;
notification.soundName = @"mysound.wav";
[[UIApplication sharedApplication] scheduleLocalNotification:notification];

5.リモートプッシュ

ネットワーク要求に依存しないローカルメッセージプッシュとは異なり、iOSシステムメソッドを直接呼び出すことができます。リモートメッセージプッシュの実装には、ユーザー機器、独自のビジネスサーバー、およびAppleのAPNサービスの相互作用が含まれます。Androidシステムでのリモートメッセージプッシュの実装とは異なり、アプリ自体はバックグラウンドサービスを介してビジネスサーバーとのロングリンク通信を維持する必要があります。iOSでのメッセージプッシュは、オペレーティングシステムとAppleのAPNサーバー間の直接の相互作用によって実現され、アプリ自体はビジネスサーバーを維持して通信する必要はありません。サーバー接続。ユーザーがプッシュ許可を有効にしている限り、当社のビジネスサーバーはAPNsサービスを呼び出すことでいつでもユーザーに通知をプッシュできます。これにより、開発者とユーザーに安全で安定したプッシュサービスを提供し、システムリソースの消費を節約し、システムの流暢さを向上させることができます。バッテリー寿命。

iOSクライアントでのリモートメッセージプッシュの実装は、次のプロセスに分けることができます。

  1. ユーザーのiphoneは、iOSシステムメソッド呼び出しを介してAppleのAPNsサーバーと通信し、デバイスのdeviceTokenを取得します。これは、APNsサービスによって割り当てられ、さまざまなデバイス上のさまざまなアプリを一意に識別します。これは、deviceID、bundleId、およびインストール時間と見なすことができます。関連情報が生成され、アプリのアップグレード操作のdeviceTokenは変更されません。アプリをアンインストールして再インストールし、オペレーティングシステムを復元して再インストールすると、deviceTokenが変更されます。

  2. AppleのAPNsサービスはdeviceTokenに基づいて実装されているため、デバイスのdeviceTokenは、後続のメッセージプッシュのためにビジネスサーバーに送信する必要があります。デバイスが複数のユーザーにログインしている可能性があり、ユーザーが複数のデバイスにログインしている可能性があります。deviceTokenに加えて、異なるメッセージを異なるユーザーにプッシュする必要がある場合は、ユーザーのopenidとdeviceTokenの間のマッピング関係も保存する必要があります。 。ユーザーが正常にログインした後、openidとdeviceTokenの間のマッピング関係を更新できます。ユーザーがログアウトした後、マッピング関係をキャンセルし、ユーザーの最後にログインしたデバイスのdeviceTokenのみを保存して、1つのデバイスが複数の繰り返し通知を受信し、1人のユーザーが異なるデバイスでそれを受信することを回避します。複数の通知など。

  3. 事実に基づくホットニュースがニュースアプリに表示されると、バックグラウンドサービスは、メッセージコンテンツやdeviceTokenなどのコンテンツを伝送し、AppleのAPNsサービスへのメッセージプッシュリクエストを開始できます。プッシュメッセージは、リクエスト形式とdeviceTokenチェックがAPNsサービスに合格する限り、非同期で実装されます。エラーは報告されませんが、ネットワークの異常または閉じられたプッシュ権限が原因で、ユーザーがプッシュメッセージを受信しない場合があります。

  4. ユーザーのデバイスへのAPNサービスのプッシュメッセージも非同期です。ユーザーがシャットダウンするか、ネットワークがプッシュの受信に失敗すると、APNは各deviceTokenの最後のプッシュメッセージを予約し、ネットワークが復元された後に再度プッシュします。

5.1、デバイスdeviceTokenを取得します

アプリの起動時に、UIApplicationのregisterForRemoteNotificationsメソッドを介してAppleのAPNSサーバーからdeviceTokenをリクエストできます。リクエストが成功すると、didRegisterForRemoteNotificationsWithDeviceTokenコールバックメソッドが実行されます。ビジネスサーバーの呼び出しを容易にするために、通常、バイナリdeviceTokenを16進数に変換します。リクエストが失敗した場合、didFailToRegisterForRemoteNotificationsWithErrorメソッドも特定のエラー情報とともに呼び出されます。関連するコードは次のとおりです。

//调用系统方法请求deviceToken
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[UIApplication sharedApplication] registerForRemoteNotifications];
}
//deviceToken获取成功的回调
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    NSString *deviceTokenStr;
    NSUInteger length = deviceToken.length;
    if (![deviceToken isKindOfClass:[NSData class]] || length == 0) {
        return;
    }
    const unsigned char *bytes = (const unsigned char *)deviceToken.bytes;
    NSMutableString *hex = [NSMutableString new];
    for (NSInteger i = 0; i < deviceToken.length; i++) {
        [hex appendFormat:@"%02x", bytes[i]];
    }
    deviceTokenStr = [hex copy];
    NSLog(@"%@", deviceTokenStr);
}
//deviceToken获取失败的回调
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    NSLog(@"error,%@",error);
}

5.2、バックグラウンドコールAPNプッシュ

ビジネス側のサーバーがAPNサービスを呼び出すときは、最初に安全な接続を確立して開発者のIDを認証する必要があります。これは、証明書ベースとトークンベースの2つの方法に分けられます。より一般的に使用されるのは、証明書ベースです。検証方法。プッシュ証明書は、さまざまなAPNプッシュインターフェイスに対応する開発環境証明書と本番環境証明書に分けられます。Appleの開発者プラットフォームまたはサードパーティプラットフォームからエクスポートするプッシュ証明書には、インターフェイスが私たちを呼び出すのを容易にするために、通常、p12とpemの2つの形式があります。次のコマンドを使用して、p12形式のファイルをpem証明書に変換できます。

openssl pkcs12 -in push_dev.p12 -out push_dev.pem -nodes

証明書に基づいてTLS接続を確立するプロセスを次の図に示します。

  1. プロバイダーサーバー(プロバイダー)は、APNサーバーへのTLS接続を確立するための要求を開始します。

  2. APNsサーバーから返される証明書は、ビジネス側サーバーによる検証用です。

  3. ビジネス側サーバーは、APNサーバーによる検証用に独自のプッシュ証明書を提供します。

  4. APNsサーバーが、ビジネス側サーバーによって提供されたプッシュ証明書が正しいことを確認した後、TLS接続が確立され、ビジネス側サーバーはメッセージプッシュ要求をAPNに直接送信できます。

ビジネスパーティとAPNの確立要求を簡単に実装するためのPHPコードは次のとおりです。

$deviceToken= '22124c450762170ca2ddb32a50381dd2c3026dbdb020f6dddcabefdca724fdd6';
//dev params
$devUrl = 'ssl://gateway.sandbox.push.apple.com:2195';
$devCertificate = 'push_dev.pem';
//product params
$proUrl = 'ssl://gateway.push.apple.com:2195';
$proCertificate = 'push_pro.pem';
// Change 2 : If any
$title = '标题';//消息标题
$content = '消息内容';//内容
$ctx = stream_context_create();
// Change 3 : APNS Cert File name and location.
stream_context_set_option($ctx, 'ssl', 'local_cert', $devCertificate);
// Open a connection to the APNS server
$fp = stream_socket_client($devUrl, $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
    exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
    'alert' =>array(
        'title'=>$title,
        'body'=>$content
    ),
    'sound' => 'default'
    );
//自定义内容
$body['userInfo'] = array(
    'url' => 'https://www.qq.com',
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
//发送多个就调用多次fwrite
//$result = fwrite($fp, $msg, strlen($msg));
echo $msg;
if (!$result)
    echo 'Message not delivered' . PHP_EOL;
else
    echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);

ビジネス側サーバーは、証明書を介してAPNとの安全な接続を確立した後、複数の連続したメッセージプッシュ操作を実行できます。各メッセージプッシュでは、deviceTokenパラメーターとPayloadパラメーターを指定する必要があります。Payloadは、リモートメッセージプッシュを受信したときにiOSの表示形式を構成するために使用されるjsonオブジェクトです。apsパラメーターには、Appleのプリセットアラート、サウンド、バッジ、およびその他のパラメーターが含まれます。アラートパラメーターには、文字列またはタイトルと本文を含めることができます。他のパラメータを持つ辞書のタイプ。バッジパラメータはプラスチックを使用してアプリアイコンの右上隅に表示される番号を設定し、バッジが0に設定されている場合はコーナーマークは表示されません。サウンドパラメータはプッシュサウンドを設定するために使用されます。このパラメータが渡されないか空の文字列が渡されると、プッシュされます。プロンプト音は鳴りません。デフォルトに設定すると、システムのデフォルトのプロンプト音が使用されます。特定のオーディオファイル名に設定することもできます。オーディオファイルは、事前にプロジェクトのバンドルディレクトリに配置する必要があり、期間は30秒を超えることはできません。

プリセットパラメータに加えて、apsの同じレベルでいくつかのパラメータをカスタマイズすることもできます。これらのパラメータは辞書タイプにすることもでき、サンプルコードのカスタムuserInfoオブジェクトなどの他のパラメータをネストできますが、一般的なプッシュメッセージのペイロードです。大きすぎないようにし、4K以内で制御する必要があります。idやurlなどの一部の重要なパラメータのみを透過的に送信することをお勧めします。特定のコンテンツは、プッシュを受信したときにクライアントからのネットワーク要求を通じて取得されます。

{
    "aps" : {
        "alert" : {
            "title" : "Game Request",
            "subtitle" : "Five Card Draw",
            "body" : "Bob wants to play poker",
        },
        "badge" : 9,
        "sound" : "gameMusic.wav",
    },
    "gameID" : "12345678"
}

上記のペイロードには、タイトル、サブタイトル、コンテンツ、メッセージプロンプトサウンド、一般的なプッシュメッセージのアプリコーナー番号、開発者がカスタマイズしたgameIDパラメーターなどのプリセットパラメーターが含まれています。ユーザーがプッシュメッセージをクリックすると、アプリが自動的に起動するか、バックグラウンドからウェイクアップします。システムのコールバックメソッドでカスタムパラメータを取得し、gameIDに従ってユーザーのゲームページを自動的に開くことができます。

5.3、メッセージプッシュデバッグツール

APNインターフェースをデバッグする場合、いくつかの優れたプッシュデバッグツールを使用して、ペイロードまたは証明書の正当性を検証できます。この記事では、2つの人気のあるオープンソースソフトウェア、つまり、国内の開発者によって保守されている外国のKnuffとsmartPushを紹介します。

  • ナフ:https://github.com/KnuffApp/Knuff

  • SmartPush:https://github.com/shaojiankui/SmartPush

6.アプリプッシュメッセージ処理

iOS10では、UserNotificationsフレームワークが開発者にUNUserNotificationCenterDelegateプロトコルを提供します。開発者は、アプリがプッシュメッセージを受信し、ユーザーがプッシュメッセージをクリックしたときに、プロトコルにメソッドを実装してビジネスロジックを処理できます。ローカルプッシュメッセージであろうとリモートプッシュメッセージであろうと、アプリの実行ステータスは次の3つの状態になります。

  1. アプリはフォアグラウンドで実行されています。この時点で、ユーザーはアプリを使用しています。プッシュメッセージを受信すると、メッセージプロンプトボックスはデフォルトではポップアップしません。willPresentNotificationコールバックメソッドが呼び出されます。開発者は、UNNotificationオブジェクトからプッシュメッセージのペイロードコンテンツを取得し、から取得できます。パラメータを定義してから、カスタムポップアップウィンドウを表示して、ユーザーが新しいメッセージを受信したことをユーザーに通知します。willPresentNotificationメソッドのcompletionHandler関数を使用して、プッシュメッセージをフォアグラウンドに直接表示することもできます。ユーザーがフォアグラウンドに表示されたプッシュメッセージをクリックすると、didReceiveNotificationResponseコールバックメソッドも表示されます。実行されます。

  2. アプリはバックグラウンドで実行されます。このとき、ユーザーはプッシュメッセージをクリックしてアプリをバックグラウンドから復帰させ、didReceiveNotificationResponseコールバックメソッドが実行されます。開発者はこのメソッドでペイロードを取得し、カスタムパラメータを解析して、対応するページを自動的に開くことができます。

  3. アプリは起動されていません。この時点で、ユーザーはプッシュメッセージをクリックしてアプリを開きます。開発者は、launchOptionsからローカルまたはリモートのプッシュメッセージのカスタムパラメータを取得し、ページの初期化後に関連するページにジャンプできます。

#import <UserNotifications/UserNotifications.h>
@interface AppDelegate ()<UNUserNotificationCenterDelegate>
@end

@implementation AppDelegate
//在App启动后就将AppDelegate对象配置为NotificationCenter的delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [UNUserNotificationCenter currentNotificationCenter].delegate = self;
    // NSDictionary *localNotification = [launchOptions valueForKey:UIApplicationLaunchOptionsLocalNotificationKey];
    NSDictionary *remoteNotification = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    if(remoteNotification){
        //app已退出,点击拉起了app
        NSDictionary *params = userInfo[@"userInfo"];
        //此时NavigationController还未初始化,可以先暂存参数,稍后跳转
        [PageSwitch handlePushSwitch:params];
    }
}
//用户点击推送消息的回调
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler API_AVAILABLE(ios(10.0)){
    UNNotification *noti = ((UNNotificationResponse *)response).notification;
    NSDictionary *userInfo = noti.request.content.userInfo;
    NSDictionary *params = userInfo[@"userInfo"];
    //根据消息推送中的参数,在用户点击推送时自动进行跳转
    [PageSwitch handlePushSwitch:params];
}
//App在前台运行时收到推送消息的回调
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(nonnull UNNotification *)notification withCompletionHandler:(nonnull void (^)(UNNotificationPresentationOptions))completionHandler API_AVAILABLE(ios(10.0)){
    //可以让App在前台运行时也能收到推送消息
    completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionAlert);
}

iOS9では、UIApplicationは、リモートメッセージプッシュ、リモートサイレントプッシュ、およびローカルメッセージプッシュのコールバック処理メソッドである、次の3つのメッセージプッシュ処理メソッドを提供します。最初の2つのコールバックメソッドは、アプリのリモートメッセージプッシュを処理するために使用できます。同時に使用すると、リモートサイレントプッシュメソッドのみが呼び出されます。ペイロードにパラメータcontent-available = 1が含まれている場合、プッシュはサイレントプッシュであり、サイレントプッシュは表示されません。プッシュメッセージの場合、アプリがバックグラウンドで一時停止されると、サイレントプッシュコールバックメソッドが実行されます。開発者は、コールバックメソッドでビジネスロジックを処理し、処理の完了後にfetchCompletionHandlerを呼び出すために30秒かかります。

//远程消息推送回调方法,ios(3.0, 10.0)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;
//远程静默推送回调方法,ios(7.0, *)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 
    fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler API_AVAILABLE(ios(7.0));
//本地消息推送回调方法,ios(4.0, 10.0)
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;

UIApplicationの3つの方法は次のとおりです。①アプリがフォアグラウンドで実行されている場合、通知を受信します。②アプリがバックグラウンドで実行されている場合、ユーザーはプッシュメッセージをクリックしてアプリをプルアップします。両方のシナリオが呼び出されます。違いは、最初の2つの方法がリモートメッセージプッシュに対応することです。受信してクリックしたトリガー応答であるdidReceiveLocalNotificationは、ローカルメッセージのプッシュに使用されます。UIApplicationのapplicationStateプロパティを使用して、アプリがフォアグラウンドで実行されているかどうかを判断し、それらを個別に実装できます。①ユーザーがメッセージをクリックしてバックグラウンドアプリを起動し、対応するページを開きます。②ユーザーがフォアグラウンドでアプリを使用すると、カスタムポップアップウィンドウが表示されます。

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
    if([UIApplication sharedApplication].applicationState == UIApplicationStateActive){
        NSLog(@"在前台,%@",userInfo);
    }else{
        NSLog(@"从后台进入前台,%@",userInfo);
        NSDictionary *params = userInfo[@"userInfo"];
        if([Tools isValidString:params[@"url"]]){
            NSString *routeUrl = params[@"url"];
            [PageSwitch handlePushSwitch:params];
        }
    }
}

7.まとめ

この記事では、最初にメッセージプッシュとプッシュ許可の適用に関連するプロジェクト構成を紹介し、次にローカルメッセージプッシュとリモートメッセージプッシュのそれぞれのさまざまな使用シナリオと実装方法を紹介し、最後にプッシュメッセージを受信した後のアプリの関連するコールバックメソッドと処理ロジックを紹介します。実際のプロジェクト開発では、Tencent CloudPushやJiguangPushなどのより成熟したサードパーティのメッセージングプラットフォームを選択することがよくあります。これらのプラットフォームは、比較的完全なプッシュおよびデータ統計サービスを提供し、インターフェイスとSDKを介して基盤となるロジックを保護します。 iOSメッセージプッシュの実装プロセスを理解することで、これらのプラットフォームをより有効に活用できるようになります。

時間の都合上、私自身の調査は詳細ではありません。抜けや誤りがある場合は、メッセージを残して訂正してください〜

8.拡張読書

  1. Appleの公式技術文書、https://developer.apple.com/documentation/usernotifications

  2. 歴史上最も包括的なiOSプッシュテクノロジー、https://cloud.tencent.com/developer/article/1198303

  3. iOSリモートプッシュ-APNの詳細な説明、https://juejin.im/post/6844903893592178696

  4. iOSサイレントプッシュの高度な知識、https://www.jianshu.com/p/c211bd295d58

  5. iOS10カスタム通知UI、https://www.jianshu.com/p/85ac47bdf387

  6. Carrier Pigeonドキュメント-プッシュサービスの概要、https://xg.qq.com/docs/ios_access/ios_push_introduction.html

  7. iOSとAndroidのバックグラウンドリアルタイムメッセージプッシュの原理と違いについては、https://cloud.tencent.com/developer/article/1150967をご覧ください。

  8. HTTP2に基づくAPNへのメッセージのプッシュについて話します。http://www.linkedkeeper.com/167.html

  9. PHPソケットベースのiosプッシュ実装、https://www.fzb.me/2015-9-7-sockect-implement-for-apns.html

  10. 可用性の高いモバイルメッセージングプラットフォームを構築するにはどうすればよいですか?、Https://www.infoq.cn/article/HA-mobile-message-push-platform

おすすめ

転載: blog.csdn.net/Tencent_TEG/article/details/109302050