Creazione di un'applicazione Web mobile con l'API di Google Reader

Questo tutorial ti insegnerà come creare un'applicazione web per lettori di feed di notizie mobile utilizzando l'API di Google Reader. Questa applicazione sarà molto "focalizzata sulle funzionalità", ma le basi che si apprendono qui dovrebbero essere sufficienti per espandersi nelle proprie app. Al momento della stesura di questo documento, non esiste un'API Google Reader ufficiale, quindi questo tutorial utilizzerà l'API non ufficiale comunemente utilizzata durante la creazione di applicazioni Google Reader.


Passaggio 1: concetti ed endpoint

concetti

Google utilizza un gergo leggermente diverso per alcune parti del backend dell'API di Google Reader. Alcune sono legate alla loro piattaforma e alcune sembrano dovute alla deriva mentre l'applicazione maturava sul front-end. Uno di questi concetti viene definito "flusso". Un flusso rappresenta il contenuto che viene tagliato e tagliato a dadini o filtrato in modi diversi. Tutti gli articoli di un feed specifico fanno parte di uno stream e così tutti gli articoli di una cartella.
Quella che segue è una breve tabella per mostrare le differenze nel gergo comune lato client e la corrispondente terminologia di backend dell'API di Google Reader:

Dalla parte del cliente API
Cartella / Tag Etichetta / Etichetta
Sottoscrizione Sottoscrizione
Persone che segui amico
Ha recitato Ha recitato
Condivisa Trasmissione

endpoint

Se hai effettuato l'accesso al tuo account Google Reader, prova ad inserire i seguenti endpoint nel tuo browser:

Informazioni utente:
https://www.google.com/reader/api/0/user-info?output=json

Elenco di abbonamenti:
https://www.google.com/reader/api/0/subscription/list?output=json

Elenco di cartelle / tag:
https://www.google.com/reader/api/0/tag/list?output=json

Elenco delle persone che segui:
https://www.google.com/reader/api/0/friend/list?output=json

Elenco delle preferenze di Google Reader:
https://www.google.com/reader/api/0/preference/stream/list?output=json

Gli endpoint di cui sopra sono di sola lettura e verranno utilizzati in questo tutorial.


Passaggio 2: creazione dell'interfaccia

Per accedere a Google Reader costruiremo una classe PHP personalizzata. Di seguito è riportato un elenco delle funzioni di cui avrà bisogno questa classe (ne approfondirò ciascuna in seguito):

Funzioni di classe

  • accesso - Ottiene il codice di autenticazione Google e il token di modifica del lettore.
  • get_subscriptions - Restituisce un elenco di feed sottoscritti.
  • get_tags - Restituisce un elenco di cartelle / tag.
  • get_friends - Restituisce una lista di persone che segui.
  • get_stream_items - Restituisce un articolo da un flusso.
  • set_article_read - Imposta un articolo come letto.
  • set_article_starred - Stars un articolo.
  • set_article_broadcast - Aggiunge un articolo al tuo elenco condiviso.
  • set_article_review - Applica il tag "recensione" a un articolo.
  • GET_URL - Richiesta GET HTTP con autenticazione Google.
  • get_anon_url - Richiesta GET HTTP senza autenticazione Google.
  • POST_URL - Richiesta POST HTTP con autenticazione Google.
  • post_anon_url - Richiesta POST HTTP senza autenticazione Google.

Proprietà

La nostra classe PHP userà un certo numero di proprietà differenti.

Come potresti essere in grado di indovinare, le seguenti proprietà verranno impostate sull'ID e sulla password dell'e-mail dell'account Google Reader:

 public $ grEmail = "; public $ grPasswd =";

Le seguenti proprietà sono utilizzate nelle funzioni Curl classe (controlla il codice sorgente per quelle):

 public $ userAgent = 'tuts + rss + bot'; pubblico $ proxy = 0; public $ proxyUrl = ";

