Création d'un client Twitter pour Android Récupération de mises à jour à l'aide d'un service

Dans cette série, nous construisons un client Twitter pour la plate-forme Android à l'aide de la bibliothèque Twitter4J. Ce tutoriel se concentrera sur l'implémentation d'un service pour extraire en permanence de nouveaux tweets pour la chronologie de départ de l'utilisateur. Nous utiliserons également un récepteur de diffusion pour mettre à jour l'interface de l'application lorsque de nouveaux tweets sont disponibles pour l'affichage..


Aussi disponible dans cette série:

  1. Création d'un client Twitter pour Android: Configuration et vue d'ensemble
  2. Création d'un client Twitter pour Android: construction de l'interface
  3. Création d'un client Twitter pour Android: Création d'une base de données chronologique
  4. Création d'un client Twitter pour Android: Récupération de mises à jour à l'aide d'un service
  5. Création d'un client Twitter pour Android: tweeter, retweeter et répondre

Étape 1: Créer une classe de service

Pour que les tweets de la chronologie de l'utilisateur local soient automatiquement affichés lorsqu'ils deviennent disponibles, nous allons utiliser un service pour les récupérer à des intervalles définis. Ce service fonctionnera à la fréquence de votre choix, en écrivant dans la base de données et en envoyant des diffusions lorsque de nouveaux tweets ont été récupérés et stockés. La classe d'activité principale de l'application recevra les diffusions et actualisera la base de données, mettant à jour l'interface de la chronologie pour afficher les nouvelles données..

Créez une nouvelle classe dans votre projet, appelez-la "TimelineService" et modifiez la ligne de déclaration de la classe d'ouverture comme suit:

 Classe publique TimelineService Etend Service 

Vous aurez besoin de l'importation suivante:

 importer android.app.Service;

Ajoutez les variables d'instance suivantes à votre classe pour interagir avec Twitter:

 / ** clé d'authentification twitter * / public final static String TWIT_KEY = "votre clé"; / ** twitter secret * / public final static String TWIT_SECRET = "votre secret"; / ** objet twitter * / private Twitter timelineTwitter;

Modifiez les variables clés et secrètes en fonction des vôtres, comme dans les didacticiels précédents. Ajoutez les variables suivantes pour la gestion de la base de données:

 / ** objet d'assistance de base de données * / private NiceDataHelper niceHelper; / ** base de données de la timeline * / private SQLiteDatabase niceDB;

Enfin, ajoutez les éléments suivants pour une utilisation générique dans la classe:

 / ** préférences partagées pour les détails de l'utilisateur * / private SharedPreferences nicePrefs; / ** gestionnaire pour le programme de mise à jour * / private Handler niceHandler; / ** délai entre l'extraction de nouveaux tweets * / private static int mins = 5; // modification en fonction du temps statique final privé FETCH_DELAY = mins * (60 * 1000); // balise de débogage private String LOG_TAG = "TimelineService";

L'objet Handler sert à planifier des mises à jour à des fréquences définies. La variable "mins" et la constante "FETCH_DELAY" vous permettent de définir la fréquence à laquelle l'application récupérera les nouvelles mises à jour à partir de la chronologie de départ de l'utilisateur. Modifiez la variable "mins" afin de refléter le nombre de minutes pendant lesquelles l'application doit attendre entre les mises à jour. Les mises à jour ne seront récupérées à cette fréquence que pendant l'exécution de l'application. Lorsque l'utilisateur quitte l'application et qu'elle est détruite, le service cesse de fonctionner. La prochaine fois que l'utilisateur lancera l'application, il récupérera les nouvelles mises à jour en redémarrant le service..

En haut de votre fichier de classe, ajoutez les importations suivantes pour la bibliothèque Twitter4J:

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

Avec la liste suivante pour les ressources Android:

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

Et enfin, les éléments suivants pour la classe Java List:

 importer java.util.List;

