Crearea unui client Twitter pentru Android Preluarea actualizărilor utilizând un serviciu

În această serie construim un client Twitter pentru platforma Android folosind biblioteca Twitter4J. Acest tutorial se va concentra pe implementarea unui serviciu pentru a prelua în permanență mesajele tweets noi pentru cronologia de acasă a utilizatorului. De asemenea, vom folosi un Receiver de difuzare pentru a actualiza interfața aplicației când devin disponibile mesaje noi pentru afișare.


Disponibile și în această serie:

  1. Crearea unui client Twitter pentru Android: Setare și prezentare generală
  2. Crearea unui client Twitter pentru Android: Construirea interfeței
  3. Crearea unui client Twitter pentru Android: Crearea unei baze de date temporale
  4. Crearea unui client Twitter pentru Android: Preluarea actualizărilor utilizând un serviciu
  5. Crearea unui client Twitter pentru Android: Tweeting, Retweeting și Replying

Pasul 1: Creați o clasă de servicii

Pentru ca mesajele tweet-uri cronologice ale utilizatorului să fie afișate automat atunci când devin disponibile, vom folosi un serviciu pentru a le prelua la intervale stabilite. Acest serviciu se va difuza la o frecventa aleasa de dumneavoastra, scriind in baza de date si transmiand emisiuni atunci cand au fost recuperate si stocate noi tweet-uri. Clasa principală a activității aplicației va primi emisiunile și solicită baza de date, actualizând interfața cronologică pentru a afișa noile date.

Creați o nouă clasă în proiectul dvs., numind-o "TimelineService" și modificând linia de declarație a clasei de deschidere după cum urmează:

 clasa publică TimelineService extinde serviciul 

Veți avea nevoie de următorul import:

 import șiroid.app.Service;

Adăugați la clasă următoarele variabile de instanță pentru a interacționa cu Twitter:

 / ** Cheie de autentificare twitter * / String final public final TWIT_KEY = "cheia ta"; / ** twitter secret * / public final static String TWIT_SECRET = "secretul tău"; / ** twitter obiect * / privat Twitter timelineTwitter;

Modificați variabilele cheie și cele secrete pentru a se potrivi cu dvs., așa cum este folosit în tutoriile anterioare. Adăugați următoarele variabile pentru manipularea bazei de date:

 / ** baza de date a ajutorului bazei de date * / private NiceDataHelper niceHelper; / ** baza de date temporală * / privat SQLiteDatabase niceDB;

În cele din urmă, adăugați următoarele pentru utilizarea generică în cadrul clasei:

 / ** preferințe partajate pentru detalii utilizator * / private SharedPreferences nicePrefs; / ** Handler pentru updater * / Handler privat niceHandler; / ** întârziere între aducerea de tweets noi * / private static int mins = 5; // modifica pentru a se potrivi static privat finală lungi FETCH_DELAY = mins * (60 * 1000); // debugging tag String privat LOG_TAG = "TimelineService";

Obiectul Handler este pentru programarea actualizărilor la frecvențele setate. Variabila "min" și constanta "FETCH_DELAY" vă permit să setați frecvența la care aplicația va prelua noi actualizări din cronologia de origine a utilizatorului. Modificați variabila "minute" pentru a reflecta totuși multe minute în care doriți ca aplicația să aștepte între actualizări. Actualizările vor fi preluate numai la această frecvență în timpul funcționării aplicației. Când utilizatorul iese din aplicație și este distrus, va opri funcționarea continuă a serviciului. Data viitoare când utilizatorul va rula aplicația, va prelua noi actualizări prin reluarea serviciului.

În partea de sus a fișierului de clasă, adăugați următoarele importuri pentru biblioteca Twitter4J:

 import twitter4j.Status; import twitter4j.Twitter; import twitter4j.TwitterFactory; import twitter4j.conf.Configuration; import twitter4j.conf.ConfigurationBuilder;

Cu următoarea listă pentru resurse Android:

 import șiroid.app.Service; import șiroid.content.ContentValues; import șiroid.content.Intent; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.os.Handler; import șiroid.os.IBinder; import șiroid.util.Log;

