Bygg en mobil webapplikasjon med Google Reader API

Denne opplæringen vil lære deg hvordan du bygger en mobilnyhetsmateleser-webapplikasjon ved hjelp av Google Reader API. Denne applikasjonen vil være veldig "funksjonsfokusert", men grunnlaget du lærer her, bør være nok til at du kan ekspandere i dine egne apper. Fra tidspunktet for denne skrivingen er det ikke en offisiell Google Reader API, så denne opplæringen vil gjøre bruk av den uoffisielle API som vanligvis brukes når du bygger Google Reader-programmer.


Trinn 1: Begrep og sluttpunkter

Begreper

Google bruker litt forskjellig lingo for noen av backend-delene av Google Reader API. Noen av det er knyttet til plattformen, og noen ser ut til å skyldes drift som applikasjonen modnes på fronten. Et slikt konsept er referert til som en "strøm". En strøm representerer innhold som er skåret og blokkert eller filtrert på forskjellige måter. Alle artiklene fra en bestemt feed er en del av en strøm, og så er alle artiklene fra en mappe.
Følgende er et korttabell for å vise forskjeller i vanlig kundeside lingo og tilhørende Google Reader API-backend-terminologi:

Klient side API
Mappe / tag Tag / Etikett
Abonnement Abonnement
Folk du følger venn
stjernet stjernet
delt Kringkaste

endepunkter

Hvis du er logget inn på Google Reader-kontoen din, kan du prøve å skrive inn følgende endepunkter i nettleseren din:

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

Liste over abonnementer:
https://www.google.com/reader/api/0/subscription/list?output=json

Liste over mapper / tagger:
https://www.google.com/reader/api/0/tag/list?output=json

Liste over personer du følger:
https://www.google.com/reader/api/0/friend/list?output=json

Liste over innstillinger for Google Leser:
https://www.google.com/reader/api/0/preference/stream/list?output=json

Ovennevnte sluttpunkter er skrivebeskyttet og vil bli brukt i hele denne opplæringen.


Trinn 2: Bygg grensesnittet

For å få tilgang til Google Reader, vil vi bygge en egendefinert PHP-klasse. Nedenfor er en liste over funksjonene denne klassen trenger (jeg går inn i hver mer dybde senere):

Klassefunksjoner

  • Logg Inn - Får Google auth kode og leser rediger token.
  • get_subscriptions - Returnerer en liste over abonnerte feeder.
  • get_tags - Returnerer en liste over mapper / tagger.
  • get_friends - Returnerer en liste over personer du følger.
  • get_stream_items - Returnerer en artikkel fra en strøm.
  • set_article_read - Angir en artikkel som lest.
  • set_article_starred - Stjerner en artikkel.
  • set_article_broadcast - Legger til en artikkel i din delte liste.
  • set_article_review - Gjelder taggen "anmeldelse" til en artikkel.
  • GET_URL - HTTP GET-forespørsel med Google-godkjenning.
  • get_anon_url - HTTP GET-forespørsel uten Google-godkjenning.
  • POST_URL - HTTP POST-forespørsel med Google-godkjenning.
  • post_anon_url - HTTP POST-forespørsel uten Google-godkjenning.

Eiendommer

Vår PHP-klasse vil bruke en rekke forskjellige egenskaper.

Som du kanskje kan gjette, blir følgende egenskaper satt til Google Reader-kontoens e-post-ID og passord:

 offentlig $ grEmail = "; offentlig $ grPasswd =";

Følgende egenskaper brukes i klassen Curl-funksjoner (sjekk kildekoden for disse):

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

Jeg har inkludert proxy-støtte fordi min hosting-leverandør (Godaddy) krever utgående trafikk for å passere gjennom en proxy. Hvis du ikke trenger proxy-støtte, hold $ proxy satt til 0 i gr-config.php.

Deretter har vi mange av begynnelsespunktene for API-er tilgjengelige:

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

De neste tre egenskapene lagrer informasjon samlet under godkjenningsprosessen:

 offentlig $ userInfo = "; beskyttet $ auth ="; beskyttet $ token = ";

I applikasjonsdelen setter vi disse til PHP-økter, slik at vi ikke trenger å logge på igjen med hver forespørsel.


Trinn 3: Fleshing ut klassens funksjoner