Ho incluso il supporto proxy perché il mio hosting ISP (Godaddy) richiede il traffico in uscita per passare attraverso un proxy. Se non hai bisogno del supporto proxy mantieni $ proxy impostato su 0 in gr-config.php.

Successivamente, abbiamo molti degli endpoint iniziali per le API disponibili:

 protetto $ _urlBase = 'https://www.google.com'; protected $ _urlApi = 'https://www.google.com/reader/api/0'; protetto $ _urlAuth = 'https://www.google.com/accounts/ClientLogin'; protected $ _urlToken = 'https://www.google.com/reader/api/0/token'; protected $ _urlUserInfo = 'https://www.google.com/reader/api/0/user-info'; protected $ _urlTag = 'https://www.google.com/reader/api/0/tag'; protetto $ _urlSubscription = 'https://www.google.com/reader/api/0/subscription'; protected $ _urlStream = 'https://www.google.com/reader/api/0/stream'; protected $ _urlFriend = 'https://www.google.com/reader/api/0/friend';

Le seguenti tre informazioni sugli archivi delle proprietà raccolte durante il processo di autenticazione:

 public $ userInfo = "; protected $ auth ="; protected $ token = ";

Nella sezione dell'applicazione li imposterai in sessioni PHP, quindi non dobbiamo effettuare nuovamente il login con ogni richiesta.


Passo 3: sparare le funzioni di classe

Le seguenti funzioni eseguiranno il sollevamento per la nostra applicazione.

Funzione di accesso

Dobbiamo avviare l'API di autenticazione di Google per iniziare:

 $ data = '& Email ='. $ this-> grEmail. '& Passwd ='. $ this-> grPasswd. '& service = reader & source ='. $ this-> userAgent. '& continua = http: //www.google.com '; $ result = $ this-> post_anon_url ($ this -> _ urlAuth, $ data);

Dopo aver interrogato l'API di autenticazione, la prima cosa da raccogliere è la stringa $ auth. Questa stringa fornisce il livello di autenticazione di Google con le nostre credenziali. Ottenere il $ auth è utile per quasi tutti i servizi di Google.

 preg_match ('/ Auth = (\ S *) /', $ result, $ match); $ this-> auth = $ match [1];

Il prossimo è il token $ e avremo bisogno di colpire un altro endpoint per questo. Il token è specifico di Google Reader ed è richiesto per le richieste che scrivono o modificano lo stato.

 $ this-> token = $ this-> get_url ($ this -> _ urlToken);

Il terzo è un oggetto di informazione utente, avremo bisogno della porzione userId. Alcune delle opzioni API richiedono il tuo ID utente google, che è un numero elevato che rappresenta il tuo account e non l'ID e-mail che utilizzi per i login. Le informazioni utente contengono anche il numero elevato utilizzato per accedere al tuo feed condiviso.

 $ this-> userInfo = json_decode ($ this-> get_url ($ this -> _ urlUserInfo));

Elenco funzioni

Queste sono semplici funzioni per recuperare un elenco dei tuoi feed in vari modi.

get_subscriptions restituisce un elenco di ogni feed a cui ti sei abbonato:

 function get_subscriptions () $ result = $ this-> get_url ($ this -> _ urlSubscription. '/ list? output = json'); restituisce json_decode ($ result); 

get_tags restituisce un elenco di tutte le cartelle e tag:

 function get_tags () $ result = $ this-> get_url ($ this -> _ urlTag. '/ list? output = json'); restituisce json_decode ($ result); 

get_friends restituisce un elenco delle persone che segui:

 function get_friends () $ result = $ this-> get_url ($ this -> _ urlFriend. '/ list? output = json'); restituisce json_decode ($ result); 

Funzione degli oggetti

