更多 在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语句前:

if (launchOptions != nil)
	{
		NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
		if (dictionary != nil)
		{
			NSLog(@"Launched from push notification: %@", dictionary);
			[self addMessageFromRemoteNotification:dictionary updateUI:NO];
		}
	}





我们先确保launchOptions参数不是nil以及launchOptions中包含了推送信息。然后调用addMessageFromRemoteNotification函数来处理这个信息。

把下面的函数加到AppDelegate.m文件中:


- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo
  {
  	NSLog(@"Received notification: %@", userInfo);
	[self addMessageFromRemoteNotification:userInfo updateUI:YES];
  }


这个函数同样依靠addMessageFromRemoteNotification来完成处理信息的工作。
将下面这个函数复制粘贴到didFinishLaunchingWithOptions:函数上面:


- (void)addMessageFromRemoteNotification:(NSDictionary*)userInfo updateUI:(BOOL)updateUI
{
	Message* message = [[Message alloc] init];
	message.date = [NSDate date];
 
	NSString* alertValue = [[userInfo valueForKey:@"aps"] valueForKey:@"alert"];
 
	NSMutableArray* parts = [NSMutableArray arrayWithArray:[alertValue componentsSeparatedByString:@": "]];
	message.senderName = [parts objectAtIndex:0];
	[parts removeObjectAtIndex:0];
	message.text = [parts componentsJoinedByString:@": "];
 
	int index = [dataModel addMessage:message];
 
	if (updateUI)
		[self.chatViewController didSaveMessage:message atIndex:index];
 
	[message release];
}


我保证这是最后一点代码了。然我们解释一下这段代码。


Message* message = [[Message alloc] init];
	message.date = [NSDate date];


首先我们创建一个Message对象。我们会把推送信息的内容提取出来,填入到这个对象中然后将这个对象加入到DataModel中。


NSString* alertValue = [[userInfo valueForKey:@"aps"] valueForKey:@"alert"];


上面的代码从推送信息中获取了信息的内容。推送信息的JSON的格式看起来是这样的:


{
	"aps":
	{
		"alert": "SENDER_NAME: MESSAGE_TEXT",
		"sound": "default"
	},
}


服务器把信息内容以及信息作者的昵称放到了“alert”栏中。我们对这个字典中的其他内容并不感兴趣。


NSMutableArray* parts = [NSMutableArray arrayWithArray:[alertValue componentsSeparatedByString:@": "]];
	message.senderName = [parts objectAtIndex:0];
	[parts removeObjectAtIndex:0];
	message.text = [parts componentsJoinedByString:@": "];


上面的代码将发送者的昵称和信息内容分解出来放入到Message对象中。发送者昵称是分号和空格之前的字符串。


int index = [dataModel addMessage:message];


现在我们可以把这个Message对象加入到DataModel中了。


if (updateUI)
		[self.chatViewController didSaveMessage:message atIndex:index];


最后,我们让ChatViewController加入这个新的信息。但是,如果推送信息是在didFinishLaunchingWithOptions函数中收到的,那我们就不能刷新这个视图,因为那时ChatViewController的表格还没有加载。视图加入这个信息会导致系统崩溃的。

就这些了。编译并运行现有的程序。用test_message.html中的表格来发送一些信息。你应该在app的聊天视图中看到这些信息气泡出现。

自定义提示信息

你应该还记得我们之前在介绍推送信息时曾说过你可以自定义提示设置。比如你可以在有信息时播放一个自定义的提示音。我在app的resources文件夹中放了一个音频文件叫做beep.caf。

打开api.php文件并在makePayload()函数中将下面这行代码:

$payload = '{"aps":{"alert":"' . $nameJson . ': ' . $textJson . '","sound":"default"}}';

改为

$payload = '{"aps":{"alert":"' . $nameJson . ': ' . $textJson . '","sound":"beep.caf"}}';



你不需要改变app本身的任何代码,甚至不用重新编译。但你还是应该在设备上关闭打开了的app。因为如果我们的app正在前台运行,那提示音是不会响的。现在用test_message.html给app发一个信息。当提示窗口出现时,提示音是不是不同了?

你也可以实验修改其他的选项。比如提供自定义按钮,或者给app设定数量小图标。(如果你想实验数量小图标,别忘了让app注册接收数量图标。现在我们的app只会有提示音和提示窗口。)