emulienfou Posté(e) 24 février 2011 Share Posté(e) 24 février 2011 Bonjour, nouveau dans le développement sous Android, je souhaiterai récupérer la valeur d'une variable depuis une classe qui implémente Runnable et qui est exécutée dans un Thread ! Voici mon code : Thread thread1 = new Thread(new IcyStreamMeta(conn)); IcyStreamMeta icy = new IcyStreamMeta(conn); thread1.start(); Log.i("TITLE", icy.streamTitle); Je suppose que je n'ai pas le droit de faire cela car j'ai une erreur dès que j'affiche mon message Log : java.lang.NullPointerException: println needs a message Cordialement ! Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 25 février 2011 Share Posté(e) 25 février 2011 Ce code me paraîtrait plus logique... (parce que dans ton code, l'instance d'IcyStreamMeta représentée par la variable icy n'a aucun lien avec l'instance manipulée par le thread...) IcyStreamMeta icy = new IcyStreamMeta(conn); Thread thread1 = new Thread(icy); thread1.start(); Log.i("TITLE", icy.streamTitle); Lien vers le commentaire Partager sur d’autres sites More sharing options...
emulienfou Posté(e) 25 février 2011 Auteur Share Posté(e) 25 février 2011 Merci bien, je voulais maintenant savoir 2 choses : Dès que je lance mon application, celle-ci affiche la valeur de streamTitle. Je voudrais savoir comment faire pour avoir la valeur actuelle car celle-ci affiche uniquement la valeur récupérée au lancement de l'application. Je voudrais avoir une boucle d'écoute qui affiche mon texte dès que le texte actuelle change ? (surement une boucle mais comment ?) Comment faire pour actualiser mon texte dans un TextView ? Cordialement Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 25 février 2011 Share Posté(e) 25 février 2011 Plutôt que d'utiliser un Thread, tu peux utiliser un AsyncTask, qui t'offre la possibilité d'envoyer des informations depuis le thread de l'AsyncTask vers celui de l'UI, ce qui te permettra d'actualiser ton affichage Pour mettre à jour le texte d'un TextView, as-tu essayé setText ? ;) Lien vers le commentaire Partager sur d’autres sites More sharing options...
Lord Yu Posté(e) 25 février 2011 Share Posté(e) 25 février 2011 Merci bien, je voulais maintenant savoir 2 choses : Dès que je lance mon application, celle-ci affiche la valeur de streamTitle. Je voudrais savoir comment faire pour avoir la valeur actuelle car celle-ci affiche uniquement la valeur récupérée au lancement de l'application. Je voudrais avoir une boucle d'écoute qui affiche mon texte dès que le texte actuelle change ? (surement une boucle mais comment ?) Comment faire pour actualiser mon texte dans un TextView ? Cordialement Il va te falloir créer un listener je pense. Ca t'évite d'avoir une boucle qui tourne tout le temps alors que c'est pas indispensable. Donc tu fais ton propre listener qui au changement du texte appellera une méthode de ta classe, méthode affichant ton texte. Lien vers le commentaire Partager sur d’autres sites More sharing options...
emulienfou Posté(e) 25 février 2011 Auteur Share Posté(e) 25 février 2011 Merci bien, j'ai un autre problème maintenant, cela fonctionne sans problème en utilisant AsyncTask ! Par contre, j'ai 2 classes qui utilise AsyncTask, je fais donc ceci pour les appeler : new IcyAsyncMeta().execute(url); new IcyAsyncTitle().execute(url); Mais, le résultat s'affiche uniquement dès que la classe IcySyncTitle à fini son traitement qui est plus long que dans la classe IcyAsyncMeta, normale ? et comment résoudre cela ? Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 25 février 2011 Share Posté(e) 25 février 2011 Comportement normal ou pas, difficile de savoir... Tout dépend de la façon dont tu as implémenté tes AsyncTask. Comment fais-tu la notification de mise à jour ? Par un publishProgress ? As-tu implémenté la méthode onProgressUpdate ? Lien vers le commentaire Partager sur d’autres sites More sharing options...
emulienfou Posté(e) 25 février 2011 Auteur Share Posté(e) 25 février 2011 Non, je n'ai ni utiliser publishProgress() ni implémenté la méthode onProgressUpdate() !!! Sinon j'ai pas très bien compris l'histoire d’implémentation de la méthode onProgressUpdate() qui est déclarée dans mon code mais vide ! Sinon pour publishProgress si j'ai bien compris cela permet d'afficher une barre de progression ? Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 25 février 2011 Share Posté(e) 25 février 2011 Ben, c'est normal alors que cela ne marche pas ;) Ce que tu veux faire, c'est, à différent moment de l'exécution de ton traitement dans ton thread, de mettre à jour une TextView. Or, depuis un thread autre que celui qui gère l'IHM, tu ne peux pas mettre à jour un élément de l'IHM, c'est interdit. Les AsyncTask offrent un mécanisme pour pouvoir malgré tout le faire via les méthodes onPreExecute/onPostExecute et onProgressUpdate (qui seront appelées dans le thread de l'IHM) - onPreExecute est appelée avant de lancer le thread de l'AsyncTask - onPostExecute est appelée après que le thread se soit terminé - onProgressUpdate est appelée lorsque tu as appelé la méthode publishProgress (depuis doInBackground). Le couple publishProgress/onProgressUpdate peut être vu comme un mécanisme de communication entre le thread de l'AsyncTask et le thread principal de l'IHM Dans ton cas, il faut donc que tu fasses appel, dans ton traitement implémenté dans doInBackground, à la méthode publishProgress en lui passant la valeur que tu souhaites afficher quand celle-ci a été modifiée, valeur que tu vas récupérer en paramètre de la méthode onProgressUpdate dans laquelle tu peux effectivement mettre à jour ta TextView Lien vers le commentaire Partager sur d’autres sites More sharing options...
emulienfou Posté(e) 25 février 2011 Auteur Share Posté(e) 25 février 2011 J'ai très bien compris en faite comment utiliser la méthode publishProgress, je ne sais pas quoi mettre entre les parenthèse car ce que j'affiche sur mon interface et le code suivant : Scanner_Android.tv10.setText(getTitle()); public class IcyAsyncTitle extends AsyncTask<URL, Integer, Long> { private URLConnection conn; private Map<String, String> metadata; @Override protected Long doInBackground(URL... urls) { // TODO Auto-generated method stub Log.i("IcyAsyncTitle", "doInBackground"); try { conn = urls[0].openConnection(); conn.setRequestProperty ("Icy-Metadata", "1"); conn.setRequestProperty("Connection", "close"); conn.setRequestProperty("Accept", null); conn.connect(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } publishProgress(); return null; } protected void onProgressUpdate(Integer... progress) { Log.i("IcyAsyncTitle", "onProgressUpdate"); try { Scanner_Android.tv10.setText(getTitle()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override protected void onPostExecute(Long result) { Log.i("IcyAsyncTitle", "onPostExecute"); } public String getTitle() throws IOException { Map<String, String> data = getMetadata(); if (!data.containsKey("StreamTitle")) return ""; return data.get("StreamTitle"); } public Map<String, String> getMetadata() throws IOException { if (metadata == null) { refreshMeta(); } return metadata; } public void refreshMeta() throws IOException { retreiveMetadata(); } private void retreiveMetadata() throws IOException { try { int metaDataOffset = 0; Map<String, List<String>> headers = conn.getHeaderFields(); InputStream stream; stream = conn.getInputStream(); if (headers.containsKey("icy-metaint")) { // Headers are sent via HTTP metaDataOffset = Integer.parseInt(headers.get("icy-metaint").get(0)); } else { // Headers are sent within a stream StringBuilder strHeaders = new StringBuilder(); char c; while ((c = (char)stream.read()) != -1) { strHeaders.append(c); if (strHeaders.length() > 5 && (strHeaders.substring((strHeaders.length() - 4), strHeaders.length()).equals("\r\n\r\n"))) { // end of headers break; } } // Match headers to get metadata offset within a stream Pattern p = Pattern.compile("\\r\\n(icy-metaint):\\s*(.*)\\r\\n"); Matcher m = p.matcher(strHeaders.toString()); if (m.find()) { metaDataOffset = Integer.parseInt(m.group(2)); } } // In case no data was sent if (metaDataOffset == 0) { return; } // Read metadata int b; int count = 0; int metaDataLength = 4080; // 4080 is the max length boolean inData = false; StringBuilder metaData = new StringBuilder(); // Stream position should be either at the beginning or right after headers while ((b = stream.read()) != -1) { count++; // Length of the metadata if (count == metaDataOffset + 1) { metaDataLength = b * 16; } if (count > metaDataOffset + 1 && count < (metaDataOffset + metaDataLength)) { inData = true; } else { inData = false; } if (inData) { if (b != 0) { metaData.append((char)B); } } if (count > (metaDataOffset + metaDataLength)) { break; } } // Set the data metadata = IcyAsyncTitle.parseMetadata(metaData.toString()); // Close stream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static Map<String, String> parseMetadata(String metaString) { Map<String, String> metadata = new HashMap(); String[] metaParts = metaString.split(";"); Pattern p = Pattern.compile("^([a-zA-Z]+)=\\'([^\\']*)\\'$"); Matcher m; for (int i = 0; i < metaParts.length; i++) { m = p.matcher(metaParts[i]); if (m.find()) { metadata.put((String)m.group(1), (String)m.group(2)); } } return metadata; } } Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 26 février 2011 Share Posté(e) 26 février 2011 Au vu de ton implémentation, utiliser un AsyncTask ne sert pas à grand chose, puisqu'il n'y a que l'ouverture de la connexion qui est faite dans le thread (dans doInBackground). La majorité du traitement est effectué dans getMetadata et consorts, déclenchée depuis le onProgressUpdate qui elle est exécutée dans le thread principal Qui plus est, je ne comprends ce que tu veux afficher; tu disais vouloir mettre à jour le TextView avec une donnée qui aurait évolué au cous de l'exécution du thread, or, de ce que j'en comprends, la seule donnée affichée ne peut l'être que lorsque tout le traitement est terminé... Mais, pour expliciter un peu mieux le fonctionnement d'AsyncTask, si tu avais un traitement long, avec le besoin de notifier de l'évolution du traitement en affichant une valeur reflétant cette évolution, voila ce que tu pourrais faire: public MonAsyncTask extends AsyncTask<URL, String, Void> { public void doInBackground(URL... urls) { // Ici est implémenté le traitement à effectuer dans le thread // publishProgress peut être utilisée pour envoyer une valeur que l'on souhaite afficher, en fonction de l'évolution du traitement publishProgress("première étape"); // Suite du traitement long publishProgress("deuxième étape"); // Suite du traitement publishProgress("troisième étape"); // blah blah blah } public onProgressUpdate(String... progress) { monTextView.setText(progress[0]); } } ce qui aurait pour effet d'afficher "première étape", "deuxième étape", etc... en fonction de l'avancée du traitement qui se déroule dans le thread Lien vers le commentaire Partager sur d’autres sites More sharing options...
emulienfou Posté(e) 26 février 2011 Auteur Share Posté(e) 26 février 2011 Merci bien pour ces explications, je vais t'expliquer, actuellement je récupère le titre de la chanson actuelle depuis le flux stream mais ce dont je voudrais c'est un Listener qui me permettrait de rafraîchir le texte via un setText(); dès que le titre de la chanson change au niveau du flux en stream !!! Lien vers le commentaire Partager sur d’autres sites More sharing options...
chpil Posté(e) 28 février 2011 Share Posté(e) 28 février 2011 Pour récupérer le titre de la chanson depuis le stream, je suppose que tu as pour cela un thread qui fait le décodage du stream en tâche de fond ? Ne peux-tu pas transformer ce thread en un AsyncTask, et faire comme je te l'indiquais, via publishProgress/onProgressUpdate ? Lien vers le commentaire Partager sur d’autres sites More sharing options...
Recommended Posts
Archivé
Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.