ios 实施 PushKit 并测试开发行为

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27245808/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:51:53  来源:igfitidea点击:

Implement PushKit and test in development behavior

iosios8apple-push-notificationsios-frameworks

提问by pasqui86

i'd like to implement PushKit service within my app ( Voip app ), but i have following doubt: I see that i can generate only production voip certificate , it works if i try to test voip push notification service on develop device ?

我想在我的应用程序(Voip 应用程序)中实现 PushKit 服务,但我有以下疑问:我看到我只能生成生产 voip 证书,如果我尝试在开发设备上测试 voip 推送通知服务,它是否有效?

This is my implementation test:

这是我的实现测试:

With this 3 line of code i can get push token on didUpdatePushCredentials callback that i use to save into my server.

使用这 3 行代码,我可以在 didUpdatePushCredentials 回调上获取推送令牌,用于保存到我的服务器中。

PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
pushRegistry.delegate = self;
pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];

Server side i generate a "normal" payload push notification with only alert text, and i sent to voip token stored into my server.

服务器端我生成一个只有警报文本的“正常”有效负载推送通知,然后我发送到存储在我的服务器中的 voip 令牌。

I use the callback with debug log, but they never getting called!

我将回调与调试日志一起使用,但它们从未被调用过!

- (void)pushRegistry:(PKPushRegistry *)registry didInvalidatePushTokenForType:(NSString *)type {

          NSLog(@"didInvalidatePushTokenForType");

}

-(void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type {

          NSLog(@"didReceiveIncomingPushWithPayload: %@", payload.description);

}

-(void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type {
     if([credentials.token length] == 0) {
           NSLog(@"voip token NULL");

          return;
     }

      NSLog(@"didUpdatePushCredentials: %@ - Type: %@", credentials.token, type);

}

If i try to generate a push notification message from my server to voip device token previously uploaded, i'm never notified on didReceiveIncomingPushWithPayload callback, but from server i get 200 ok message( message was successfully sent )

如果我尝试从我的服务器生成一条推送通知消息到之前上传的 voip 设备令牌,我永远不会收到 didReceiveIncomingPushWithPayload 回调的通知,但是从服务器我收到 200 ok 消息(消息已成功发送)

回答by M Penades

Just in case someone is interested on testing voip push notifications with Pushkit here I left a small procedure I followed successfully:

以防万一有人对使用 Pushkit 测试 voip 推送通知感兴趣,我留下了一个我成功遵循的小程序:

1 - Create, if you do not have it already, a CSRwith Keychain Access and save your CSR locally.

1 -创建,如果你没有它已经,一个CSR钥匙扣,访问和保存您的CSR本地。

2 - Go to Apple Developer and get access Certificates, Identifiers & Profiles. On the member center.

2 - 转到 Apple Developer 并获取访问证书、标识符和配置文件。在会员中心。

  • Inside Identifiers-> App IDs Create one new app id
  • Inside Devices-> All Add devices UDID you want to use for testing voip pushes
  • Inside Certificates-> All Create a new Production certificate: VoIP Services Certificate. Select previously created app Id for your voip Service Certificate. Select previously created CSR (Certificate Signing Request) and once created download your new voip_services.cer
  • 在 Identifiers-> App IDs 里面创建一个新的 app id
  • 内部设备-> 所有添加设备 UDID 要用于测试 voip 推送
  • Inside Certificates-> All 创建一个新的生产证书:VoIP 服务证书。为您的 voip 服务证书选择之前创建的应用程序 ID。选择之前创建的 CSR(证书签名请求),创建后下载新的 voip_services.cer

Once downloaded double click on voip_services.cerin order to open Keychain Access application and export private key for generated certificate: right button Export certificate.p12file.

下载后双击voip_services.cer以打开 Keychain Access 应用程序并导出生成证书的私钥:右键导出certificate.p12文件。

Save voip_services.cerand certificate.p12file in a folder in order to create your server push notification generator

voip_services.cercertificate.p12文件保存在一个文件夹中,以创建您的服务器推送通知生成器

Finally go to Apple Developer website again and inside Provisioning Profiles->Distribution create a new Ad-Hoc distribution profileincluding on it all devices UDID you want to use for testing voip pushes. Download this profile and drag and drop to your xcode in order to use it on your application.

最后再次访问 Apple Developer 网站,在 Provisioning Profiles->Distribution 中创建一个新的Ad-Hoc 分发配置文件,其中包括要用于测试 voip 推送的所有设备 UDID。下载此配置文件并将其拖放到您的 xcode 中,以便在您的应用程序中使用它。

Now lets create the iOS app that will receive voip push notifications:

现在让我们创建将接收 voip 推送通知的 iOS 应用程序:

  • Create a new Single View Application from Xcode new project menu.
  • Fill its bundle Identifier according to created app id in previous section.
  • Add PushKit.framework in General-> Linked Frameworks and Libraries.
  • In Capabilities enable Background Mode and select Voice over IP option.
  • In Build Settings -> Code Signing select provisioning profile you downloaded previously and select Distribution as Code Signing Identity.
  • 从 Xcode 新项目菜单创建一个新的单一视图应用程序。
  • 根据上一节中创建的应用程序 id 填写其 bundle Identifier。
  • 在 General-> Linked Frameworks and Libraries 中添加 PushKit.framework。
  • 在功能中启用后台模式并选择 IP 语音选项。
  • 在 Build Settings -> Code Signing 中选择您之前下载的配置文件,然后选择 Distribution 作为 Code Signing Identity。

Lets add in the app the code Pasqualeadded in his question:

让我们在应用程序中添加Pasquale在他的问题中添加的代码:

In your root view controller header (ViewController.h) an import for PushKit.framework:

在您的根视图控制器标头 ( ViewController.h) 中导入 PushKit.framework:

#import <PushKit/PushKit.h>

Add delegate in order to implement its functions:

添加委托以实现其功能:

@interface ViewController : UIViewController <PKPushRegistryDelegate>

Add in viewDidLoad function of your root view controller (ViewController.m) push registration:

添加根视图控制器(ViewController.m)推送注册的 viewDidLoad 函数:

- (void)viewDidLoad {
    [super viewDidLoad];

    PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
    pushRegistry.delegate = self;
    pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
}

Implement required delegate functions:

实现所需的委托功能:

- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type{
    if([credentials.token length] == 0) {
        NSLog(@"voip token NULL");
        return;
    }

    NSLog(@"PushCredentials: %@", credentials.token);
}

- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type
{
    NSLog(@"didReceiveIncomingPushWithPayload");
}

Once everything is compiling and ok, archive your project and export your ipa file in order to install it on testing devices (you can use for example Testflight to do the job).

一旦一切都编译好了,归档您的项目并导出您的 ipa 文件,以便将其安装在测试设备上(您可以使用例如 Testflight 来完成这项工作)。

Execute it and get from logs the PushCredentials we will use to send pushes.

执行它并从日志中获取我们将用于发送推送的 PushCredentials。

Now lets go to server side (I followed this great guide of raywenderlich tutorials):

现在让我们转到服务器端(我遵循了这个很棒的raywenderlich 教程指南):

Get back to folder were you placed the three files:

回到您放置三个文件的文件夹:

  • voip_services.cer
  • certificate.p12
  • voip_services.cer
  • 证书.p12

1 - Open a terminal and create pem file from certificate file:

1 - 打开终端并从证书文件创建 pem 文件:

#openssl x509 -in voip_services.cer -inform der -out PushVoipCert.pem

2 - Create pem file from exported private key file:

2 - 从导出的私钥文件创建 pem 文件:

#openssl pkcs12 -nocerts -out PushVoipKey.pem -in certificate.p12

3 - Join both pem files in one:

3 - 将两个 pem 文件合二为一:

#cat PushVoipCert.pem PushVoipKey.pem > ck.pem

In order to send pushes you can use Pusherfrom raywenderlich tutorialstutorial or using a simple php script:

为了发送推送您可以使用推杆raywenderlich教程教程或使用一个简单的PHP脚本:

<?php

// Put your device token here (without spaces):
$deviceToken = '0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78';

// Put your private key's passphrase here:
$passphrase = 'pushchat';

// Put your alert message here:
$message = 'My first push notification!';

////////////////////////////////////////////////////////////////////////////////

$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $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' => $message,
    'sound' => 'default'
    );

// 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));

if (!$result)
    echo 'Message not delivered' . PHP_EOL;
else
    echo 'Message successfully delivered' . PHP_EOL;

// Close the connection to the server
fclose($fp);

you should modify in script:

你应该在脚本中修改:

  • $deviceToken by adding your PushCredentials (from app logs)
  • $passphrase by the passphrase you added on step 2 when creating PushVoipKey.pem
  • $deviceToken 通过添加您的 PushCredentials(来自应用程序日志)
  • $passphrase 由您在创建 PushVoipKey.pem 时在步骤 2 中添加的密码短语

That's it. Execute php script:

就是这样。执行php脚本:

#php simplePushScript.php

and you should receive your voip push notification (you should see app log: "didReceiveIncomingPushWithPayload")

并且您应该会收到您的 voip 推送通知(您应该会看到应用日志:“didReceiveIncomingPushWithPayload”)

After that test I wondered how I could receive standard push notifications through pushkit framework, but unfortunately I have no answer as when registering the push type I could not find any other PKPushType but the PKPushTypeVoIP...

在那次测试之后,我想知道如何通过 pushkit 框架接收标准推送通知,但不幸的是我没有答案,因为在注册推送类型时我找不到任何其他 PKPushType 但 PKPushTypeVoIP ...

pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];

