Een mobiele webtoepassing bouwen met de Google Reader API

In deze zelfstudie leert u hoe u een mobiele webtoepassing voor nieuwsfeedreaderingen maakt met behulp van de Google Reader API. Deze applicatie zal zeer "gericht op functies" zijn, maar de basis die u hier leert zou voldoende moeten zijn om uit te breiden in uw eigen apps. Vanaf het moment van schrijven is er geen officiële Google Reader API, dus deze tutorial zal gebruik maken van de onofficiële API die gewoonlijk wordt gebruikt bij het bouwen van Google Reader-applicaties.


Stap 1: Concepten en eindpunten

Concepts

Google gebruikt een iets ander jargon voor een aantal van de backend delen van de Google Reader API. Een deel ervan is gekoppeld aan hun platform en sommige lijken te wijten te zijn aan afwijkingen als de applicatie aan de voorkant is uitgerijpt. Eén zo'n concept wordt een "stream" genoemd. Een stroom vertegenwoordigt inhoud die op verschillende manieren wordt gesneden en in blokjes wordt gesneden of wordt gefilterd. Alle artikelen uit een specifieke feed maken deel uit van een stream, en alle artikelen uit een map ook.
Het volgende is een korte tabel om verschillen in algemene client-side jargon en de bijbehorende terminologie van de Google Reader API-backend weer te geven:

Kant van de cliënt API
Map / tag Tag / label
Abonnement Abonnement
Mensen die je volgt vriend
Met ster Met ster
gedeelde Uitzending

Eindpunten

Als u bent aangemeld bij uw Google Reader-account, kunt u de volgende eindpunten in uw browser invoeren:

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

Lijst met abonnementen:
https://www.google.com/reader/api/0/subscription/list?output=json

Lijst met mappen / tags:
https://www.google.com/reader/api/0/tag/list?output=json

Lijst met mensen die u volgt:
https://www.google.com/reader/api/0/friend/list?output=json

Lijst met voorkeuren van Google Reader:
https://www.google.com/reader/api/0/preference/stream/list?output=json

De bovenstaande eindpunten zijn alleen-lezen en zullen in deze zelfstudie worden gebruikt.


Stap 2: De interface bouwen

Om toegang te krijgen tot Google Reader, bouwen we een aangepaste PHP-klasse. Hieronder staat een lijst met de functies die deze klas nodig heeft (ik zal later in meer detail ingaan):

Class Functies

  • Log in - Haalt Google-auth-code en lezerwijzigings-token op.
  • get_subscriptions - Retourneert een lijst met geabonneerde feeds.
  • get_tags - Retourneert een lijst met mappen / tags.
  • get_friends - Retourneert een lijst met mensen die u volgt.
  • get_stream_items - Retourneert een artikel uit een stream.
  • set_article_read - Stelt een artikel in als gelezen.
  • set_article_starred - Stars een artikel.
  • set_article_broadcast - Voegt een artikel toe aan uw gedeelde lijst.
  • set_article_review - Past de tag "review" toe op een artikel.
  • get_url - HTTP GET-verzoek met Google-verificatie.
  • get_anon_url - HTTP GET-verzoek zonder Google-verificatie.
  • POST_URL - HTTP POST-verzoek met Google-verificatie.
  • post_anon_url - HTTP POST-aanvraag zonder Google-verificatie.

eigenschappen

Onze PHP-klasse gebruikt een aantal verschillende eigenschappen.

Zoals u wellicht kunt raden, worden de volgende eigenschappen ingesteld voor de e-ID en het wachtwoord van uw Google Reader-account:

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

De volgende eigenschappen worden gebruikt in de klasse Curl-functies (bekijk de broncode daarvan):

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

Ik heb proxy-ondersteuning opgenomen omdat mijn hosting-ISP (Godaddy) uitgaande verkeer door een proxy moet laten gaan. Als je geen proxy-ondersteuning nodig hebt, hou dan $ proxy op 0 in gr-config.php.

Vervolgens hebben we veel van de begin-eindpunten voor de beschikbare API's:

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

De volgende drie eigenschappen slaan informatie op die is verzameld tijdens het authenticatieproces:

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

In de toepassingssectie stellen we deze in op PHP-sessies, zodat we bij elk verzoek niet opnieuw hoeven in te loggen.


Stap 3: De klassenfuncties uitvloeien

De volgende functies zullen het zware werk voor onze toepassing doen.

Aanmeldingsfunctie

We moeten de Google Authentication API starten om te beginnen:

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

