Opprette en Twitter-klient for Android Henter oppdateringer ved hjelp av en tjeneste

I denne serien bygger vi en Twitter-klient for Android-plattformen ved hjelp av Twitter4J-biblioteket. Denne opplæringen vil fokusere på å implementere en tjeneste for kontinuerlig å hente nye tweets for brukerens hjem tidslinje. Vi vil også bruke en kringkasting mottaker for å oppdatere appgrensesnittet når nye tweets blir tilgjengelige for visning.


Også tilgjengelig i denne serien:

  1. Opprette en Twitter-klient for Android: Oppsett og oversikt
  2. Opprette en Twitter-klient for Android: Bygg grensesnittet
  3. Opprette en Twitter-klient for Android: Opprette en tidslinjedatabase
  4. Opprette en Twitter-klient for Android: Henter oppdateringer ved hjelp av en tjeneste
  5. Opprette en Twitter-klient for Android: Tweeting, Retweeting og Svar

Trinn 1: Opprett en serviceklasse

Slik at brukerens hjem tidslinje tweets automatisk blir vist når de blir tilgjengelige, skal vi bruke en tjeneste for å hente dem med bestemte intervaller. Denne tjenesten vil kjøre med en frekvens etter eget valg, skrive til databasen og sende kringkastinger når nye tweets er hentet og lagret. Appens hovedaktivitetsklasse mottar kringkastingene og krever databasen, oppdatering av tidslinjegrensesnittet for å vise de nye dataene.

Opprett en ny klasse i prosjektet ditt, navngi det "TimelineService" og endre åpningsklasse deklarasjonslinjen som følger:

 offentlig klasse TimelineService utvider tjenesten 

Du trenger følgende import:

 importere android.app.Service;

Legg til følgende forekomstvariabler i klassen din, for å kommunisere med Twitter:

 / ** kvitteringsautentiseringsnøkkel * / offentlig endelig statisk streng TWIT_KEY = "din nøkkel"; / ** twitter hemmelig * / offentlig endelig statisk streng TWIT_SECRET = "din hemmelige"; / ** twitter objekt * / privat Twitter tidslinjeTwitter;

Endre nøkkelen og hemmelige variabler som passer til din egen, som brukt i de forrige veiledningene. Legg til følgende variabler for databasebehandling:

 / ** databasehjelpobjekt * / privat NiceDataHelper niceHelper; / ** tidslinje database * / privat SQLiteDatabase niceDB;

Til slutt legger du til følgende for generisk bruk i klassen:

 / ** delte preferanser for brukerdetaljer * / privat SharedPreferences nicePrefs; / ** handler for oppdaterer * / privat Handler niceHandler; / ** forsinkelse mellom å hente nye tweets * / private statiske int min = 5; // endre for å passe privat statisk endelig lang FETCH_DELAY = minutter * (60 * 1000); // debugging tag private String LOG_TAG = "TimelineService";

Handler-objektet er for planlegging av oppdateringer ved angitte frekvenser. Med "Min" -variabelen og "FETCH_DELAY" -konstanten kan du angi hvor ofte appen skal hente nye oppdateringer fra brukerens hjemtidslinje. Endre "min" -variabelen for å gjenspeile hvor mange minutter du vil at appen skal vente mellom oppdateringer. Oppdateringene blir bare hentet på denne frekvensen mens appen kjører. Når brukeren kommer ut av appen, og den blir ødelagt, vil den stoppe tjenesten fra kontinuerlig kjøring. Neste gang brukeren kjører appen, henter den nye oppdateringer ved å starte Tjenesten på nytt.

Øverst i klassefilen legger du til følgende import for Twitter4J-biblioteket:

 importer twitter4j.Status; importere twitter4j.Twitter; importer twitter4j.TwitterFactory; importer twitter4j.conf.Configuration; importer twitter4j.conf.ConfigurationBuilder;