That's all! Thanks for reading!

就这样!谢谢阅读!

回答by Troy

Today I explored this in great detail. I, too, was wondering how to use the generated push token on a development build when Apple only allows us to generate a production VoIP push certificate.

今天我对此进行了非常详细的探讨。我也想知道当 Apple 只允许我们生成生产 VoIP 推送证书时,如何在开发版本中使用生成的推送令牌。

On the server, you have to send a production push to gateway.push.apple.comand a development/sandbox push to gateway.sandbox.push.apple.com. I was able to generate and receive VoIP pushes on a development build of my app using the production VoIP certificate on gateway.sandbox.push.apple.com. I have not yet tried, but assume it will also work on an ad hoc or production build and using gateway.push.apple.com.

在服务器上,您必须向 发送生产推送gateway.push.apple.com和开发/沙盒推送gateway.sandbox.push.apple.com。我能够使用gateway.sandbox.push.apple.com. 我还没有尝试过,但假设它也适用于临时或生产构建并使用gateway.push.apple.com.

Also, note that push notifications do not work in the simulator at all.

另请注意,推送通知在模拟器中根本不起作用。

回答by Shebuka

You need to enable also Remote Notifications, even if you don't use them:

您还需要启用远程通知,即使您不使用它们:

  • inside your App ID identifier on Developer portal
  • recreate the Development Provisioning profiles
  • hit Download All in XCode -> Preferences... -> Accounts -> your account
  • enable Remote Notifications in Capabilities -> Background Modes
  • 在开发者门户上的 App ID 标识符中
  • 重新创建开发供应配置文件
  • 在 XCode 中点击 Download All -> Preferences... -> Accounts -> your account
  • 在 Capabilities -> Background Modes 中启用远程通知

Done this you will receive the delegate callback both in Debug and in Release.

完成此操作后,您将在 Debug 和 Release 中收到委托回调。