2009-08-14 20 views
28

Qualcuno può chiarire che cosa gli APN (Apple Push Notification) vogliono fino a come lo si interroga?Tecnica PHP per interrogare gli APNs Feedback Server

I documenti dicono che inizia a inviare non appena viene stabilita la connessione. Significa che non faccio un fread() su di esso?

Ecco il mio codice corrente per cercare di leggerlo. NON ho inserito il fread() in un ciclo perché non so quale risposta indichi "non più record da leggere" e non volevo un ciclo infinito sul mio server.

<?php 
$apnsCert = 'HOHRO-prod.pem'; 

$streamContext = stream_context_create(); 
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert); 
stream_context_set_option($streamContext, 'ssl', 'verify_peer', false); 

$apns = stream_socket_client('ssl://feedback.push.apple.com:2196', $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext); 

echo 'error=' . $error; 
echo 'errorString=' . $errorString; 


$result = fread($apns, 38); 
echo 'result=' . $result; 


fclose($apns); 
?> 

Finora tutto ciò che ottengo è una risposta nulla. Non ci sono errori quindi è in connessione.

Non so se la risposta nulla significa che non ci sono dati oppure il mio fread() è il modo sbagliato per farlo.

Grazie

+0

Oggi ho scoperto che fread() non funzionerà perché il feedback APN invia i dati della spazzatura fino a quando il feedback reale. Ciò causa il fallimento di fread, perché sta leggendo dati null/vuoti. Come gw1921 menziona di seguito, è necessario eseguire il loop su feof() fino a strlen (fread ($ apns, 38)). Da quel momento in poi, avrai un feedback valido. Quindi, decomprimere i dati come suggerito da Nick B in basso. (Un altro trucco sgradevole: l'app disinstallata non genera feedback a meno che non si disponga di un'altra app sul dispositivo con lo stesso ambiente aps. Pertanto, sul proprio dispositivo sono necessarie 2 app sandbox abilitate al push per consentire a quello disinstallato di compilare il feedback.) – brack

+0

Anche io ho un codice simile e anch'io ottengo null da fread. Non sono sicuro che il mio codice funzioni davvero e l'APNS sta inviando una risposta NULL o manca qualcosa. Sono sicuro che la mia connessione ad APNS abbia avuto successo. Ho installato la mia applicazione su alcuni dispositivi 5-10 e inviato un paio di avvisi, quindi ho disinstallato l'applicazione da pochi e ho iniziato a inviare nuovamente gli avvisi in modo che il server di feedback di APNS ci informasse che non era in grado di fornire su pochi dispositivi. Non ho niente di diverso da vuoto in fread() :-(Se hai fatto qualcosa di diverso e ho funzionato per favore fammi sapere. – Anish

+0

Hai usato "pushutil"? Una volta capito, è un modo più veloce per controllare il server di feedback.È un'utility Mac OS X che si compila e quindi si esegue dalla riga di comando di Unix. Google Erica Sadun - è sul suo sito sotto Push. –

risposta

1

ho ottenuto la soluzione dal forum di Apple ed è per lo sviluppo. Prova anche per la produzione.

"Bene, come muto come sembra, ho trovato una soluzione:

Creare un'App ID fittizio nel portale del programma, attivare le notifiche di sviluppo spinta su di esso creare e scaricare il profilo di provisioning associato Creare un nuovo progetto xcode e invoca il metodo registerForRemoteNotificationTypes all'avvio. Installa l'app fittizia sul tuo dispositivo. A questo punto, dovresti avere due app DEVELOPMENT in esecuzione sul tuo dispositivo: l'app originale e l'app fittizia. Entrambe devono essere registrate per ricevere push notifiche Disinstallare l'app originale e provare a inviare una notifica push a quell'app. Richiamare il servizio di feedback vice, e dovresti ricevere i dati indietro. "

2

Quel codice sembra giusto, tuttavia è necessario eseguire un ciclo e controllare la fine del flusso per poter leggere tutti i codici dispositivo.

while (!feof($apns)) { 
     $devcon = fread($apns, 38); 
} 

Tuttavia, il mio problema è il disimballaggio effettivo dei dati. Qualcuno sa come decomprimere i dati binari che hai appena letto per ottenere l'effettivo ID del dispositivo (come stringa) insieme al timestamp ecc.?

+1

Penso che questa sia l'idea giusta - $ array = unpack ("NnH32", $ result); $ feedbackTime = $ row [0]; $ feedbackLen = $ row [1]; $ feedbackUDID = $ row [2]; Questo decomprime i 38 byte inviati dal server di feedback. Tuttavia, il valore di data a 32 bit è nell'ordine di rete o big-endian. Se qualcuno è in grado di fornire una funzione PHP che capovolge i 4 byte nell'ordine Intel (little-endian), penso che abbiamo la soluzione. NOTA: l'UDID effettivo è una stringa di caratteri e NON è necessario che l'ordine venga capovolto. –