Følgende funksjoner vil gjøre tungløftingen for vår applikasjon.

Innloggingsfunksjon

Vi må treffe Google Autentiserings API for å starte:

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

Etter å ha søkt autentiserings-API-en, er den første tingen å samle $ auth-strengen. Denne strengen forsyner Googles autentiseringslag med våre legitimasjonsbeskrivelser. Komme til $ auth er nyttig for nesten alle Google-tjenester.

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

Neste er $ token og vi må treffe et annet sluttpunkt for det. Token er spesifikk for Google Reader og kreves for forespørsler som skriver eller endrer tilstand.

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

Den tredje er et brukerinformasjonsobjekt, vi trenger bruker-delen. Noen av API-alternativene krever google userId, som er et stort tall som representerer kontoen din, og ikke e-post-IDen du bruker til pålogginger. Brukerinformasjonen inneholder også det store nummeret som brukes til å få tilgang til delt feed.

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

Liste Funksjoner

Dette er enkle funksjoner for å hente en liste over feeds på ulike måter.

get_subscriptions returnerer en liste over hver feed du har abonnert på:

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

get_tags returnerer en liste over alle mappene og kodene:

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

get_friends returnerer en liste over personene du følger:

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

Elementer Funksjon

Dette er kjøttet i klassen og hva alt annet fører til. Med denne funksjonen returnerer vi de enkelte artikler basert på de angitte kriteriene. De $ strøm trekkes fra resultatene av listefunksjonene, og det kan være en feed fra en venn, en hel mappe eller en bestemt feed. $ n er antall artikler å returnere på en gang. For appen har jeg begrenset det til bare 20, men hvis du bruker dette til noe annet enn sanntidsvisning, kan du støte det opp til 1000. Etter 1000 må du bruke fortsettingsalternativet, som ikke er tilgjengelig for dette artikkel.