Med følgende liste for Android-ressurser:

 importere android.app.Service; importer android.content.ContentValues; importer android.content.Intent; importer android.content.SharedPreferences; importer android.database.sqlite.SQLiteDatabase; importere android.os.Handler; importer android.os.IBinder; importer android.util.Log;

Og til slutt følgende for Java List-klassen:

 importer java.util.List;

For å implementere vår serviceklasse skal vi gi metodene "onCreate" og "onStartCommand" for når klassen er instantiated og tjenesten startet, "onDestroy" -metoden for når den er ferdig, og "onBind" -metoden, som kreves selv om vi ikke vil bruke det. Vi skal også lage en indre klasse, der vi henter oppdateringene fra Twitter med faste intervaller.

La oss først implementere "onCreate" -metoden:

 @Override public void onCreate () super.onCreate (); // sette opp klassen

Innenfor metoden vil vi instantiere noen av våre instansvariabler:

 // få prefs nicePrefs = getSharedPreferences ("TwitNicePrefs", 0); // få databasehjelpen niceHelper = ny NiceDataHelper (dette); // få databasen niceDB = niceHelper.getWritableDatabase ();

La oss også lage en forekomst av Twitter4J-objektet slik at vi kan hente tweets:

 // få brukerinnstillinger String userToken = nicePrefs.getString ("user_token", null); String userSecret = nicePrefs.getString ("user_secret", null); // opprett ny konfigurasjon Konfigurasjon twitConf = ny ConfigurationBuilder () .setOAuthConsumerKey (TWIT_KEY) .setOAuthConsumerSecret (TWIT_SECRET) .setOAuthAccessToken (userToken) .setOAuthAccessTokenSecret (userSecret) .build (); // Installer ny twitter tidslinjeTwitter = Ny TwitterFactory (twitConf) .getInstance ();

Vi må implementere "onBind" metoden selv om vi ikke faktisk bruker den, så legg den til som følger:

 @Override public IBinder onBind (Intent Intent) return null; 

Trinn 2: Opprett en Runnable Class

Når Tjenesten starter, vil "onStartCommand" -metoden utføres, og når den blir ødelagt, vil "onDestroy" -metoden brann. Vi vil implementere begge disse metodene snart, men først vil vi lage en indre klasse for å håndtere å hente oppdateringene i faste perioder. I klassedeklarasjonen "TimelineService" legger du til følgende klassebeskrivelse:

 / ** * TimelineUpdater klasse implementerer runnable grensesnittet * / class TimelineUpdater implementerer Runnable // hente oppdateringer

Inne i denne klassen vil vi hente brukerens hjemme tidslinje, skrive dem til databasen og sende en kringkasting til hovedaktiviteten når det er nye tweets å vise. Alt dette skal skje i "run" -metoden, så legg det til din nye indre klasse som følger:

 // kjøre metode offentlig tomgang runde () 

Vi sender bare sendingen til hovedaktiviteten når det er nye tweets, så for å holde oversikt oppretter vi en boolsk variabel inne i "run" -metoden:

 // se etter oppdateringer - antar ingen boolsk statusChanges = false;

Deretter skal vi forsøke å hente data fra Internett, så vi må prøve å fange blokker:

 prøv // hent tidslinje fangst (Unntak te) Log.e (LOG_TAG, "Unntak:" + te); 

Inne i prøveblokken, hent brukerens tidslinje som et Listobjekt:

 // hente den nye hjemme tidslinje tweets som en liste Liste homeTimeline = tidslinjeTwitter.getHomeTimeline ();

Den hentede tidslinjen er en liste over statusobjekter. Hvert Status-objekt inneholder dataene for en enkelt tweet-oppdatering. Nå må vi gå gjennom de nye tweets og sette dem inn i databasen:

 // iterate gjennom nye statusoppdateringer for (Status statusUpdate: homeTimeline) // kaller getValues-metoden til datahjelpeklassen, passerer de nye oppdateringene ContentValues ​​timelineValues ​​= NiceDataHelper.getValues ​​(statusUpdate); // Hvis databasen allerede inneholder oppdateringene, vil de ikke bli satt inn niceDB.insertOrThrow ("home", null, timelineValues); // bekreft vi har nye oppdateringer statusChanges = true; 