Și, în sfârșit, următoarele pentru clasa Java List:

 import java.util.List;

Pentru a implementa clasa Service, vom furniza metode "onCreate" și "onStartCommand" pentru momentul în care clasa este instanțiată și serviciul a început, metoda "onDestroy" pentru momentul finalizării și metoda "onBind", care este necesară deși nu o vom folosi. De asemenea, vom crea o clasă interioară, în care vom prelua actualizările de la Twitter la intervale stabilite.

Mai întâi, să implementăm metoda "onCreate":

 @Override publice void onCreate () super.onCreate (); // configurați clasa

În cadrul metodei, vom instanțiza câteva dintre variabilele noastre de instanță:

 / / get prefs nicePrefs = getSharedPreferences ("TwitNicePrefs", 0); // obține ajutor de bază de date niceHelper = new NiceDataHelper (this); // obține baza de date niceDB = niceHelper.getWritableDatabase ();

Să creați, de asemenea, o instanță a obiectului Twitter4J, astfel încât să putem prelua tweet-uri:

 // a obține preferințele utilizatorului String userToken = nicePrefs.getString ("user_token", null); String userSecret = nicePrefs.getString ("user_secret", null); // crea configurație nouă Configurație twitConf = new ConfigurationBuilder () .setOAuthConsumerKey (TWIT_KEY) .setOAuthConsumerSecret (TWIT_SECRET) .setOAuthAccessToken (userToken). setOAuthAccessTokenSecret (userSecret) .build (); // instanțiați noul timer twitterTwitter = noul TwitterFactory (twitConf) .getInstance ();

Trebuie să implementăm metoda "onBind", deși nu o folosim de fapt, deci adăugați-o după cum urmează:

 @Override publice IBinder onBind (intenția intenției) return null; 

Pasul 2: Creați o clasă care poate fi rulată

Când serviciul pornește, metoda "onStartCommand" va fi executată și, atunci când va fi distrusă, va porni metoda "onDestroy". Vom implementa în curând aceste două metode, dar mai întâi vom crea o clasă interioară care să se ocupe de preluarea actualizărilor la perioade fixe. În interiorul declarației de clasă "TimelineService", adăugați următoarea schiță a clasei:

 / ** * TimelineCategoriaUpdater implementează interfața care poate fi rulată * / class TimelineUpdater implementează Runnable // fetch updates

În cadrul acestei clase vom recupera cronologia utilizatorului de la domiciliu, le vom scrie în baza de date și vom trimite un Broadcast la activitatea principală atunci când vor apărea noi mesaje tweets. Toate acestea se vor întâmpla în metoda "run", așa că adăugați-o la noua clasă interioară după cum urmează:

 // rula metoda void run public () 

Vom trimite doar Broadcast-ul la activitatea principală atunci când există noi tweets, așa că pentru a urmări creăm o variabilă booleană în cadrul metodei "run":

 // verificați pentru actualizări - nu asumați niciun status booleanChanges = false;

În continuare vom încerca să preluăm datele de pe Internet, așa că trebuie să încercăm și să prindem blocuri:

 încercați // preluați cronologia captură (Excepție te) Log.e (LOG_TAG, "Excepție:" + te); 

În interiorul blocului de încercare, preluați cronologia utilizatorului ca un obiect List:

 // preluarea noii linii de cronologie cronologică la domiciliu ca listă Listă homeTimeline = timelineTwitter.getHomeTimeline ();

Cronologia preluată este o listă de obiecte de stare. Fiecare obiect Status conține datele pentru o actualizare tweet unică. Acum trebuie să introducem tweet-urile noi și să le inserăm în baza de date:

 // iterați prin noile actualizări de stare pentru (Status statusUpdate: homeTimeline) // apela metoda getValues ​​a clasei helper de date, trecând noile actualizări ContentValues ​​timelineValues ​​= NiceDataHelper.getValues ​​(statusUpdate); // dacă baza de date conține deja actualizările, acestea nu vor fi inserate niceDB.insertOrThrow ("home", null, timelineValues); // confirmăm că avem noi actualizări statusChanges = true; 

