訊息推播ios用了apns,android用的是gcm。推播失敗都會回傳無效的token,但是無效的tokne中,能不能區分到哪些是禁止通知,哪些是卸載app導致的呢?
1 APNS PHP 的推播回傳錯誤處理
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; } }
透過禁止通知,apns不會報錯,不會將這個token當成無效或錯誤的token。
卸載app,會呼叫到以下判斷,statusCode等於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; }
因此,apns應該是可以區分卸載導致的推送失敗,但是禁止通知則無法反應
2 GCM的錯誤判斷代碼分析:
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); }
如果禁止通知,上述2個方法都不會寫入錯誤token,也就是說禁止通知,token也是有效的,且不會回傳錯誤。
如果是卸載app,則會執行到getInvalidRegistrationIds,且$result['error']==NotRegistered
這樣,GCM如果返回的是NotRegistered,則說明是卸載產生的錯誤訊息,而禁止通知,GCM是當成正常token發出去的。
通過以上測試,說明apns和gcm對禁止通知都是當成正常token來處理的,而卸載app則會當成無效的token。 (卸載後重裝的話,會產生新的token)