Pour implémenter notre classe Service, nous allons fournir les méthodes "onCreate" et "onStartCommand" pour le moment où la classe est instanciée et le service démarré, la méthode "onDestroy" pour le moment où elle se termine et la méthode "onBind", qui est obligatoire. bien que nous ne l'utilisons pas. Nous allons également créer une classe interne dans laquelle nous allons récupérer les mises à jour de Twitter à des intervalles définis..

Tout d'abord, implémentons la méthode "onCreate":

 @Override public void onCreate () super.onCreate (); // configurer la classe

Dans la méthode, nous allons instancier certaines de nos variables d'instance:

 // get prefs nicePrefs = getSharedPreferences ("TwitNicePrefs", 0); // récupère l'assistant de base de données niceHelper = new NiceDataHelper (this); // récupère la base de données niceDB = niceHelper.getWritableDatabase ();

Créons également une instance de l'objet Twitter4J afin de pouvoir récupérer des tweets:

 // récupère les préférences de l'utilisateur String userToken = nicePrefs.getString ("user_token", null); String userSecret = nicePrefs.getString ("user_secret", null); // crée une nouvelle configuration Configuration twitConf = new ConfigurationBuilder () .setOAuthConsumerKey (TWIT_KEY) .setOAuthConsumerSecret (TWIT_SECRET) .setOAuthAccessToken (userToken) .setOAuthAccessTokenSecret (userSecret) .build (); // instancie un nouveau journal Twitter Twitter = new TwitterFactory (twitConf) .getInstance ();

Nous devons implémenter la méthode "onBind" bien que nous ne l'utilisions pas réellement, ajoutez-le comme suit:

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

Étape 2: Créer une classe exécutable

Lorsque le service démarre, la méthode "onStartCommand" s'exécute et lorsqu'elle est détruite, la méthode "onDestroy" se déclenche. Nous allons bientôt implémenter ces deux méthodes, mais nous allons d'abord créer une classe interne pour gérer l'extraction des mises à jour à des périodes fixes. Dans votre déclaration de classe "TimelineService", ajoutez le plan de classe suivant:

 / ** * La classe TimelineUpdater implémente l'interface exécutable * / class TimelineUpdater implémente Runnable // fetch updates

Dans cette classe, nous allons récupérer la chronologie de base de l'utilisateur, les écrire dans la base de données et envoyer une diffusion à l'activité principale lorsque de nouveaux tweets doivent être affichés. Tout cela va se passer dans la méthode "run", ajoutez-le donc à votre nouvelle classe interne comme suit:

 // run method public void run () 

Nous n'allons envoyer la diffusion à l'activité principale que lorsqu'il y a de nouveaux tweets. Par conséquent, pour garder une trace, nous créons une variable booléenne dans la méthode "run":

 // vérifier les mises à jour - supposer aucun boolean statusChanges = false;

Nous allons ensuite essayer de récupérer des données sur Internet. Nous avons donc besoin d’essayer d’attraper des blocs:

 try // fetch timeline catch (Exception te) Log.e (LOG_TAG, "Exception:" + te); 

Dans le bloc try, récupérez le scénario de l'utilisateur sous forme d'objet List:

 // récupérer les nouveaux tweets de la chronologie de la maison sous forme de liste List homeTimeline = timelineTwitter.getHomeTimeline ();

La chronologie récupérée est une liste d'objets Status. Chaque objet Status contient les données pour une seule mise à jour de tweet. Nous devons maintenant parcourir les nouveaux tweets et les insérer dans la base de données:

 // itère à travers les nouvelles mises à jour de statut pour (Status statusUpdate: homeTimeline) // appelle la méthode getValues ​​de la classe d'assistance de données en transmettant les nouvelles mises à jour ContentValues ​​timelineValues ​​= NiceDataHelper.getValues ​​(statusUpdate); // si la base de données contient déjà les mises à jour, elles ne seront pas insérées. niceDB.insertOrThrow ("home", null, timelineValues); // confirme que nous avons de nouvelles mises à jour statusChanges = true; 

