我想将推送消息广播到多个设备。目前,如果数据库表中只存储了2个(可能是1个或2个)设备令牌,则可以发送消息。对于3个或更多设备令牌,我无法发送推送消息。它甚至不会向先前添加的2个设备发送消息。在服务器端,我可以看到传递的消息,但它们实际上并未传递。
我在开发者资料和分发配置文件上测试了它,但是如果在DB表中只保存了1或2个设备,我只能发送消息。
在这两种情况下,我都使用了一个app id,它被配置用于开发和分发。
我的服务器端php代码如下:
<?php
error_reporting(0);
include 'classfiles/Tokens.php';
if(isset($_POST))
{
$sender = $_POST['sender'];
$message = $_POST['message'];
$token = new Tokens;
$arrtokens = $token->getTokens();
$devicetoken = $_POST['device_token'];
// Settings
$apnsCert = 'test.pem';//To be changed
$apnsHost = 'gateway.push.apple.com';//To be changed
$apnsPort = 2195;
// Connect to Apple Push Notification server
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'passphrase', 'test123');
//60 -> timeout in seconds
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $streamContext);
if (!$apns) {
die('Error creating ssl socket');
}
stream_set_blocking ($apns, 0);
echo 'Connected to APNS' . PHP_EOL;
if(is_array($arrtokens))
{
//foreach($arrtokens as $key=>$deviceToken)
for($i=0;$i<count($arrtokens);$i++)
{
$incrementcount = 0;
$tokenid = $arrtokens[$i][0];
$badgecount = $arrtokens[$i][1];
$incrementcount = $badgecount+1;
// Prepare payload
$payload =
array(
'aps' => array(
'alert' => $message,
'badge' => $incrementcount,
'sound' => 'default',
'sender' => $sender
)
);
$payload = json_encode($payload);
/*
// this was also working
$apnsMessage =
chr(1)
. pack('N', 88)
. pack('N', time() + 86400)
. chr(0) . chr(32)
. pack('H*', str_replace(' ', '', $tokenid))
. chr(0) . chr(strlen($payload))
. $payload . $payload;
*/
$apnsMessage = chr(0) .pack('n',32) . pack('H*', str_replace(' ', '', $tokenid)) . chr(0) . chr(strlen($payload)) . $payload;
// this was also working
// $apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $tokenid)) . chr(0) . chr(strlen($payload)) . $payload;
// this was also working
// $apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $device_tokens_array[i])) . chr(0) . chr(strlen($payload)) . $payload;
// $result =fwrite($apns, $apnsMessage);
$result = fwrite($apns, $apnsMessage, strlen($apnsMessage));
if(!$result)
{
echo 'Message to the device ' . $arrtokens[$i][0] . ' not delivered' . '<br/>';
}else
{
$token->updateToken($tokenid,$incrementcount);
echo 'Message to the device ' . $arrtokens[$i][0] . ' successfully delivered' . '<br/>';
}
// sleep(10);
}
}
else if($devicetoken != "")
{
$apnsMessage =
chr(1)
. pack('N', 88)
. pack('N', time() + 86400)
. chr(0) . chr(32)
. pack('H*', str_replace(' ', '', $deviceToken))
. chr(0) . chr(strlen($payload))
. $payload . $payload;
$result = fwrite($apns, $apnsMessage);
if(!$result)
echo 'Message to the device ' . $token . ' not delivered' . PHP_EOL;
else
echo 'Message to the device ' . $token . ' successfully delivered' . PHP_EOL;
}
usleep(500000);
fclose($apns);
}
function checkAppleErrorResponse($apns)
{
$responseBinary = fread($apns, 6);
if ($responseBinary !== false && strlen($responseBinary) == 6)
{
print(
"\n"
.'Error message recieved from Apple.'."\n"
.'For the meaning, refer to: "Provider Communication with Apple Push Notification Service"'."\n"
);
$response = unpack('Ccommand/Cstatus_code/Nidentifier', $responseBinary);
var_dump($response);
}
}
?>
我的客户端代码在这里:
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"error : %@", [error description]);
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(@"deviceToken : %@", deviceToken);
NSString *myDeviceToken = [[[deviceToken description]
stringByReplacingOccurrencesOfString: @"<" withString: @""]
stringByReplacingOccurrencesOfString: @">" withString: @""];
NSLog(@"%@",myDeviceToken);
[[NSUserDefaults standardUserDefaults] setObject:myDeviceToken forKey:@"myDeviceToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
receivedData = [[NSMutableData alloc] initWithLength:0];
NSString *urlString = [NSString stringWithFormat:@"%@%@", tokenApi, myDeviceToken];//deviceToken
urlString = [urlString stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
NSLog(@"URL : %@", urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types == UIRemoteNotificationTypeNone) {
NSLog(@"UIRemoteNotificationTypeNone");
} else if (types == UIRemoteNotificationTypeAlert) {
NSLog(@"UIRemoteNotificationTypeAlert");
} else if (types == UIRemoteNotificationTypeBadge) {
NSLog(@"UIRemoteNotificationTypeBadge");
} else if (types == UIRemoteNotificationTypeSound) {
NSLog(@"UIRemoteNotificationTypeSound");
}
UIApplicationState state = [application applicationState];
int batchNo = [[UIApplication sharedApplication] applicationIconBadgeNumber];
if (state == UIApplicationStateActive) {
NSLog(@"applicationIconBadgeNumber : %d", [[UIApplication sharedApplication] applicationIconBadgeNumber]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[[userInfo objectForKey:@"aps"] objectForKey:@"sender"]
message:[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
batchNo = 0;
} else {
NSLog(@"applicationIconBadgeNumber : %d", [[UIApplication sharedApplication] applicationIconBadgeNumber]);
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:batchNo - 1];
batchNo = [[UIApplication sharedApplication] applicationIconBadgeNumber];
}
NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:@"myDeviceToken"];
receivedData = [[NSMutableData alloc] initWithLength:0];
NSString *urlString = [NSString stringWithFormat:@"%@%@&count=% d", updateTokenApi, token,batchNo];//deviceToken
urlString = [urlString stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
NSLog(@"URL : %@", urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];
// NSLog(@"userInfo : %@", userInfo);
NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"alerts"]];
// NSLog(@"Before : %@", array);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM/dd/YYYY hh:mm a"];
NSMutableArray *alertarray = [[NSMutableArray alloc] initWithCapacity:0];
[alertarray addObject:[dateFormatter stringFromDate:[NSDate date]]];
[alertarray addObject:[[userInfo objectForKey:@"aps"] objectForKey:@"sender"]];
[alertarray addObject:[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]];
[array addObject:alertarray];
NSArray *alertsArray = [[NSArray alloc] initWithArray:array];
[[NSUserDefaults standardUserDefaults] setObject:alertsArray forKey:@"alerts"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[[[self accountPage] accountHistoryPage] alertsArray] removeAllObjects];
[[[[self accountPage] accountHistoryPage] alertsArray] addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"alerts"]];
[[[[self accountPage] accountHistoryPage] accountDetailTableView] reloadData];
// NSLog(@"After : %@", [[NSUserDefaults standardUserDefaults] objectForKey:@"alerts"]);
}
答案 0 :(得分:4)
最可能的解释是第3个设备令牌无效。如果您首先发送到此设备令牌,Apple将关闭套接字并忽略其他两个设备的消息,即使它们似乎在服务器端成功传送。 如果您正在混合开发和生产设备令牌,这可以解释为什么其中一些是无效的。如果使用生产证书打开到APNS服务器的套接字,则只有生产设备令牌对该连接有效(反之亦然)。