我已经构建了一个类似于Snapchat的消息传递应用程序 - 一个用户可以发送另一个用户图片。我正在尝试向应用添加推送通知,以便当从UserA向UserB发送消息时,UserB会收到“来自UserA的新消息”的推送通知。
我现在已经研究了几个小时了,我觉得我非常接近。
我正在尝试使用Parse发送推送通知。我希望它的工作方式如下:当UserA向UserB发送消息时,还会向UserB发送一条推送通知,其中显示“来自UserA的新消息”。我成功地使用Parse网站向使用该应用程序的设备发送推送通知,但是无法从应用程序内部成功发送推送通知(当用户发送消息时)接收用户的设备。
推送通知显然已成功发送,因为我的Parse帐户显示了我发送的消息。但是,没有消息实际到达目标设备,推送通知列表显示每个推送通知的0个订阅者。
我可以点击其中一个来查看详细信息。
此外,我正在使用分发/生产配置文件&证书。
这是我在UserA向UserB发送消息后使用发送推送通知的代码 - message
对象是已上传到Parse的消息,而messageRecipients是消息的用户正被送往:
// Send Push Notification to recipients
NSArray *messageRecipients = [message objectForKey:@"recipientIds"];
PFQuery *pushQuery = [PFInstallation query];
[pushQuery whereKey:@"owner" containedIn:messageRecipients];
PFPush *push = [[PFPush alloc] init];
[push setQuery:pushQuery];
[push setMessage:[NSString stringWithFormat: @"New Message from %@!", [PFUser currentUser].username]];
[push sendPushInBackground];
以下是我的AppDelegate.m相关方法:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[Parse setApplicationId:@"[This is where my app Id is]"
clientKey:@"[This is where client Id is]"];
[self customizeUserInterface];
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound];
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[PFPush storeDeviceToken:deviceToken];
[PFPush subscribeToChannelInBackground:@""];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
NSLog(@"Did fail to register for push, %@", error);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[PFPush handlePush:userInfo];
}
我还在Parse.com论坛上提交了一篇文章:https://parse.com/questions/sending-a-push-notification-from-one-user-to-another-user
我有什么遗漏或做错了吗?
编辑:我现在能够在我的Parse帐户中看到订阅者,但我实际上并没有在我的设备上收到推送通知。当我尝试从Parse网站发送推送通知测试时也是如此。
答案 0 :(得分:4)
我的搜索一直回到这里,但这里没有任何内容真正拼写出来。所以这就是我的工作方式:
在我的AppDelegate.m中,我有:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
PFUser *currentUser = [PFUser currentUser];
if (currentUser) {
//save the installation
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
currentInstallation[@"installationUser"] = [[PFUser currentUser]objectId];
// here we add a column to the installation table and store the current user’s ID
// this way we can target specific users later
// while we’re at it, this is a good place to reset our app’s badge count
// you have to do this locally as well as on the parse server by updating
// the PFInstallation object
if (currentInstallation.badge != 0) {
currentInstallation.badge = 0;
[currentInstallation saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
// Handle error here with an alert…
}
else {
// only update locally if the remote update succeeded so they always match
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
NSLog(@"updated badge");
}
}];
}
} else {
[PFUser logOut];
// show the signup screen here....
}
}
在我发送推送的viewController中:
<强> myViewController.h 强>
@property (nonatomic, strong) NSMutableArray *recipients; // declare the array we'll use to store our recipients
<强> myViewController.m 强>
- (void)viewDidLoad
{
[super viewDidLoad];
self.recipients = [[NSMutableArray alloc] init]; // initialize the array we'll use to hold our recipients
}
// in another part of the code (not shown here) we set up a tableView with all of the current user's friends in it
// when the user taps a row in that tableView we add or remove the selected friend from our recipients list
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
PFUser *user = [self.friends objectAtIndex:indexPath.row];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.recipients addObject:user.objectId]; // user selected a recipient, add them to the array
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
[self.recipients removeObject:user.objectId]; // user de-selected a recipient, remove them from the array
}
}
- (void)uploadMessage
{
UIImage *newImage = [self resizeImage:self.image toWidth:640.0f andHeight:960.0f];
NSData *fileData= UIImageJPEGRepresentation(newImage, 1.0);
NSString *fileName= @"image.jpg";;
NSString *fileType= @"image";
PFFile *file = [PFFile fileWithName:fileName data:fileData];
[file saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
// Handle error here with an alert…
}
else {
PFObject *message = [PFObject objectWithClassName:@"Messages"];
[message setObject:file forKey:@"file"];
[message setObject:fileType forKey:@"fileType"];
[message setObject:self.recipients forKey:@"recipientIds"];
// self.recipients is an NSMutableArray of the objectIds for each
// user the message will go to
[message setObject:[[PFUser currentUser] objectId] forKey:@"senderId"];
[message setObject:[[PFUser currentUser] username] forKey:@"senderName"];
[message saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
// Handle error here with an alert…
}
else {
// Everything was successful! Reset UI… do other stuff
// Here’s where we will send the push
//set our options
NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:
@“Ne messages available!!”, @"alert",
@"Increment", @"badge",
nil];
// Now we’ll need to query all saved installations to find those of our recipients
// Create our Installation query using the self.recipients array we already have
PFQuery *pushQuery = [PFInstallation query];
[pushQuery whereKey:@"installationUser" containedIn:self.recipients];
// Send push notification to our query
PFPush *push = [[PFPush alloc] init];
[push setQuery:pushQuery];
[push setData:data];
[push sendPushInBackground];
}
}];
}
}];
}
答案 1 :(得分:3)
我想我有答案。我遇到了同样的问题,我刚解决了。
当您为所有者设置值时,应使用“[PFUser currentUser] .objectId”,而不是[PFUser currentUser]。后者为您提供了一个指向所有者的指针,但我们需要一个字符串来在这种情况下设置Push查询。
当我们第一次将所有者设置为安装时,我们应该将objectId设置为字符串为owner而不是像下面的[PFUser currentUser]。
[currentInstallation setObject:[PFUser currentUser].objectId forKey:@"owner"];
稍后我们可以将所有者(字符串)设置为我们的pushQuery。
答案 2 :(得分:0)
您是否尝试将所有者存储在安装中。即
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:deviceToken];
[currentInstallation setObject:[PFUser currentUser] forKey:@"owner"];
[currentInstallation saveInBackground];
}
来自:click here
答案 3 :(得分:0)
鉴于您到目前为止发布的内容,我不确定您的代码为什么不适合您。似乎您的安装表不包含“所有者”列,或者它包含“所有者”列,其值/类型不是[message objectForKey:@"recipientIds"]
数组中包含的值/类型;但是,为了防止您需要/想要尝试备份方法,这是使用Parse将推送通知从一个设备发送到另一个设备的另一种方法:
首先将接收推送的用户/用户组订阅到他们自己的唯一频道(除主频道外),例如
[PFPush subscribeToChannelInBackground:taylors_channel];
然后,从发送推送的设备,将频道设置为收件人的频道:
PFPush *push = [[PFPush alloc] init];
[push setChannel:taylors_channel];
[push setMessage:[NSString stringWithFormat: @"New Message from %@!", [PFUser currentUser].username]];
[push sendPushInBackground];
此外,您还可以为多个同伴设置相同的频道,或使用[push setChannels:channel_array]
一次向多个频道发送消息;
答案 4 :(得分:0)
要详细说明djshiow的响应,请保存当前安装。
PFQuery * pushQuery = [PFInstallation query];
PFUser * userReceivingPush;
[pushQuery whereKey:@"owner" equalTo:userReceivingPush];
NSString * alert = [NSString stringWithFormat:@"You have a new message from %@!", [PFUser currentUser].username];
NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:
alert, @"alert",
@"default", @"sound",
@"Increment", @"badge",
nil];
[PFPush sendPushDataToQueryInBackground:pushQuery withData:data block:^(BOOL succeeded, NSError *error) {
if (!error) {
}
else {
}
}];