Notez que nous appelons la méthode "getValues" de la classe NiceDataHelper, qui est statique. La méthode "getValues" prend les objets Twitter Status et récupère les données pertinentes pour notre base de données, à savoir l'ID tweet, le texte, le nom d'écran, l'heure et l'URL de l'image de profil, qui sont tous contenus dans chaque instance Status. La méthode les renvoie sous forme d'ensembles de valeurs pouvant être insérés dans la base de données, ce que nous faisons ici. Comme il y a de nouveaux tweets, nous avons défini le drapeau "statusChanges" sur true.

Après le blocage, nous envoyons une diffusion à l'activité principale uniquement s'il y a de nouveaux tweets à afficher:

 // si nous avons de nouvelles mises à jour, envoyez une diffusion if (statusChanges) // elle devrait être reçue dans la classe de scénario principale sendBroadcast (new Intent ("TWITTER_UPDATES")); 

Nous nous en occuperons plus tard dans la classe d'activité principale. Enfin, après cette instruction if et toujours dans la méthode "run", demandez à Android de rappeler la méthode "run" après le délai choisi:

 // retarde la récupération des nouvelles mises à jour niceHandler.postDelayed (this, FETCH_DELAY);

En haut de votre classe TimelineService, ajoutez une autre variable d'instance pour cette nouvelle classe:

 / ** objet de thread de mise à jour * / private TimelineUpdater niceUpdater;

Étape 3: Démarrer l'objet exécutable

Nous pouvons maintenant gérer la méthode "TimelineService" pour le démarrage du service. De retour dans la classe Service (en dehors de la nouvelle classe Runnable), ajoutez la méthode "onStartCommand":

 @Override public int onStartCommand (intention, intentions, int, startId) super.onStart (intent, startId); // récupère le gestionnaire niceHandler = new Handler (); // crée une instance de la classe du programme de mise à jour niceUpdater = new TimelineUpdater (); // ajout à la file d'attente niceHandler.post (niceUpdater); // return sticky return START_STICKY; 

Ici, nous appelons la méthode de la superclasse et renvoyons une valeur entière standard. Nous instancions également le gestionnaire et la nouvelle classe Runnable. Le gestionnaire ajoute le fichier exécutable à la file d'attente de processus de sorte que sa méthode "run" s'exécute.

Maintenant, tout ce dont nous avons besoin pour finir la classe Service est d'implémenter la méthode destroy:

 @Override public void onDestroy () super.onDestroy (); // arrête la mise à jour niceHandler.removeCallbacks (niceUpdater); niceDB.close (); 

Étape 4: Recevoir les émissions

De retour dans la classe d'activité principale de l'application, nous pouvons maintenant démarrer le service et recevoir les diffusions résultantes. Ajoutez la variable d'instance suivante en haut de votre classe "TwitNiceActivity":

 / ** Broadcast receiver lorsque de nouvelles mises à jour sont disponibles * / private BroadcastReceiver niceStatusReceiver;

Vous aurez besoin de la déclaration d'importation suivante:

 importer android.content.BroadcastReceiver;

Ajoutez une nouvelle classe interne à votre classe d'activité principale pour recevoir des diffusions, en veillant à l'ajouter en dehors de l'une des méthodes mais dans la déclaration de la classe d'activité:

 / ** * Classe pour implémenter la réception de diffusion pour les nouvelles mises à jour * / class TwitterUpdateReceiver étend BroadcastReceiver 