Observați că sunăm metoda "getValues" din clasa NiceDataHelper, care este statică. Metoda "getValues" ia obiectele Twitter Status și prelucrează datele relevante pentru baza noastră de date, adică ID-ul tweet-ului, textul, numele ecranului, adresa URL a imaginii de profil și ora, toate conținute în fiecare instanță Stare. Metoda le returnează ca seturi de valori care pot fi inserate în baza de date, pe care le facem aici. Deoarece există tweet-uri noi, setăm flagul "statusChanges" la true.

După blocul de captură, trimitem o difuzare la activitatea principală numai dacă există mesaje tweet noi pentru afișare:

 // dacă avem noi actualizări, trimiteți o difuzare dacă (statusChanges) // aceasta ar trebui primită în clasa cronologică principală sendBroadcast ("New Intent" ("TWITTER_UPDATES")); 

Ne vom ocupa de primirea acestui lucru în clasa de activitate principală mai târziu. În cele din urmă, după această instrucțiune if și încă în interiorul metodei "run", instruiți Android să apeleze din nou metoda "run" după întârzierea aleasă:

 // întârziere la preluarea noilor actualizări niceHandler.postDelayed (this, FETCH_DELAY);

În partea de sus a clasei TimelineService, adăugați o altă variabilă de instanță pentru această clasă nouă:

 / ** obiect updater obiect * / privat TimelineUpdater niceUpdater;

Pasul 3: Porniți obiectul Runnable

Acum putem gestiona metoda "TimelineService" pentru momentul în care începe Serviciul. Înapoi în clasa Service (în afara noii clase Runnable), adăugați metoda "onStartCommand":

 @Override public int peStartCommand (Intent intent, int flags, int startId) super.onStart (intent, startId); // obțineți handler niceHandler = Handler nou (); // a crea o instanță a clasei updater niceUpdater = new TimelineUpdater (); // adauga la coada de rulare niceHandler.post (niceUpdater); // returnați întoarcerea sticky START_STICKY; 

Aici numim metoda superclasei și returnează o valoare întregă standard. De asemenea, instanțiăm Handlerul și noua clasă Runnable. Handler-ul adaugă Runnable la coada de proces, astfel încât să se execute metoda "run".

Acum, tot ce trebuie să terminăm clasa Service este implementarea metodei de distrugere:

 @Override public void peDestroy () super.onDestroy (); // opriți actualizarea niceHandler.removeCallbacks (niceUpdater); niceDB.close (); 

Pasul 4: Primește difuzări

Înapoi în clasa principală a activității din aplicație, putem începe serviciul și vom primi transmisiile rezultate. Adăugați următoarea variabilă de instanță în partea de sus a clasei dvs. "TwitNiceActivity":

 / ** Receptor difuzat atunci când sunt disponibile noi actualizări * / Private BroadcastReceiver niceStatusReceiver;

Veți avea nevoie de următoarea declarație de import:

 import șiroid.content.BroadcastReceiver;

Adăugați o nouă clasă interioară în clasa principală a activității dvs. pentru a primi postările de difuzare, asigurându-vă că o adăugați în afara oricăreia dintre metode, dar încă în interiorul declarației clasei de activitate:

 / ** * Clasa pentru implementarea chitanței difuzate pentru noi actualizări * / class TwitterUpdateReceiver extinde BroadcastReceiver 

Această clasă va face un singur lucru: să primească transmisiuni - să implementeze metoda "onReceive" în interiorul ei:

 @Override public void onReceive (Contextul contextului, intenția intenției) 

În cadrul acestei metode, vom reduce la minimum dimensiunea bazei de date ștergând unele înregistrări ori de câte ori devin disponibile tweets noi:

 int rowLimit = 100; dacă DatabaseUtils.queryNumEntries (cronologieDB, "home")> rowLimit) String deleteQuery = "DELETE FROM home WHERE" + BaseColumns._ID + "NOT IN" + "SELECT" + BASICColumns._ID + "FROM home ORDER BY" update_time DESC "+" limită "+ rowLimit +") "; timelineDB.execSQL (deleteQuery); 