Legg merke til at vi kaller "getValues" -metoden i NiceDataHelper-klassen, som er statisk. Metoden "getValues" tar Twitter Statusobjekter og henter de relevante dataene for databasen, dvs. tweet-ID, tekst, skjermnavn, tid og profilbilde, som alle finnes i hver Status-forekomst. Metoden returnerer disse som sett av verdier som kan settes inn i databasen, som vi gjør her. Siden det er nye tweets, setter vi "statusChanges" -flagget til ekte.

Etter fangstblokken sender vi en kringkasting til hovedaktiviteten bare hvis det er nye tweets å vise:

 // hvis vi har nye oppdateringer, send en kringkasting hvis (statusChanges) // dette skulle bli mottatt i hoved tidslinjeklassen sendBroadcast (new Intent ("TWITTER_UPDATES")); 

Vi vil takle kvittering for dette i hovedaktivitetsklassen senere. Til slutt, etter dette hvis erklæring og fortsatt inne i "run" -metoden, instruerer Android om å ringe "run" -metoden igjen etter den valgte forsinkelsen:

 // forsinkelse ved å hente nye oppdateringer niceHandler.postDelayed (dette, FETCH_DELAY);

Øverst i din TimelineService-klasse legger du til en annen instansvariabel for denne nye klassen:

 / ** updater tråd objekt * / privat TimelineUpdater niceUpdater;

Trinn 3: Start Runnable Object

Nå kan vi håndtere "TimelineService" -metoden for når tjenesten starter. Tilbake i Service-klassen (utenfor den nye Runnable-klassen) legger du til "onStartCommand" -metoden:

 @Override public int onStartCommand (Intent intent, int flagger, int startId) super.onStart (intent, startId); // få handler niceHandler = new Handler (); // lage en forekomst av oppdateringsklassen niceUpdater = ny TimelineUpdater (); // legg til å kjøre køen niceHandler.post (niceUpdater); // returnere klistret retur START_STICKY; 

Her kaller vi metoden til superklassen og returnerer en standard heltallverdi. Vi arrangerer også Handler og ny Runnable-klassen. Handler legger til Runnable i prosesskøen, slik at dens "run" -metode vil utføres.

Nå er alt vi trenger for å fullføre Service-klassen, å implementere ødeleggelsesmetoden:

 @Override public void onDestroy () super.onDestroy (); // stopp oppdateringen niceHandler.removeCallbacks (niceUpdater); niceDB.close (); 

Trinn 4: Motta sendinger

Tilbake i appens hovedaktivitetsklasse, kan vi nå starte tjenesten og motta de resulterende sendingene. Legg til følgende forekomstvariabel øverst i din "TwitNiceActivity" -klasse:

 / ** Broadcast mottaker for når nye oppdateringer er tilgjengelige * / private BroadcastReceiver niceStatusReceiver;

Du trenger følgende importerklæring:

 importer android.content.BroadcastReceiver;

Legg til en ny indre klasse i din hovedaktivitetsklasse for å motta sendinger, og sørg for at du legger til den utenfor noen av metodene, men fortsatt i aktivitetsklasserklæringen:

 / ** * Klasse for å implementere Broadcast-kvittering for nye oppdateringer * / klasse TwitterUpdateReceiver utvider BroadcastReceiver 

Denne klassen skal gjøre en ting: motta sendinger - så implementer "onReceive" -metoden inne i det:

 @Override public void onReceive (Context context, Intent Intent) 

Innenfor metoden skal vi minimere størrelsen på databasen ved å slette noen av postene når nye tweets blir tilgjengelige:

 int radLimit = 100; hvis (DatabaseUtils.queryNumEntries (timelineDB, "home")> rowLimit) String deleteQuery = "DELETE FROM home WHERE" + BaseColumns._ID + "IKKE IN" + "(SELECT" + BaseColumns._ID + "FROM home ORDER BY" + " update_time DESC "+" limit "+ rowLimit +") "; timelineDB.execSQL (deleteQuery); 