+0

Questo va bene? --------- /* Convertire galleggiante da HostOrder alla rete Order */function FToN ($ val) { $ a = unpack ("I", pack ("f", $ val)); pacchetto di ritorno ("N", $ a [1]); } /* Convertire galleggiante dalla rete Ordine di HostOrder */ funzione NToF ($ val) { $ a = unpack ("N", $ val); $ b = scompattare ("f", pacchetto ("I", $ a [1])); return $ b [1]; } – strange

0

Questo finalmente ha funzionato per me.

$arr = unpack("H*", $devconts); 
$rawhex = trim(implode("", $arr)); 

$feedbackTime = hexdec(substr($rawhex, 0, 8)); 
$feedbackDate = date('Y-m-d H:i', $feedbackTime); 
$feedbackLen = hexdec(substr($rawhex, 8, 4)); 
$feedbackDeviceToken = substr($rawhex, 12, 64); 

E quindi si controlla semplicemente il token del dispositivo rispetto al timestamp!

+0

Funziona alla grande, gw1921. Sto memorizzando il $ feedbackDate in una colonna SQL per ora.Che tipo di dati dovrebbe essere la colonna? L'ho impostato su Integer e questo mi sta dando "2009". Le altre 2 colonne, lunghezza e gettone, funzionano GRANDE !! Grazie –

70

Ecco una grande Gotcha, che mi ha confuso quando ho provato prima il collegamento: i server di feedback APNS restituiscono solo i gettoni dei dispositivi che sono "scaduti" dalla tua ultima richiesta di un feedback. Il che significa che la maggior parte delle volte otterrai una risposta NULL a meno che tu non abbia già a che fare con un elevato volume di utenti della tua app.

Quindi assicurati di memorizzare i token del dispositivo scaduti su disco o db, perché dopo la tua query di feedback sono andati per sempre. Questo rende il test un dolore per non dire altro!

Ecco una funzione completa per recuperare i gettoni dispositivo dal server di retroazione APNS (molte grazie per le risposte di cui sopra per avermi aiutato a mettere tutto insieme):

function send_feedback_request() { 
    //connect to the APNS feedback servers 
    //make sure you're using the right dev/production server & cert combo! 
    $stream_context = stream_context_create(); 
    stream_context_set_option($stream_context, 'ssl', 'local_cert', '/path/to/my/cert.pem'); 
    $apns = stream_socket_client('ssl://feedback.push.apple.com:2196', $errcode, $errstr, 60, STREAM_CLIENT_CONNECT, $stream_context); 
    if(!$apns) { 
     echo "ERROR $errcode: $errstr\n"; 
     return; 
    } 


    $feedback_tokens = array(); 
    //and read the data on the connection: 
    while(!feof($apns)) { 
     $data = fread($apns, 38); 
     if(strlen($data)) { 
      $feedback_tokens[] = unpack("N1timestamp/n1length/H*devtoken", $data); 
     } 
    } 
    fclose($apns); 
    return $feedback_tokens; 
} 

Se tutto va bene, i valori restituiti da questa funzione sarà simile a questa (via print_r()):

Array 
(
    Array 
    (
     [timestamp] => 1266604759 
     [length] => 32 
     [devtoken] => abc1234..............etcetc 
    ), 
    Array 
    (
     [timestamp] => 1266604922 
     [length] => 32 
     [devtoken] => def56789..............etcetc 
    ), 
) 
+0

Grazie per questa elegante soluzione. Ora ho solo bisogno di sapere come confrontare il timestamp restituito dal suddetto codice di feedback al timestamp che ho salvato nel mio database, che ovviamente rappresenta l'ultima volta che il dispositivo mi ha inviato un token. Devo solo confrontare un numero intero diretto? O devo convertire i timestamp per correggere l'endianness o qualcosa del genere? –

+0

Questa risposta dovrebbe essere la soluzione accettata, IMO. Questo è fondamentalmente quello che sto facendo, e funziona perfettamente. Se ancora non visualizzi i dati di feedback con questo metodo, verifica di avere un'altra app sul dispositivo con push abilitata che riporta allo stesso ambiente aps dell'app disinstallata. Johnny - per quanto riguarda il timestamp, una volta estratto come nel post di Nick, puoi fare un confronto tra interi. – brack

+1

In tal caso, non ricevo una risposta dal server di feedback? Le mie notifiche vanno bene (come posso dire dai log) ma per qualche ragione non ricevo mai alcuna notifica sul dispositivo! – lostInTransit

Problemi correlati