Cette classe va faire une chose: recevoir des émissions - implémentez donc la méthode "onReceive" à l'intérieur:

 @Override public void onReceive (contexte de contexte, intention de l'intention) 

Dans la méthode, nous allons réduire la taille de la base de données en supprimant certains enregistrements dès que de nouveaux tweets sont disponibles:

 int rowLimit = 100; if (DatabaseUtils.queryNumEntries (timelineDB, "home")> rowLimit) String deleteQuery = "SUPPRIMER DE LA maison WHERE" + BaseColumns._ID + "NOT IN" + (SELECT "+ BaseColumns._ID +" FROM maison ORDER BY "+" update_time DESC "+" limit "+ rowLimit +") "; timelineDB.execSQL (deleteQuery); 

Dans ce cas, nous limitons le tableau à 100 lignes, mais vous pouvez bien sûr le remplacer par un nombre de votre choix. La requête supprime tous les enregistrements sauf les 100 plus récents de la table..

Ajoutez l'importation suivante à la classe:

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

Nous devons maintenant interroger la base de données et mettre à jour les vues de l'interface utilisateur à l'aide de l'adaptateur:

 timelineCursor = timelineDB.query ("home", null, null, null, null, null, "update_time DESC"); startManagingCursor (timelineCursor); timelineAdapter = new UpdateAdapter (contexte, timelineCursor); homeTimeline.setAdapter (timelineAdapter);

Notez que nous utilisons un processus similaire à celui de la méthode "setupTimeline". Lorsque l'utilisateur a déjà exécuté l'application au moins une fois, lors de son lancement, il verra les données existantes lors de l'extraction de nouvelles données. Dès que les nouvelles données sont disponibles, les vues seront mises à jour pour les afficher. Naturellement, la vitesse à laquelle cela se produira dépendra de la connectivité réseau de l'utilisateur..


Étape 5: Démarrer le service

Terminons la méthode "setupTimeline". Après la dernière ligne sur laquelle vous avez instancié la classe UpdateAdapter, avant la fin du bloc try, ajoutez ce qui suit pour définir l'adaptateur sur la timeline:

 // Ceci fera que l'application remplira les nouvelles données de mise à jour dans la vue de chronologie homeTimeline.setAdapter (timelineAdapter);

Créez ensuite une instance de votre classe Broadcast Receiver et enregistrez-la pour recevoir les mises à jour de la classe Service:

 // instancie la classe du récepteur pour savoir quand de nouvelles mises à jour sont disponibles niceStatusReceiver = new TwitterUpdateReceiver (); // s'inscrire aux mises à jour registerReceiver (niceStatusReceiver, new IntentFilter ("TWITTER_UPDATES"));

Notez que la chaîne que nous fournissons au constructeur IntentFilter ici correspond à la chaîne que nous utilisons lors de l'envoi de la diffusion dans la classe TimelineService Runnable..

Vous aurez besoin de l'importation suivante:

 importer android.content.IntentFilter;

Enfin, démarrez le service en passant le nom de la classe:

 // démarre le service pour les mises à jour maintenant this.getApplicationContext (). startService (new Intent (this.getApplicationContext (), TimelineService.class));

Avant de terminer, implémentons la méthode destroy pour la classe principale d'activité car elle concerne les objets que nous avons utilisés ici:

 @Override public void onDestroy () super.onDestroy (); try // arrêtez le service de mise à jour stopService (nouvelle intention (this, TimelineService.class)); // supprime le récepteur enregistrer unregisterReceiver (niceStatusReceiver); // ferme la base de données timelineDB.close ();  catch (Exception se) Log.e (LOG_TAG, "impossible d'arrêter le service ou le destinataire"); 

Chaque fois que vous gérez des bases de données et des services, il est important de ne pas gaspiller des ressources en les laissant actives lorsque l'application ne s'exécute pas réellement. Ici, nous arrêtons le service, annulons l'enregistrement du destinataire et fermons la base de données. Lorsque l'application est relancée, celles-ci seront toutes relancées..


Suivant

Nous avons maintenant implémenté l'affichage des tweets de la chronologie de la maison, en les récupérant à intervalles fixes via un service et en détectant leur récupération à l'aide de diffusions. Dans le dernier tutoriel, nous allons implémenter les tweets, les retweet et les réponses. Cela impliquera la mise en place d'une nouvelle activité de tweet et des boutons retweet / réponse dans chaque mise à jour de la chronologie principale..