I dette tilfellet begrenser vi bordet til 100 rader, men du kan selvfølgelig endre dette til et antall du ønsker. Spørringen sletter alle, men de 100 nyeste postene i tabellen.

Legg til følgende import i klassen:

 importer android.provider.BaseColumns; importer android.database.DatabaseUtils; importer android.content.Context;

Nå må vi spørre databasen og oppdatere brukergrensesnittet Visninger ved hjelp av adapteren:

 timelineCursor = timelineDB.query ("home", null, null, null, null, null, "update_time DESC"); startManagingCursor (timelineCursor); timelineAdapter = ny UpdateAdapter (kontekst, tidslinjemarkør); homeTimeline.setAdapter (timelineAdapter);

Legg merke til at vi bruker en lignende prosess til det som skjer i "setupTimeline" -metoden. Når brukeren allerede har kjørt appen minst én gang, vil den se de eksisterende dataene mens nye data hentes, ved å starte den. Så snart de nye dataene er tilgjengelige, blir visningene oppdatert for å vise det. Selvfølgelig vil hastigheten der dette skjer, avhenge av brukerens nettverkstilkobling.


Trinn 5: Start tjenesten

La oss fullføre "setupTimeline" -metoden. Etter at linjen der du har opprettet oppdateringsadapter-klassen siste gang, før forsøksblokken slutter, legger du til følgende for å stille inn adapteren til tidslinjen:

 // dette vil gjøre appen fylle ut de nye oppdateringsdataene i tidslinjevisningen homeTimeline.setAdapter (tidslinjeAdapter);

Deretter opprett en forekomst av din Broadcast Receiver-klassen og registrer den for å motta oppdateringer fra Tjenesten-klassen:

 // instantiate receiver class for å finne ut når nye oppdateringer er tilgjengelige niceStatusReceiver = ny TwitterUpdateReceiver (); // registrere for oppdateringer registerReceiver (niceStatusReceiver, ny IntentFilter ("TWITTER_UPDATES"));

Legg merke til at strengen vi gir til IntentFilter-konstruktøren her, stemmer overens med strengen vi bruker når du sender kringkasting i tidslinjens Runnable-klasse.

Du trenger følgende import:

 importer android.content.IntentFilter;

Endelig, start tjenesten, bestått klassenavnet:

 // start tjenesten for oppdateringer nå this.getApplicationContext (). startService (new Intent (this.getApplicationContext (), TimelineService.class));

Før vi er ferdig, la oss implementere ødeleggelsesmetoden for hovedaktivitetsklassen, siden det gjelder objekter vi har brukt her:

 @Override public void onDestroy () super.onDestroy (); prøv // stopp oppdateringsstartstoppService (ny Intent (dette, TimelineService.class)); // Fjern mottakerregister unregisterReceiver (niceStatusReceiver); // lukk databasen timelineDB.close ();  fangst (Unntak se) Log.e (LOG_TAG, "Kan ikke stoppe Service eller mottaker"); 

Når du håndterer databaser og tjenester, er det viktig å ikke kaste bort ressurser ved å la dem kjøre når appen ikke faktisk utføres. Her stopper vi Tjenesten, registrerer mottakeren vi har lyttet til og avsluttet databasen. Når appen blir lansert igjen, vil alle bli startet på nytt.


neste

Vi har nå implementert å vise brukerens hjemme tidslinje tweets, hente dem med faste intervaller gjennom en tjeneste og oppdage henting av dem via Broadcasts. I den endelige opplæringen vil vi implementere tweeting, retweeting og svar. Dette vil innebære å implementere en ny Tweet Aktivitet og Retweet / Svar-knappene i hver oppdatering i hoved tidslinjen.