Na het opvragen van de authenticatie-API, is het eerste wat u moet verzamelen de $ auth-tekenreeks. Deze reeks levert de authenticatielaag van Google met onze inloggegevens. De $ auth is handig voor bijna elke Google-service.

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

Het volgende is het $ token en daarvoor moeten we een ander eindpunt bereiken. Token is specifiek voor Google Reader en is vereist voor aanvragen die status schrijven of wijzigen.

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

De derde is een gebruikersinformatieobject, we hebben het userId-gedeelte nodig. Voor sommige van de API-opties is uw google userId vereist. Dit is een groot getal dat uw account vertegenwoordigt en niet het e-mailadres dat u gebruikt voor aanmeldingen. De gebruikersinformatie bevat ook het grote aantal dat wordt gebruikt voor toegang tot uw gedeelde feed.

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

Lijst Functies

Dit zijn eenvoudige functies om op verschillende manieren een lijst met uw feeds op te halen.

get_subscriptions geeft een lijst met alle feed waarop u bent geabonneerd:

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

get_tags geeft een lijst met alle mappen en tags terug:

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

get_friends geeft een lijst met de mensen die je volgt terug:

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

Items Functie

Dit is het vlees van de klas en waar alles naar toe leidt. Met deze functie retourneren we de afzonderlijke artikelen op basis van de opgegeven criteria. De $ stroom wordt getrokken uit de resultaten van de lijstfuncties en het kan een feed zijn van een vriend, een hele map of een specifieke feed. $ n is het aantal artikelen dat in één keer moet worden geretourneerd. Voor de app heb ik het beperkt tot slechts 20, maar als je dit hergebruikt voor iets anders dan real-time weergave, kun je het tot maximaal 1000 pushen. Na 1000 moet je de vervolgoptie gebruiken, wat buiten de scope voor dit is artikel.

