Sylvain-a Posté(e) 3 octobre 2011 Share Posté(e) 3 octobre 2011 Salut à tous, Ca fait un moment que je ne suis pas venu sur le forum, mais la j'ai grand besoin de votre aide :). Donc, je conçois une app qui utilise un timer. Comme c'est un minuteur, je dois mettre a jour le texte d'un TextView disponible dans l'activity concernée. Seulement, lorsque je tente de faire une mise à jour "indirectement", ça m'indique que le Thread n'est pas le bon. Comme des lignes d'exemple valent mieux qu'un long discours : public class MonActivity extends Activity{ private TextView txt=null; public void onCreate(Bundle instance){ /*Blabla*/ Timer t=new Timer(); t.shedule(new MyTimerTask(this), 0, 1000); // on lance le timer, qui a une période de 1s TextView txt=findViewById(monId); } public void update(){ txt.setText("Mon temps"); } } public class MyTimerTask{ private MonActivity a=null; public MyTimerTask(MonActivity a){ this.a=a; } public void run(){ a.update(); } } Donc, je récapitule ce qu'il est censé se passer : -Je démarre mon Activity qui démarre le Timer -> je passe mon Activity en argument du TimerTask -Chaque seconde, la fonction update de MonActivity est appelée et met a jour le texte J'ai essayé de passer le Thread en argument, mais je trouve pas de moyen de l'utiliser. Je vous remercie par avance pour votre aide. Cordialement. PS : j'ai cherché sur le forum & google & faq java & autres, mais n'ai pas vraiment trouvé ce que je cherchais. Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 4 octobre 2011 Share Posté(e) 4 octobre 2011 Le problème, c'est que le Timer tourne dans son propre thread, et essaie de mettre à jour l'UI. Et sous Android, il est interdit de mettre à jour l'UI depuis un autre thread que le principal Pour résoudre ton problème, tu peux utiliser runOnUiThread, qui te permettra d'exécuter un traitement dans le thread principal depuis un autre thread Change le corps de la méthode run de ta MyTimerTask public void run() { a.runOnUiThread(new Runnable() { public void run() { a.update(); } }); } 1 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Sylvain-a Posté(e) 4 octobre 2011 Auteur Share Posté(e) 4 octobre 2011 Merci, ça fonctionne en effet, j'avais aperçu cette méthode lors de mes recherches mais je me demandais si il y avait plus "souple". (En réalité, "monActivity" peut être une activity ou un service donc j'avais créé une interface, et le runOnUiThread est alors indisponible). En attendant de trouver j'ai tout de même implémenté la méthode que tu m'as proposé :) Encore merci :) Si quelqu'un a d'autres propositions je vous remercie d'avance :). Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 4 octobre 2011 Share Posté(e) 4 octobre 2011 Si le traitement à effectuer par le Timer est porté par un Service, tu n'auras pas ce problème d'être obligé de passer par le thread de l'UI, vu que dans un Service, tu n'as pas d'IHM. Dans ce cas, cela devrait fonctionner sans runOnUiThread (hors problématique éventuelle de synchronisation d'accès aux données portées par le Service) Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Sylvain-a Posté(e) 4 octobre 2011 Auteur Share Posté(e) 4 octobre 2011 Ah c'est bon a savoir, je teste ça ce soir justement (le service). En réalité j'ai besoin des deux solutions car l'utilisation du service est au choix de l'utilisateur. Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Sylvain-a Posté(e) 6 octobre 2011 Auteur Share Posté(e) 6 octobre 2011 (modifié) Re salut à tous, Je réécris sur ce topic pour pas trop polluer le forum. Je tente en vain depuis 3 jours de mettre en place une solution à mon problème, sans résultats. Donc voici le souci : Mon activity (la même que précédemment) lance un service. Le service lance un timer. Ce que je cherche à faire c'est récupérer la valeur actuelle du timer via une méthode (jusque la pas de soucis). Le problème, c'est que je veux le faire à des instants précis (en gros, à chaque fois que le timer effectue une action). Je pourrai bien entendu simplement appeler une méthode de mon activity, seulement le service peut aussi être exécuté en tache de fond (donc Lorsque l'activity n'est pas a l'écran). Dans ce cas la, l'activity n'est plus mise à jour jusqu'a ce qu'elle soit résumée. Seulement je ne trouve pas comment envoyer des informations depuis mon service vers mon activity (Un peu dans la même idée que les évènements). J'ai regardé du côté de bind et de ServiceConnection... mais sans trouver ce que je cherche. Avez vous une idée? Encore merci :). Modifié 6 octobre 2011 par Sylvain-a Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 7 octobre 2011 Share Posté(e) 7 octobre 2011 Utilise le mécanisme des BroadcastReceiver Il te faut définir un message, qui sera privé à ton application, qui sera envoyé par ton Service (ou plus exactement par le Timer de ton Service) via un sendBroadcast, message qui sera reçu par un BroadcastReceiver, ce dernier n'étant pas déclaré dans le AndroidManifest, mais instancié et enregistré uniquement lorsque ton Activity est affichée; tu recevras donc ton message dans ton Activity, et sera alors capable de la mettre à jour Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Sylvain-a Posté(e) 7 octobre 2011 Auteur Share Posté(e) 7 octobre 2011 Merci :) je vais tenter cette solution. J'avais mis en place un systeme de listener/receiver mais je trouvais que ce n'était pas très propre. Je teste la et je posterai un exemple de solution au cas ou ça peut aider quelqu'un :) Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 7 octobre 2011 Share Posté(e) 7 octobre 2011 Le BroadcastReceiver peut être assimilé à un système de listener/receiver. Ta solution n'était donc pas une mauvaise solution ;) Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Sylvain-a Posté(e) 7 octobre 2011 Auteur Share Posté(e) 7 octobre 2011 Voici un exemple schématique de solution :) class MonActivity extends Activity{ public void onCreate(Bundle instance){ /*blabla*/ MonReceiver= receiver=new MonReceiver(); registerReceiver(receiver, new IntentFilter("monaction")); } } class MonReceiver(){ public void onReceive(Context c, Intent i){ /*blabla*/ } } class MonService(){ public void update(){ Intent i=new Intent(); i.setAction("monaction") sendBroadcast(i); } } Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 7 octobre 2011 Share Posté(e) 7 octobre 2011 Ne pas oublier de désenregistrer (méthode unregisterReceiver) le BroadcastReceiver lorsque l'Activity n'est plus active, sinon tu vas avoir des surprises (ton Service envoie un broadcast alors que l'Activity n'est plus présente, le Receiver, toujours enregistré le reçoit et essaie de mettre à jour l'IHM de l'Activity, et badaboum, ça plante ;) ) Je serai toi, j'enregistrerai plutôt le receiver dans le onResume de l'Activity, et le désenregistrerai dans le onPause, le Receiver ne sera actif que lorsque l'Activity a le focus Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Sylvain-a Posté(e) 8 octobre 2011 Auteur Share Posté(e) 8 octobre 2011 (modifié) Merci, en réalité c'est ce que j'ai fait, je n'ai juste pas détaillé dans l'exemple. J'enregistre bien dans le onResume et desenregistre dans le onPause. Je tue le service lorsque l'activité est stoppée. Sinon, une autre question : Comment accéder aux fichiers xml depuis un service? Par exemple, j'aimerai la valeur de app_name dans strings (Donc R.string.app_name). Seulement, ça a l'air inaccessible depuis le service (avec eclipse en tout cas :() Y'a t'il un moyen? Modifié 8 octobre 2011 par Sylvain-a Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 10 octobre 2011 Share Posté(e) 10 octobre 2011 Tu veux faire quoi ? Récupérer la valeur de la chaine de caractères identifiée par R.string.app_name ? Rien de plus simple String s = getString(R.string.app_name); depuis un Service ou une Activity (getString est une méthode de la classe Context dont héritent Activity et Service) Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Sylvain-a Posté(e) 11 octobre 2011 Auteur Share Posté(e) 11 octobre 2011 Non, en réalité, la valeur R.string.app_name n'a pas l'air accessible depuis mon service, c'est ça mon problème Et je comprends pas pourquoi ^^ Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 11 octobre 2011 Share Posté(e) 11 octobre 2011 Et là, je ne comprends plus ton problème... Tu as quoi ? une erreur de compilation ? à l'exécution ? Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Recommended Posts
Rejoignez la conversation
Vous pouvez poster maintenant et vous enregistrez plus tard. Si vous avez un compte, connectez-vous maintenant pour poster.