get_stream_items aksepterer en rekke parametere, og med standardinnstillingene trenger du bare å gi den en strøm:

 funksjon get_stream_items ($ stream = ", $ xt_a = array ('bruker / - / state / com.google / read'), $ daysago = 3, $ n = 20, $ magi = True) 

$ ot er vant til å fortelle Google Reader du ikke vil returnere noen artikler eldre dem denne gangen. Google Reader går etter epok tid, men jeg liker å bruke $ DAYSAGO fordi det er bare lettere å gå i dager i stedet for sekunder. Fra det kan vi beregne $ ot fra nåværende tid. $ ck er viktig, men jeg har aldri fått en god forklaring om det, og uten et offisielt Google Reader-API kan det forbli et mysterium. Jeg har satt det til tid () * 1000 og det virker bare, mens tiden () * 100 ikke gjør det.

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

$ magi er en boolsk til å returnere artiklene ved hjelp av Google Reader "magisk" rangering, eller, hvis falsk, av den nyeste først. Du kan også sortere etter eldste først ved å sette $ r = 'o' hvis du vil.

 hvis ($ magic == True) $ r = 'a';  ellers $ r = 'n'; 

$ xt_a brukes til å ekskludere artikler av en feed basert på visse metadata relatert til artikkelenes tilstand. Som standard returnerer funksjonen ikke uleste innlegg fordi det utelukker artikler som er merket som lest.

 $ xt = "; foreach ($ xt_a som $ key => $ verdi) $ xt. = '& xt ='. $ verdi;

Vi sender den endelige nettadressen til Google Reader og returnerer resultatene etter at parametrene er angitt:

 $ url = $ dette -> _ urlStream. '/ innhold /'.$ stream.'? ot = '. $ ot.' & r = '. $ r. $ xt.' & n = '. $ n.' & ck = ' . $ ck '& client =' $ dette-> brukeragent..; $ result = $ this-> get_url ($ url); return json_decode ($ resultat); 

Sett funksjon

Tre av disse funksjonene brukes til å skrive tilbake til Google Reader og merke artikler med en bestemt stat. Den siste brukes til å sette en tagg. Du kan enkelt kondensere alle fire ned til en enkelt funksjon og passere "a =" som en funksjonsparameter. Denne oppsettet er bare min preferanse, jeg foretrekker det på denne måten, så koden som bruker klassen er renere og enklere å lese. Hvis du planlegger å lage din egen funksjon, kan du sende inn flere "a =" om gangen. Du kan også passere flere "i =" og "s =" alternativer, du må bare passere like mye og i riktig rekkefølge. Jeg sender vanligvis 10 om gangen når du merker mange elementer som lest.

Sett artikkelen til "les" -tilstanden:

 funksjon set_article_read ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ Dette-> useragent; $ data = 'a = bruker / - / state / com.google / read & async = true & s ='. $ stream. '& i ='. $ id. '& T ='. $ this-> token; returnere $ this-> post_url ($ url, $ data); 

Stjær artikkelen:

 funksjon set_article_starred ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ Dette-> useragent; $ data = 'a = bruker / - / state / com.google / starred & async = true & s ='. $ stream. '& i ='. $ id. '& T ='. $ this-> token; returnere $ this-> post_url ($ url, $ data); 

Del artikkelen med de som følger deg:

 funksjon set_article_broadcast ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ Dette-> useragent; $ data = 'a = bruker / - / state / com.google / broadcast & async = true & s ='. $ stream. '& i ='. $ id. '& T ='. $ this-> token; returnere $ this-> post_url ($ url, $ data); 

Denne siste gjelder en anmeldelse tagg:

 funksjon set_article_review ($ id, $ stream) $ url = $ dette -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ Dette-> useragent; $ data = 'a = user /'.$ this-> userInfo-> userId.' / label / Review & async = sant & s = '. $ stream.' & i = '. $ id.' & T = '. $ this-> token ; returnere $ this-> post_url ($ url, $ data); 

Ovennevnte bør brukes i appen, slik at du kan markere noe å se gjennom når du bruker en vanlig nettleser.


Trinn 4: Til på applikasjonen

Programgrensesnittet er bygd på bunnen av den utmerkede HTML5-kjeleplaten på http://html5boilerplate.com/. Jeg tok index.php fra kjeleplaten og splitt den i header og footer inkluderer filer. Hovedsiden er index.php og vil akseptere en &liste querystring-verdi som angir hvilken liste som skal vises. Den er standard til mappelisten. Ethvert element i listen vil gå til articles.php med &strøm og &liste passert. Klassen er plassert i en fil gr.php med gr-config.php som faktisk er filen som inneholder den til de andre. Det kan være åpenbart, men i gr-config.php vil vi også sette inn konfigureringsalternativene for klassen. Den siste php-filen er set_article.php. Det vil bli kalt med en AJAX-forespørsel fra articles.php og er ansvarlig for å ringe til de angitte funksjonene.

Jeg har tatt med de to kodene under i header.php, inkludert fil, men de kommenteres:

  

De gjør webappefunksjonen mer som en vanlig app når du legger til nettstedet på IOS-hjemmeskjermen. eple-touch-oppstart-bilde Gir et bilde som skal vises mens hovedsiden lastes inn. eple-mobile-web-app-stand gjør nettstedet kjørt på egen Safari-forekomst, heller enn i det generelle Safari-forekomsten. Den eneste problematiske tingen er det med eple-mobile-web-app-stand sett til ja, klikker du på en lenke til et annet domene, åpnes lenken i hovedalternativet Safari, og tvinger deg til multitask tilbake til leserappen.


Trinn 5: Bygg hovedsiden

For denne applikasjonen skal vi bygge en hovedside som vil vise en liste over heller Mapper (standard), Venner eller abonnementer.

Skjermbilde

Oppsettet

Her er oppsettet på begynnelsen av index.php, articles.php og set_article.php sider:

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

Menyen

Menyen er en enkel HTML-liste som kan brukes til å hente de forskjellige abonnementslistene:

 

Menyen bruker en sprite for knappene basert på det fine ikonet Glyphish.

Koden

Nå videre til den første virkelige bruken av klassen. I utgangspunktet skal vi sjekke om &liste er satt og, hvis ikke, standard til merkervisning. Da er det bare en bryteretning å vite hvilken liste å bygge og gr funksjon å bruke.

Først er vi standard $ liste til koder hvis ingenting er bestått og deretter passere $ liste til en bryter. Når $ liste matcher subs vi utfører bare en ganske rett liste over alle abonnementene som returneres. Dette kan være mye for tunge brukere, og derfor er taggermodus standard.

 hvis (isset ($ _ GET ['list'])) $ list = $ _GET ['liste'];  else $ list = 'tags';  bytte ($ list) case 'subs': $ subs = $ gr-> get_subscriptions (); foreach ($ subs-> abonnementer som $ sub) echo '
  • '$ sub-> tittelen'
  • '; gå i stykker;

    Dataene kommer tilbake med den fulle etikettstrengen heller enn bare mappenavnet. Ved å sette opp $ remove vil vi bli kvitt de unødvendige delene av etikettstrengen og bare vise mappenavnet. Dessverre er det ikke mulig å ekskludere gjennomgang fra etikettene returnert, så jeg måtte håndtere det med PHP. Jeg sjekker også for at vi bare viser etiketter:

     case 'tags': $ tags = $ gr-> get_tags (); $ remove = 'user /'.$ gr-> userInfo-> userId.' / label / '; foreach ($ tags-> tagger som $ tag) if (strpos ($ tag-> id, '/ label /')> 0 && strpos ($ tag-> id, '/ Review') == 0) $ title = str_replace ($ remove, ", $ tag-> id); ekko '
  • '$ tittel,'
  • '; gå i stykker;

    Vennens nettadresse har imidlertid mye mer informasjon fra brukerens profil. En fin ting vi kan bruke, er profilbildet og inkluderer det som et 32 ​​piksler bilde:

     sak 'venner': $ friends = $ gr-> get_friends (); foreach ($ friends-> venner som $ venn) if ($ friend-> contactId! = -1) echo '
  • ', $ venn-> display,'
  • '; gå i stykker;

    Trinn 6: Bygg artikkelen

    Denne siden er hvor du vil se artiklene, merk dem lese, sette dem til å bli vurdert senere, merk dem som favoritt, eller del dem med vennene dine.

    Skjermbilde

    Oppsettet

    Samme som hovedsiden.

    Menyen

    En annen enkel HTML-liste. Jeg er ikke en fan av å bruke window.history for en tilbakeknapp, så for baksiden sender jeg dem tilbake til listen de så på.

     

    Koden

    De get_stream_items funksjon fra vår klasse er den primære driveren for siden, og de fleste av standardene er gode for dette. Som standard utelukkes elementer som er merket som lest, men jeg har utvidet $ xt_a array for å ekskludere artikler som er merket med "review" label / tag. På denne måten ser vi elementer som vi markerer for gjennomgang aldri opp på denne listen, selv om vi ikke har lest dem enda. Vi skal laste opp artiklene i skjult div koder og bare vise :første barn, Deretter manipulere de andre via JavaScript.

     $ stream = $ _GET ['stream']; $ articles = $ gr-> get_stream_items ($ stream, array ('bruker / - / state / com.google / read', 'user /'.$ gr-> userInfo-> userId.' / label / Review ')) ; hvis (count ($ articles-> items)> 0) foreach ($ articles-> elementer som $ artikkel) 

    I stedet for å prøve å holde tilstand i en økt eller en matrise i JavaScript, bruker jeg bare de relavante dataene som attributter på hver artikkel er wrapper div.

     ekko '
    '; echo'
    alternativt [0] -> href, '">', $ artikkelen-> tittel, '
    ';

    Innholdet kan komme tilbake i sammendrag eller ikke, avhengig av feedet. Siden vi er mobile, prøver vi sammendrag, men faller tilbake til hele innholdet hvis det ikke er tilgjengelig. Vi vil også gjøre koblingene i artikkelen pop i et nytt vindu.

     hvis isset ($ article-> summary-> innhold)) $ content = str_replace ('href =', 'target = "_ blank" href = ", $ artikkel-> oppsummering-> innhold); annet $ innhold = str_replace ("href = ',' target =" _ blank "href = ', $ artikkel-> innhold-> innhold); 

    Til slutt, vis hva vi har:

     ekko '
    '$ Innhold,'
    '; ekko '
    ';

    Trinn 7: JavaScript for artikkelhandlinger

    JavaScript er sterkt avhengig av jQuery. Artikkelen.php-menyen samtaler set_article () når du klikker på en handling og ringer set_article.php for å behandle den handlingen. set_article () Vil først fange id og strøm fra artikkelen vi ser på div stikkord. Det vil da ta tak i summen for å avfalle en oppdatering hvis vi treffer slutten av de tilgjengelige artiklene. Set_article.php-skriptet returnerer en 1 hvis handlingen skal utføres til neste artikkel. Ellers kontrollerer den handlingen som utføres, og enten lyser stjernen eller delikonet. Det bruker $ .Eq () og variabelen skjære å oppregne gjennom de returnerte artiklene.

    Innstilling Total variabel dynamisk heller enn bare å bruke '20':

     var totalt = $ ('.artikkel'). størrelse (); funksjon set_article (handling) 

    Legge til attributter til artikkelomslaget div stikkord:

     id = $ ('artikkel'). eq (skive) .attr ('id'); stream = $ ('artikkel'). eq (skive) .attr ('stream');

    Her sender vi id og strøm til set_article.php siden og får tilbake en 1 eller 0. Den 1 betyr at handlingen krever fjerning av artikkelen fra visning og 0 betyr at dette bare er en tilstandsendring.

     $ .get ('/ set_article.php? action =' + action + '& id =' + id + '& stream =' + stream, funksjon (data) if (data == "1") $ ('artikkel') .qq (skive) .hide (); skive + = 1; $ ('artikkel'). eq (skive) .show (); $ ('.stjernet'). css (backgroundPosition: '-62px -31px '); $ ('. broadcast '). css (backgroundPosition:' -93px -31px '); else 

    Hvis det returnerer en 0, må vi se hvilken handling som ble tatt, slik at den riktige ikonstatusen også blir byttet:

     if (action == 'starred') $ ('. starred'). css (backgroundPosition: '-62px 0px');  ellers $ ('. broadcast'). css (backgroundPosition: '-93px 0px');  hvis (skive> = totalt) window.location.reload (true); ); 

    Trinn 8: Bruk av handlinger til artikler

    Dette er den endelige biten av PHP som vil tillate oss å manipulere artikkelen.

    Oppsettet

    Samme som hovedsiden.

    Koden

    Det harde arbeidet er gjort i klassen, så denne siden er egentlig bare en bryter for å kjøre klassefunksjonen som samsvarer med handlingen. Du lurer kanskje på hvorfor Google krever $ strøm variabel. Fra det jeg kan fortelle, har alt å gjøre med hvordan Google lagrer alle leserdataene og kutter transaksjonstiden når du behandler disse redigeringsfunksjonene.

     hvis (isset ($ _ GET ['action'])) $ action = $ _GET ['action']; $ id = $ _GET ['id']; $ stream = $ _GET ['stream']; bytte ($ action) case 'read': $ r = $ gr-> set_article_read ($ id, $ stream); ekko '1'; gå i stykker; case 'starred': $ r = $ gr-> set_article_starred ($ id, $ stream); ekko '0'; gå i stykker; case 'broadcast': $ r = $ gr-> set_article_broadcast ($ id, $ stream); ekko '0'; gå i stykker; case 'review': $ r = $ gr-> set_article_review ($ id, $ stream); ekko '1'; gå i stykker; 

    Trinn 9: Avrund det med CSS

    De fleste av CSS er ikke noe spesielt. Jeg har de to sentrale stilene inkludert nedenfor:

     .artikkel-sammendrag img, .article-summary embed maks-høyde: 50%; en maksimal bredde på: 50%;  .artikkel: første barn display: block; 

    De max-høyde: 50% og en maksimal bredde på 50% erklæringer er svært nyttige når du repurposing HTML som kan ha bilder og embeds. Det holder bildene og youtube inkluderer fra overbelastning av mobilskjermen.


    Trinn 10: Lær mer

    Inntil det er en offisiell API, er disse stedene bra for å få litt mer informasjon om å bygge apper med Google Reader:

    • Venner av det uoffisielle Google Reader-API: En diskusjonsgruppe med massevis av god info og folk.
    • Niall Kennedy: En av de første til å rote med API.
    • Stack Overflow: Spørsmål merket med google-leser-api (jeg har begynt å svare på noen av dem).
    • pyrfeed: Wiki for denne python-klassen har mye info.
    • Martin Doms: Godt gjort bryte ned av nettadressene som brukes i API.