Questa è la carne della classe e ciò a cui tutto il resto porta. Con questa funzione restituiamo i singoli articoli in base ai criteri specificati. Il $ flusso viene estratto dai risultati delle funzioni di elenco e potrebbe essere un feed di un amico, un'intera cartella o un feed specifico. $ n è il numero di articoli da restituire contemporaneamente. Per l'app l'ho limitato a solo 20, ma se lo riutilizzi per qualcosa di diverso dalla visualizzazione in tempo reale puoi aumentarlo fino a 1000. Dopo il 1000 devi usare l'opzione di continuazione, che è fuori dallo scopo per questo articolo.

get_stream_items accetta un numero di parametri e con i valori predefiniti hai solo bisogno di fornirgli un flusso:

 function get_stream_items ($ stream = ", $ xt_a = array ('utente / - / stato / com.google / leggi'), $ daysago = 3, $ n = 20, $ magic = True) 

$ ot è usato per dire a Google Reader che non vuoi restituire articoli più vecchi questa volta. Google Reader passa di epoca, ma mi piace usare $ DAYSAGO perché è solo più semplice andare per giorni anziché per secondi. Da quello, possiamo calcolare $ ot dall'ora corrente. $ ck è importante, ma non ho mai ricevuto una buona spiegazione a riguardo, e senza un'API ufficiale di Google Reader potrebbe rimanere un mistero. L'ho impostato su time () * 1000 e funziona, mentre time () * 100 no.

 $ ot = time () - ($ daysago * 86400); $ ck = time () * 1000;

$ magia è un booleano che restituisce gli articoli utilizzando la classifica "magica" di Google Reader o, se è falso, la più recente. Puoi anche ordinare prima il più vecchio impostando $ r = 'o' se lo desideri.

 if ($ magic == True) $ r = 'a';  else $ r = 'n'; 

$ xt_a viene utilizzato per escludere articoli di un feed in base a determinati metadati relativi allo stato dell'articolo. Di default la funzione restituisce solo messaggi non letti perché esclude gli articoli contrassegnati come letti.

 $ xt = "; foreach ($ xt_a come $ chiave => valore $) $ xt. = '& xt ='. $ valore;

Passiamo l'URL finale a Google Reader e restituiamo i risultati dopo aver impostato i parametri:

 $ url = $ this -> _ urlStream. '/ contents /'.stream stream.'? ot = '. $ ot.' & r = '. $ r. $ xt.' & n = '. $ n.' & ck = ' . $ ck '& client =' $ this-> userAgent..; $ result = $ this-> get_url ($ url); restituisce json_decode ($ result); 

Imposta funzione

Tre di queste funzioni sono utilizzate per riscrivere Google Reader e contrassegnare gli articoli con un determinato stato. L'ultimo è usato per impostare un tag. Potresti facilmente condensare tutti e quattro in una singola funzione e passare "a =" come parametro di funzione. Questa configurazione è solo una mia preferenza, preferisco così così il codice che usa la classe è più pulito e più facile da leggere. Se hai intenzione di creare una tua funzione, puoi inviare più "a =" alla volta. Inoltre, puoi passare più opzioni "i =" e "s =", devi solo passare una quantità uguale e nell'ordine corretto. Generalmente passo 10 alla volta quando segnano molti articoli come letti.

Imposta l'articolo sullo stato "leggi":

 funzione set_article_read ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ This-> userAgent; $ data = 'a = utente / - / stato / com.google / read & async = true & s ='. $ stream. '& i ='. $ id. '& T ='. $ this-> token; restituire $ this-> post_url ($ url, $ data); 

Star l'articolo:

 function set_article_starred ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ This-> userAgent; $ data = 'a = utente / - / stato / com.google / starred & async = true & s ='. $ stream. '& i ='. $ id. '& T ='. $ this-> token; restituire $ this-> post_url ($ url, $ data); 

Condividi l'articolo con chi ti segue:

 funzione set_article_broadcast ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ This-> userAgent; $ data = 'a = utente / - / stato / com.google / broadcast & async = true & s ='. $ stream. '& i ='. $ id. '& T ='. $ this-> token; restituire $ this-> post_url ($ url, $ data); 

Quest'ultimo applica un tag di revisione:

 function set_article_review ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ This-> userAgent; $ data = 'a = utente /' .$ this-> userInfo-> userId. '/ label / Review & async = true & s ='. $ stream. '& i ='. $ id. '& T ='. $ this-> token ; restituire $ this-> post_url ($ url, $ data); 

Quanto sopra deve essere utilizzato nell'app in modo da poter contrassegnare qualcosa da rivedere quando si utilizza un browser normale.


Passaggio 4: sull'applicazione

L'interfaccia dell'applicazione è costruita sulla base dell'ottimo standard HTML5 di http://html5boilerplate.com/. Ho preso l'index.php dal boilerplate e l'ho diviso in file header e footer include. La pagina principale è index.php e accetterà un &elenco valore di querystring che indica quale elenco visualizzare. Per impostazione predefinita l'elenco delle cartelle. Qualsiasi elemento nella lista andrà a articles.php con il & Stream e &elenco passato. La classe è inserita in un file gr.php con gr-config.php che in realtà è il file che lo include negli altri. Potrebbe essere ovvio, ma in gr-config.php inseriremo anche le opzioni di configurazione per la classe. L'ultimo file php è set_article.php. Verrà chiamato con una richiesta AJAX da articles.php ed è responsabile della chiamata alle funzioni impostate.

Ho incluso i due tag qui sotto nel file di inclusione header.php ma sono commentati:

  

Rendono l'app Web più simile a un'app normale quando aggiungi il sito alla schermata iniziale di iOS. apple-touch-startup-immagine fornisce un'immagine da visualizzare mentre viene caricata la pagina principale. apple-mobile-web-app-capable rende il sito eseguito sulla propria istanza di Safari piuttosto che nell'istanza generale di Safari. L'unica cosa problematica è che con apple-mobile-web-app-capable impostato su Sì, facendo clic su un collegamento a un dominio diverso apre il collegamento nell'istanza principale di Safari, forzando quindi il multitasking all'app di lettura.


Passaggio 5: creazione della pagina principale

Per questa applicazione costruiremo una pagina principale che visualizzerà una lista di entrambi Cartelle (predefinito), Amici o Sottoscrizioni.

Immagine dello schermo

Il set up

Ecco la configurazione all'inizio delle pagine index.php, articles.php e set_article.php:

 session_set_cookie_params (300); session_start (); include_once ( 'gr-config.php'); include_once ( 'header.php');

Il menu

Il menu è un semplice elenco HTML che può essere utilizzato per recuperare i diversi elenchi di iscrizioni:

 

Il menu usa uno sprite per i pulsanti basato sul simpatico set di icone Glyphish.

Il codice

Ora al primo vero uso della classe. Fondamentalmente, stiamo andando a verificare se &elenco è impostato e, in caso contrario, il valore predefinito è la visualizzazione dei tag. Quindi è solo un'istruzione switch per sapere quale lista costruire e la funzione gr da usare.

Per prima cosa, abbiamo l'impostazione predefinita $ lista per tag se non viene passato nulla e quindi passare $ lista a un interruttore. quando $ lista corrisponde ai sottotitoli, abbiamo appena prodotto un elenco abbastanza semplice di tutti gli abbonamenti restituiti. Questo può essere molto per gli utenti pesanti ed è per questo che la modalità tag è l'impostazione predefinita.

 if (isset ($ _ GET ['list'])) $ list = $ _GET ['list'];  else $ list = 'tags';  switch ($ list) case 'subs': $ subs = $ gr-> get_subscriptions (); foreach ($ subs-> subscriptions as $ sub) echo '
  • '$ sub> titolo,'
  • '; rompere;

    I dati tornano con la stringa etichetta completa piuttosto che solo il nome della cartella. L'impostazione $ remove ci consentirà di eliminare le parti non necessarie della stringa di etichette e di mostrare solo il nome della cartella. Sfortunatamente, non c'è modo di escludere Review dalle etichette restituite, quindi ho dovuto gestirlo con PHP. Verifico anche che vengano visualizzate solo le etichette:

     case 'tags': $ tags = $ gr-> get_tags (); $ remove = 'user /'.$ gr-> userInfo-> userId.' / label / '; foreach ($ tag-> tag come $ tag) if (strpos ($ tag-> id, '/ label /')> 0 && strpos ($ tag-> id, '/ Review') == 0) $ title = str_replace ($ remove, ", $ tag-> id); echo '
  • '$ titolo,'
  • '; rompere;

    L'URL degli amici ha però molte informazioni aggiuntive dal profilo dell'utente. Una cosa carina che possiamo usare è l'immagine del profilo e includerla come immagine a 32 pixel:

     case "amici": $ friends = $ gr-> get_friends (); foreach ($ friends-> amici come $ friend) if ($ friend-> contactId! = -1) echo '
  • ', $ amico-> displayName,'
  • '; rompere;

    Passaggio 6: creazione della pagina dell'articolo

    Questa pagina ti consente di visualizzare gli articoli, contrassegnarli come letti, impostarli per essere esaminati in seguito, contrassegnarli come preferiti o condividerli con i tuoi amici.

    Immagine dello schermo

    Il set up

    Come la pagina principale.

    Il menu

    Un altro semplice elenco HTML. Non sono un fan dell'uso di window.history per un pulsante indietro, quindi per il retro li sto mandando di nuovo alla lista che stavano visualizzando.

     

    Il codice

    Il get_stream_items la funzione della nostra classe è il driver principale per la pagina e la maggior parte dei valori predefiniti è buona per questo. Di default esclude gli elementi contrassegnati come letti ma ho esteso il $ xt_a array per escludere anche gli articoli contrassegnati con l'etichetta / tag "recensione". In questo modo gli elementi che contrassegniamo per la revisione non vengono mai visualizzati in questo elenco, anche se non li abbiamo ancora letti. Stiamo per caricare gli articoli in nascosto div tag e mostra solo il :Primogenito, quindi manipola gli altri tramite JavaScript.

     $ stream = $ _GET ['stream']; $ articoli = $ gr-> get_stream_items ($ stream, array ('utente / - / stato / com.google / leggi', 'utente /'.grondi gr-> userInfo-> userId.' / label / Review '))) ; if (count ($ articles-> items)> 0) foreach ($ articles-> items as $ article) 

    Invece di provare a mantenere lo stato in una sessione o in un array in JavaScript, sto semplicemente utilizzando le parti di dati rilavanti come attributi sul div wrapper di ogni articolo.

     eco '
    '; echo'
    si alternano [0] -> href, '">', $ article-> titolo, '
    ';

    Il contenuto può tornare in forma di sintesi o meno a seconda del feed. Dal momento che siamo mobili tenteremo di fare un riepilogo, ma torneremo al contenuto completo se non è disponibile. Inoltre inseriremo i link nell'articolo in una nuova finestra.

     if (isset ($ article-> summary-> content)) $ content = str_replace ('href =', 'target = "_ blank" href = ", $ article-> summary-> content); else $ content = str_replace ("href = ',' target =" _ blank "href = ', $ article-> content-> content); 

    Infine, mostra ciò che abbiamo:

     eco '
    '$ Content,'
    '; eco '
    ';

    Passaggio 7: JavaScript per le azioni di articolo

    Il JavaScript è fortemente dipendente da jQuery. Il menu article.php chiama set_article () quando fai clic su un'azione e chiama set_article.php per elaborare quell'azione. set_article () prima catturerò l'id e lo stream dall'articolo che stiamo visualizzando div etichetta. Afferrerà quindi il totale per sparare una ricarica se raggiungiamo la fine degli articoli disponibili. Lo script set_article.php restituirà un 1 se l'azione eseguita dovrebbe passare all'articolo successivo. Altrimenti, controlla l'azione eseguita e accende la stella o l'icona Condividi. Sta usando $ .Eq () e la variabile fetta per elencare attraverso gli articoli restituiti.

    Ambientazione totale variabile dinamicamente piuttosto che solo usando '20':

     var total = $ ('. article'). size (); function set_article (action) 

    Aggiunta di attributi al wrapper dell'articolo div etichetta:

     id = $ ('. article'). eq (slice) .attr ('id'); stream = $ ('. article'). eq (slice) .attr ('stream');

    Qui passiamo id e stream alla pagina set_article.php e prendiamo un 1 o 0. L'1 significa che l'azione richiede la rimozione dell'articolo dalla vista e lo 0 significa che questo è solo un cambiamento di stato.

     $ .get ('/ set_article.php? action =' + action + '& id =' + id + '& stream =' + stream, function (data) if (data == "1") $ ('. article') .eq (slice) .hide (); slice + = 1; $ ('. article'). eq (slice) .show (); $ ('. starred'). css (backgroundPosition: '-62px -31px '); $ ('. broadcast '). css (backgroundPosition:' -93px -31px '); else 

    Se restituisce uno 0, allora dobbiamo vedere quale azione è stata presa in modo che anche il corretto stato dell'icona sia cambiato:

     if (action == 'starred') $ ('. starred'). css (backgroundPosition: '-62px 0px');  else $ ('. broadcast'). css (backgroundPosition: '-93px 0px');  if (slice> = total) window.location.reload (true); ); 

    Passaggio 8: Applicazione delle azioni agli articoli

    Questo è l'ultimo bit di PHP che ci permetterà di manipolare l'articolo.

    Il set up

    Come la pagina principale.

    Il codice

    Il duro lavoro è fatto in classe, quindi questa pagina è in realtà solo un passaggio per eseguire la funzione di classe che corrisponde all'azione. Potresti chiederti perché Google richiede il $ flusso variabile. Da quello che posso dire, tutto ha a che fare con il modo in cui Google memorizza tutti i dati del lettore e riduce i tempi di transazione durante l'elaborazione di queste funzioni di modifica.

     if (isset ($ _ GET ['action'])) $ action = $ _GET ['action']; $ id = $ _GET ['id']; $ stream = $ _GET ['stream']; switch ($ action) case 'read': $ r = $ gr-> set_article_read ($ id, $ stream); echo '1'; rompere; case 'stellato': $ r = $ gr-> set_article_starred ($ id, $ stream); echo '0'; rompere; case 'broadcast': $ r = $ gr-> set_article_broadcast ($ id, $ stream); echo '0'; rompere; caso 'recensione': $ r = $ gr-> set_article_review ($ id, $ stream); echo '1'; rompere; 

    Passo 9: Arrotondalo con i CSS

    La maggior parte dei CSS non è nulla di troppo speciale. Ho i due stili chiave inclusi di seguito:

     .immagine-riassunto img, .article-summary embed altezza massima: 50%; max-width: 50%;  .article: first-child display: block; 

    Il max-height: 50% e max-width: 50% le dichiarazioni sono molto utili quando si ripropone l'HTML che può contenere immagini e incorporarle. Mantiene le immagini e include anche youtube da sovraccaricare lo schermo mobile.


    Passaggio 10: ulteriori informazioni

    Finché non ci sarà un'API ufficiale, questi luoghi sono ottimi per ottenere ulteriori informazioni sulla creazione di app con Google Reader:

    • Amici dell'API di Google Reader non ufficiale: un gruppo di discussione con molte informazioni e persone straordinarie.
    • Niall Kennedy: uno dei primi a fare casino con l'API.
    • Stack Overflow: domande contrassegnate con google-reader-api (ho iniziato a rispondere ad alcune di esse).
    • pyrfeed: il wiki per questa classe python ha molte informazioni.
    • Martin Doms: ben fatto abbattere gli URL utilizzati nell'API.