Push notification not propagating to multiple devices in iphone app?

I want to broadcast a push message to multiple devices. Currently I can send messages if there are only 2 (1 or 2) device tokens in the database table. For 3 or more device tokens, I cannot send push messages. It doesn't even send messages to the previously added 2 devices. Side by side, I see messages as delivered, but they are not actually being delivered.

I tested it on both developer profile and distribution profile, but on both I can only send messages if only 1 or 2 devices are stored in the DB table.

In both cases, I used a single App ID that is configured for development and distribution.

My server side php code looks like this:

<?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);
}
}

?>

      

And my client side code is here:

- (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"]);
}

      

+1


source to share


1 answer


The most likely explanation is that the 3rd device token is invalid. If you send this device token first, Apple closes the socket and messages to the other two devices are ignored, even if they seem to have been successfully delivered on the server side. If you mix development and production tokens, that explains why some of them are invalid. If you are using a production certificate to open a socket on the APNS server, only production device tokens are valid for that connection (and vice versa).



+4


source







All Articles