În acest caz, limităm masa la 100 de rânduri, dar, desigur, puteți schimba acest lucru la un număr de alegere. Interogarea șterge toate cele 100 de înregistrări noi din tabel.

Adăugați în clasa următoarele importuri:

 import android.provider.BaseColumns; import android.database.DatabaseUtils; importați android.content.Context;

Acum trebuie să interogăm baza de date și să actualizăm interfața utilizator Vizualizări folosind Adaptorul:

 timelineCursor = cronologieDB.query ("home", null, null, null, null, null, "update_time DESC"); startManagingCursor (timelineCursor); timelineAdapter = noul UpdateAdapter (context, timelineCursor); homeTimeline.setAdapter (timelineAdapter);

Observați că folosim un proces similar cu ceea ce se întâmplă în metoda "setupTimeline". Atunci când utilizatorul a executat deja aplicația cel puțin o dată, la lansarea acesteia, vor vedea datele existente în timp ce se prelucrează date noi. Imediat ce noile date sunt disponibile, vizualizările vor fi actualizate pentru a fi afișate. Bineînțeles, viteza cu care se întâmplă acest lucru depinde de conectivitatea utilizatorului în rețea.


Pasul 5: Porniți serviciul

Să terminăm metoda "setupTimeline". După ce ați trecut ultima dată în clasa UpdateAdapter, înainte de terminarea blocului de încercări, adăugați următoarele pentru a seta adaptorul la cronologie:

 // aceasta va face aplicația să populeze noile date de actualizare în vizualizarea cronologică homeTimeline.setAdapter (timelineAdapter);

Apoi creați o instanță a clasei dvs. de radiodifuzor și înregistrați-o pentru a primi actualizări din clasa Service:

 // instanțiați clasa receptor pentru a afla când sunt disponibile actualizări noi niceStatusReceiver = new TwitterUpdateReceiver (); // înregistrare pentru actualizări registerReceiver (niceStatusReceiver, new IntentFilter ("TWITTER_UPDATES"));

Observați că String-ul pe care îl furnizăm constructorului IntentFilter se potrivește cu Stringul pe care îl folosim atunci când trimitem Broadcast-ul în cadrul clasei TimelineService Runnable.

Veți avea nevoie de următorul import:

 import android.content.IntentFilter;

În cele din urmă, porniți serviciul, trecând numele clasei:

 // începe serviciul pentru actualizări acum this.getApplicationContext () startService (nou intenție (this.getApplicationContext (), TimelineService.class));

Înainte de a termina, să punem în aplicare metoda distrugerii pentru clasa principală de activități, deoarece se referă la obiectele pe care le-am folosit aici:

 @Override public void peDestroy () super.onDestroy (); încercați // opriți serviciul updater Service stopService (nou intenție (aceasta, TimelineService.class)); // elimina receptorul inregistreaza unregisterReceiver (niceStatusReceiver); // închideți cronologia bazei de dateDB.close ();  captură (Excepție se) Log.e (LOG_TAG, "nu poate opri serviciul sau receptorul"); 

Ori de câte ori gestionați bazele de date și serviciile, este important să nu pierdeți resursele, lăsându-le să ruleze atunci când aplicația nu se execută efectiv. Aici oprim serviciul, neînregistrarea receptorului pe care l-am ascultat și închiderea bazei de date. Când aplicația este lansată din nou, toate acestea vor fi repornite.


Următor →

Am implementat acum afișarea tweet-urilor cronologice de acasă ale utilizatorilor, preluarea acestora la intervale fixe printr-un serviciu și detectarea recuperării acestora utilizând Broadcast-uri. În tutorialul final vom implementa tweeting, retweeting și răspuns. Aceasta va implica implementarea unei noi Activități Tweet și a butoanelor retweet / răspuns în cadrul fiecărei actualizări din linia temporală principală.

Cod