get_stream_items accepteert een aantal parameters en met de standaardinstellingen hoeft u deze alleen maar van een stream te voorzien:

 functie get_stream_items ($ stream = ", $ xt_a = array ('user / - / state / com.google / read'), $ daysago = 3, $ n = 20, $ magic = True) 

$ ot wordt gebruikt om Google Reader te laten weten dat je deze keer geen artikelen ouder deze wilt retourneren. Google Reader gaat voorbij tijd, maar ik gebruik graag $ DAYSAGO omdat het gewoon makkelijker is om te gaan met dagen in plaats van met seconden. Daar kunnen we uitrekenen $ ot van de huidige tijd. $ ck is belangrijk, maar ik heb er nooit een goede uitleg over gekregen en zonder een officiële Google Reader API kan dit een raadsel blijven. Ik heb het ingesteld op time () * 1000 en het werkt gewoon, terwijl time () * 100 dat niet doet.

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

$ magic is een boolean om de artikelen te retourneren met behulp van de "magic" -ranking van Google Reader, of, indien false, met de nieuwste eerst. Je kunt ook eerst sorteren op oudste door $ r = 'o' in te stellen als je dat wilt.

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

$ xt_a wordt gebruikt om artikelen van een feed uit te sluiten op basis van bepaalde metadata met betrekking tot de staat van het artikel. Standaard retourneert de functie alleen ongelezen berichten omdat deze artikelen uitsluit die zijn gemarkeerd als gelezen.

 $ xt = "; foreach ($ xt_a als $ key => $ value) $ xt. = '& xt ='. $ value;

We geven de uiteindelijke URL door aan Google Reader en retourneren de resultaten nadat de parameters zijn ingesteld:

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

Functie instellen

Drie van deze functies worden gebruikt om terug te schrijven naar Google Reader en artikelen met een bepaalde status te markeren. De laatste wordt gebruikt om een ​​tag in te stellen. Je zou alle vier gemakkelijk tot een enkele functie kunnen condenseren en de "a =" als een functieparameter doorgeven. Deze instelling is gewoon mijn voorkeur, ik geef er de voorkeur aan, zodat de code die de klas gebruikt, schoner en gemakkelijker leesbaar is. Als u van plan bent om uw eigen functie te creëren, kunt u meerdere "a =" tegelijkertijd invoeren. Ook kun je meerdere "i =" en "s =" opties passeren, je moet gewoon een gelijk aantal en in de juiste volgorde doorgeven. Ik geef over het algemeen een cijfer van 10 op een moment waarop veel items als gelezen worden gemarkeerd.

Stel het artikel in op de status "lezen":

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

Ster het artikel:

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

Deel het artikel met degenen die jou volgen:

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

Deze laatste past een beoordelingstag toe:

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

Het bovenstaande moet in de app worden gebruikt, zodat u iets kunt markeren om te beoordelen wanneer u de volgende keer een gewone browser gebruikt.


Stap 4: naar de applicatie

De applicatie-interface is gebouwd op basis van de uitstekende HTML5-boilerplate op http://html5boilerplate.com/. Ik nam de index.php van de standaard en splitste deze in header en footer include files. De hoofdpagina is index.php en accepteert een &lijst querystringwaarde die aangeeft welke lijst moet worden weergegeven. Het is standaard ingesteld op de mappenlijst. Elk item in de lijst gaat naar articles.php met de &stroom en &lijst geslaagd. De klasse wordt in een bestand gr.php geplaatst, waarbij gr-config.php feitelijk het bestand is dat het in de andere invoegt. Het is misschien logisch, maar in gr-config.php plaatsen we ook de configuratie-opties voor de klas. Het laatste php-bestand is set_article.php. Het wordt gebeld met een AJAX-verzoek van articles.php en is verantwoordelijk voor het aanroepen van de ingestelde functies.

Ik heb de twee onderstaande tags opgenomen in de header.php include file, maar ze zijn becommentarieerd:

  

Ze maken de web-app meer als een normale app wanneer u de site op het startscherm van iOS toevoegt. apple-touch-startup-image biedt een afbeelding die moet worden weergegeven terwijl de hoofdpagina wordt geladen. appel-mobile-web-app-capable zorgt ervoor dat de site wordt uitgevoerd op zijn eigen Safari-instantie in plaats van op de algemene Safari-instantie. Het enige probleem is dat met appel-mobile-web-app-capable ingesteld op ja, klikken op een koppeling naar een ander domein opent de koppeling in het hoofd-Safari-exemplaar, waardoor u wordt gedwongen terug te keren naar de reader-app.


Stap 5: Bouw de hoofdpagina op

Voor deze toepassing gaan we een hoofdpagina bouwen die een lijst van beide weergeeft Mappen (standaard), Vrienden of abonnementen.

screenshot

De opzet

Dit is de setup aan het begin van de pagina's index.php, articles.php en set_article.php:

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

Het menu

Het menu is een eenvoudige HTML-lijst die kan worden gebruikt om de verschillende abonnementslijsten op te halen:

 

Het menu maakt gebruik van een sprite voor de knoppen op basis van de leuke icon set Glyphish.

De code

Nu naar het eerste echte gebruik van de klas. Kortom, we gaan kijken of &lijst is ingesteld en, indien niet, standaard in de weergave tags. Dan is het gewoon een switch-statement om te weten welke lijst moet worden gebouwd en welke gr-functie moet worden gebruikt.

Ten eerste zijn we standaard $ lijst naar tags als er niets wordt doorgegeven en vervolgens wordt doorgegeven $ lijst naar een schakelaar. Wanneer $ lijst komt overeen met subs, we geven gewoon een vrij eenvoudige lijst af met alle geretourneerde abonnementen. Dit kan veel zijn voor zware gebruikers, daarom is de tags-modus de standaard.

 if (isset ($ _ GET ['list'])) $ list = $ _GET ['list'];  else $ list = 'tags';  switch ($ list) case 'subs': $ subs = $ gr-> get_subscriptions (); foreach ($ subs-> abonnementen als $ sub) echo '
  • id); echo '
  • streamen, '\' ">', $ vriend-> Selecteer'
  • '; pauze;

    Stap 6: Bouw de artikelpagina op

    Op deze pagina bekijkt u de artikelen, markeert u deze, stelt u ze later opnieuw in, markeert u ze als favoriet of deelt u ze met uw vrienden.

    screenshot

    De opzet

    Hetzelfde als de hoofdpagina.

    Het menu

    Nog een eenvoudige HTML-lijst. Ik ben geen fan van het gebruik van window.history voor een terugknop, dus voor de achterkant stuur ik ze terug naar de lijst die ze bekeken.

     

    De code

    De get_stream_items De functie van onze klas is de primaire driver voor de pagina en de meeste standaardinstellingen zijn hiervoor goed. Standaard worden items uitgesloten die zijn gemarkeerd als gelezen, maar ik heb de extensie verlengd $ xt_a array om ook artikelen uit te sluiten die zijn gemarkeerd met het label / label 'recensie'. Op deze manier worden items die we voor beoordeling markeren nooit weergegeven in deze lijst, ook al hebben we ze nog niet gelezen. We gaan de artikelen in het verborgen laden div tags en laat alleen de :eerstgeborene, manipuleer dan de anderen via JavaScript.

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

    In plaats van te proberen de status in een sessie of een array in JavaScript vast te houden, gebruik ik alleen de relevante gegevens als attributen op de wrapper div van elk artikel.

     echo '
    '; echo'
    alternatieve [0] -> href, ''>', $ artikel-> titel'
    ';

    De inhoud kan terugkomen in samenvatting of niet, afhankelijk van de feed. Omdat we mobiel zijn, proberen we het voor een samenvatting, maar we gaan terug naar de volledige inhoud als het niet beschikbaar is. We zullen ook de links in het artikel in een nieuw venster laten verschijnen.

     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); 

    Laat tot slot zien wat we hebben:

     echo '
    '$ Content'
    '; echo '
    ';

    Stap 7: JavaScript voor artikelacties

    Het JavaScript is sterk afhankelijk van jQuery. Het artikel.php-menu roept set_article () wanneer u op een actie klikt en set_article.php aanroept om die actie te verwerken. set_article () zullen eerst het ID en de stream van het artikel dat we bekijken, pakken div label. Het zal dan het totaal pakken om een ​​herlaadbeurt af te vuren als we het einde van de beschikbare artikelen bereiken. Het script set_article.php retourneert een 1 als de uitgevoerde actie naar het volgende artikel moet gaan. Anders worden de uitgevoerde acties gecontroleerd en wordt het pictogram Ster of Delen verlicht. Het gebruikt $ .Eq () en de variabele plak opsommen via de geretourneerde artikelen.

    omgeving totaal verander dynamisch in plaats van alleen '20' te gebruiken:

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

    Kenmerken toevoegen aan de artikelomslag div label:

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

    Hier geven we de id en stream door aan de pagina set_article.php en krijgen we een 1 of 0 terug. De 1 betekent dat de actie het verwijderen van het artikel uit het zicht vereist en de 0 betekent dat dit slechts een statuswijziging is.

     $ .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 '); $ ('. uitzending '). css (backgroundPosition:' -93px -31px '); else 

    Als er een 0 wordt geretourneerd, moeten we zien welke actie is ondernomen, zodat de juiste status van het pictogram ook wordt gewijzigd:

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

    Stap 8: Acties op artikelen toepassen

    Dit is het laatste deel van PHP waarmee we het artikel kunnen manipuleren.

    De opzet

    Hetzelfde als de hoofdpagina.

    De code

    Het harde werk is gedaan in de klas, dus deze pagina is eigenlijk maar een schakel om de klassefunctie uit te voeren die overeenkomt met de actie. U vraagt ​​zich misschien af ​​waarom Google het vereist $ stroom variabel. Van wat ik kan vertellen, heeft dit alles te maken met hoe Google alle lezersgegevens opslaat en de transactietijd verkort bij het verwerken van deze bewerkingsfuncties.

     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'; breken; case 'starred': $ r = $ gr-> set_article_starred ($ id, $ stream); echo '0'; breken; case 'broadcast': $ r = $ gr-> set_article_broadcast ($ id, $ stream); echo '0'; breken; case 'review': $ r = $ gr-> set_article_review ($ id, $ stream); echo '1'; breken; 

    Stap 9: Afronden met CSS

    Het merendeel van de CSS is niet iets speciaals. Ik heb de twee belangrijkste stijlen hieronder opgenomen:

     .artikel-samenvatting img, .artikel-samenvatting embed max-height: 50%; max-width: 50%;  .artikel: first-child display: block; 

    De max-height: 50% en max-width: 50% Verklaringen zijn erg handig bij het hergebruiken van HTML met afbeeldingen en insluitingen. Het houdt de afbeeldingen en youtube inclusief van het overbelasten van het mobiele scherm.


    Stap 10: Meer informatie

    Totdat er een officiële API beschikbaar is, zijn deze plaatsen ideaal om aanvullende informatie te krijgen over het bouwen van apps met Google Reader:

    • Vrienden van de onofficiële Google Reader API: een discussiegroep met veel geweldige info en mensen.
    • Niall Kennedy: een van de eersten die knoeit met de API.
    • Stack Overflow: vragen getagd met google-reader-api (ik ben begonnen sommige van hen te beantwoorden).
    • pyrfeed: De wiki voor deze pythonklasse heeft veel info.
    • Martin Doms: Goed gedaan afbakening van de URL's die in de API worden gebruikt.