For message push, ios uses apns, and android uses gcm. If the push fails, an invalid token will be returned. However, among the invalid tokens, can we distinguish which ones are prohibited notifications and which ones are caused by uninstalling the app?
1 APNS PHP push return error handling
Push.php
if (!empty($aMessage['ERRORS'])) { foreach($aMessage['ERRORS'] as $aError) { if ($aError['statusCode'] == 0) { $this->_log("INFO: Message ID {$k} {$sCustomIdentifier} has no error ({$aError['statusCode']}), removing from queue..."); $this->_removeMessageFromQueue($k); continue 2; } else if ($aError['statusCode'] > 1 && $aError['statusCode'] <= 8) { $this->_log("WARNING: Message ID {$k} {$sCustomIdentifier} has an unrecoverable error ({$aError['statusCode']}), removing from queue without retrying..."); $this->_removeMessageFromQueue($k, true); continue 2; } } if (($nErrors = count($aMessage['ERRORS'])) >= $this->_nSendRetryTimes) { $this->_log( "WARNING: Message ID {$k} {$sCustomIdentifier} has {$nErrors} errors, removing from queue..." ); $this->_removeMessageFromQueue($k, true); continue; } }
By disabling notifications, apns will not report an error and will not regard this token as an invalid or wrong token.
Uninstalling the app will call the following judgment, statusCode is equal to 8
if ($aError['statusCode'] > 1 && $aError['statusCode'] <= 8) { $this->_log("WARNING: Message ID {$k} {$sCustomIdentifier} has an unrecoverable error ({$aError['statusCode']}), removing from queue without retrying..."); $this->_removeMessageFromQueue($k, true); continue 2; }
Therefore, apns should be able to distinguish push failures caused by uninstallation, but disabling notifications will not respond
2 GCM error judgment code analysis:
Response.class .php
/** * Returns an array containing invalid registration ids * They must be removed from DB because the application was uninstalled from the device. * * @return array */ public function getInvalidRegistrationIds() { if ($this->getFailureCount() == 0) { return array(); } $filteredResults = array_filter($this->results, function($result) { return (isset($result['error']) && (($result['error'] == "NotRegistered") || ($result['error'] == "InvalidRegistration"))); }); return array_keys($filteredResults); } /** * Returns an array of registration ids for which you must resend a message (?), * cause devices aren't available now. * * @TODO: check if it be auto sended later * * @return array */ public function getUnavailableRegistrationIds() { if ($this->getFailureCount() == 0) { return array(); } $filteredResults = array_filter($this->results, function($result) { return ( isset($result['error']) && ($result['error'] == "Unavailable") ); }); return array_keys($filteredResults); }
If notifications are disabled, neither of the above two methods will write the error token. That is to say, if notifications are disabled, the token is also valid and no error will be returned.
If the app is uninstalled, getInvalidRegistrationIds will be executed, and $result['error']==NotRegistered
In this way, if GCM returns NotRegistered, it means that the error message is caused by uninstallation, and the notification is prohibited. GCM treats it as Normal tokens are issued.
Through the above test, it shows that apns and gcm handle ban notifications as normal tokens, while uninstalling the app will treat them as invalid tokens. (If you uninstall and reinstall, a new token will be generated)