这篇文章还可以在这里找到 英语
If you're new here, you may want to subscribe to my RSS feed or follow me on Twitter. Thanks for visiting!
如果你还是没有收到推送的信息,那看看push.php脚本是否仍在运行。然后看看push_development.log文件,这个文件的内容应该和如下类似:
2011-05-06T23:57:29+02:00 Sending message 1 to '0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78', payload: '{"aps":{"alert":"SteveJ: Hello, world!","sound":"default"}}' 2011-05-06T23:57:29+02:00 Message successfully delivered
你也应该在phpMyAdmin里的push_queue数据库表格看到一行关于这个信息的记录。
推送信息有时可能需要一段时间才会到达,有时就算到了苹果的服务器后也可能无法发送到设备上。你应该多试几次说不定就可以了。
在app运行的情况下接收推送信息
当你的iPhone收到推送信息后到底会发生什么呢?总共有三种可能性:
- app在前台运行. 接收到推送信息时屏幕上不会有任何显示,也不会有提示音,但你的app delegate会收到这个推送信息。你可以在这里加入代码来处理接收到的信息。
- app不在前台运行。iPhone可能停留在主界面或者另一个app正在运行.一个提示窗口会弹出,可能伴随着提示音。用户可以点击Close按钮来关闭这个窗口或者点击View按钮来打开你的app。如果用户点击的时Close按钮,那你的app不会处理这个推送的信息。
- iPhone在锁屏状态下. 同样一个提示窗口弹出,并伴随着提示音,但是这个窗口不会有Close和View按钮。屏幕解锁后会自动进入你的app。
因为app delegate是接收推送信息的地方,我们对app的最后改动都是在AppDelegate.m文件中。我们需要修改两处:
- application:didFinishLaunchingWithOptions:函数. 如果推送信息到达时你的app不在前台运行,而用户在弹出窗口点击了“View”按钮,你的app会重新运行然后这个信息会作为参数注入到application:didFinishLaunchingWithOptions:函数中。
- application:didReceiveRemoteNotification:函数. 如果信息到达时你的app正在前台运行,那这个函数就会被调用。在iOS4.0或更新的版本,如果你的app从暂停状态进入前台,这个函数也会被调用。你可以用UIApplication的applicationState属性来检查你的app是否是从暂停状态苏醒。
上述的两个函数都会有一个字典参数其中包含了JSON格式的推送信息内容。OS已经帮我们把JSON格式的信息转换成Objective-C字典了。将下面的代码加到didFinishLaunchingWithOptions:函数的return语句前:
|
我们先确保launchOptions参数不是nil以及launchOptions中包含了推送信息。然后调用addMessageFromRemoteNotification函数来处理这个信息。
把下面的函数加到AppDelegate.m文件中:
|
这个函数同样依靠addMessageFromRemoteNotification来完成处理信息的工作。
将下面这个函数复制粘贴到didFinishLaunchingWithOptions:函数上面:
|
我保证这是最后一点代码了。然我们解释一下这段代码。
|
首先我们创建一个Message对象。我们会把推送信息的内容提取出来,填入到这个对象中然后将这个对象加入到DataModel中。
|
上面的代码从推送信息中获取了信息的内容。推送信息的JSON的格式看起来是这样的:
|
服务器把信息内容以及信息作者的昵称放到了“alert”栏中。我们对这个字典中的其他内容并不感兴趣。
|
上面的代码将发送者的昵称和信息内容分解出来放入到Message对象中。发送者昵称是分号和空格之前的字符串。
|
现在我们可以把这个Message对象加入到DataModel中了。
|
最后,我们让ChatViewController加入这个新的信息。但是,如果推送信息是在didFinishLaunchingWithOptions函数中收到的,那我们就不能刷新这个视图,因为那时ChatViewController的表格还没有加载。视图加入这个信息会导致系统崩溃的。
就这些了。编译并运行现有的程序。用test_message.html中的表格来发送一些信息。你应该在app的聊天视图中看到这些信息气泡出现。
自定义提示信息
你应该还记得我们之前在介绍推送信息时曾说过你可以自定义提示设置。比如你可以在有信息时播放一个自定义的提示音。我在app的resources文件夹中放了一个音频文件叫做beep.caf。
打开api.php文件并在makePayload()函数中将下面这行代码:
|
改为:
|
你不需要改变app本身的任何代码,甚至不用重新编译。但你还是应该在设备上关闭打开了的app。因为如果我们的app正在前台运行,那提示音是不会响的。现在用test_message.html给app发一个信息。当提示窗口出现时,提示音是不是不同了?
你也可以实验修改其他的选项。比如提供自定义按钮,或者给app设定数量小图标。(如果你想实验数量小图标,别忘了让app注册接收数量图标。现在我们的app只会有提示音和提示窗口。)
反馈服务器
你现在应该已经累得想睡觉了吧,但是我们还是要给服务器再加一些代码,然我们的服务器更加完善。
现象一下下面这个情况:你的数据库中有一个表格记录了很多用户的设备编码。但有的用户会移除你的app。很悲伤的情况但是无可避免。
但是,你的服务器并不会知道这个变化。服务器会继续将信息推送到他们的设备上。
这当然是一个及其不应该的情况,所以我们需要这个反馈服务器。你需要定期联系这个服务器来下载无效的设备编码列表。你应该停止给这些设备推送信息。
在PushChatServer/push文件夹中你应该看到feedback.php这个文件。这个文件中的代码会连接反馈服务器并下载相应的设备编码。你应该还看到了feedback_config.php文件。这个文件含有feedback.php脚本所需要的选项值。这个脚本会使用你的PEM文件,SSL证书和密钥来链接苹果服务器。
与push.php不同的是,你不应该在后台线程中不断运行反馈脚本。你应该建立一个cron job让服务器每小时运行这个脚本一次。
Unlike push.php, the feedback script should not be run continuously as a background process. Instead, you should set up a cron job on the server that launches it every hour or so.
这个脚本会连接到苹果的反馈服务,下载无效的设备编码列表,关闭连接。然后它会到active_users表格中删除列表中的用户。
改进和限制
PushChat用推送信息的方式作为传递信息的唯一渠道。在我们的教程中看起来不错,但却有一个潜在的问题。信息是否能成功推送到用户设备并没有被保障。所以如果推送服务丢失了任何一个信息,用户就永远无法收到这个信息了。还有就是如果用户在弹出提示时点击了“Close”按钮,我们的app就不会接收到这则信息。在我们的app中,就不会有关于这个信息的气泡出现在聊天界面中了。
更好地方法是在服务器上保持一个数据库。我们的API可以把每个信息都放入一个叫“messages”的数据库表格中。当app启动时(因为用户手动开启,或者通过信息提示窗口),我们会从服务器下载这些信息。这样就不会有信息丢失的情况了。
push.php脚本功能齐全,但是如果你的app有很多用户的话就不应该使用了。PHP远没有C或者C++的效率高,速度快。还有就是你可以看看这些PHP脚本:http://code.google.com/p/php-apns/。
下一步做什么?
这是我们的教程所有的代码。
虽然这个教程以及可以赶得上一个短篇小说了,但是关于推送服务,我们还有许多没有提到的。如果你的app非常依赖推送服务,我建议你再看看下面这些资源:
- 苹果的本地和推送信息编程指南
- App Store Approval Guidelines的第五章(section 5)
- Technical Note TN2265
- WWDC 2010 视频集的第129节. 这些讲座大多是关于本地信息提示的。但一开始也有对推送信息的介绍。
如果你有任何问题,意见或者建议,请登陆下面的论坛发表评论!
这个教程是由iOS教程组成员 Matthijs Hollemans编写的。Matthijs是一个经验丰富的自由iOS 开发者,可以接收合同工作!
翻译分类: