Bonjour,
Il y a quelques jours, j'ai eu une problématique à résoudre (3 services différents à regrouper en 1 widget), et depuis je me suis lancé dans le développement d'un appWidget, en java, pour android.
Voilà ce que je veux :
- Je pose mon widget sur l'écran
- Il va dans le class qui update
- Si j'ai une connexion internet, je récupère les données depuis une API (dans un autre thread)
- J'applique mes nouvelles données sur mon UI (depuis mon autre thread)
Actuellement, voilà ce qu'il se passe :
- Je choisi de mettre mon widget sur l'écran.
- Mon widget lance la class qui hérite d'AppWidgetProvider sur la méthod onUpdate()
- Dans cette méthod onUpdate(), je vérifie que j'ai une connexion internet
- Si j'ai une connexion internet, je vais dans une classe qui hérite d'AsyncTask pour récupérer mes données
- Je récupère mes données depuis internet dans le doInBackground()
- Si ça à marché, dans le onPostExecute(), j'applique les nouveaux textes sur mon UI.
- J'actualise mon widget
- Si j'ai une connexion internet, je vais dans une classe qui hérite d'AsyncTask pour récupérer mes données
Le problème est le suivant : comment modifier mon layout (un textView) depuis le thread de la classe qui hérite d'AsyncTask, sachant que je n'ai pas de context ?
Voici mon code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /*Manifest*/ <application android:allowBackup="true" android:icon="@drawable/app_icon" android:label="@string/app_name" > <receiver android:name=".TorrentInfoWidget" > <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_definition" /> </receiver> </application> |
1 2 3 4 5 | /* Petite partie du widget_layout */ <TextView android:id="@+id/widget_peers_value" /*...*/ android:text="@string/widget_peers_value" /> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | /* La class qui herite d'AppWidgetProvider */ package ovh.krostar.torrentinfo; import java.util.ArrayList; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.AsyncTask; import android.util.Log; public class TorrentInfoWidget extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { ConnectivityManager connectionManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo(); if (networkInfo == null || networkInfo.isConnected() == false) { Log.w("ERROR", "Connexion impossible"); return ; } new bgThread().execute(Integer.toString(1), "core.get_session_status", "num_peers"); Log.i("TorrentInfo", "Widget Updated"); } private class bgThread extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... p) { int id = Integer.parseInt(p[0]); String method = p[1]; ArrayList<String> params = new ArrayList<String>(); int nLoop = 0; for (String param : p) { if (nLoop >= 2) params.add(param); nLoop++; } DelugeRPC delugeInfo = new DelugeRPC(); String delugeResponse = delugeInfo.sendCommand(id, method, params); return (delugeResponse); } @Override protected void onPostExecute(String result) { if (result != null) { Log.i("RESULT", result); //Ici je change la valeur de ma textview } else Log.i("RESULT", "NULL"); } } } |
Ma classe delugeRPC retourne une chaine de caractères.
J'avais pensé à getView().findViewById(id.widget_peers_value)
, mais il me dit que je n'ai pas la fonction getView()
par-ce que je n'hérite pas d'un module qui me la propose, et idem avec juste findViewById()
Au début, je voulais faire tout directement dans l'onUpdate()
1 2 3 4 5 6 7 8 | RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout); int peersInfos = delugeInfo.getPeersInfos(); views.setTextViewText(R.id.widget_peers_value, Integer.toString(peersInfos)); ComponentName myWidget = new ComponentName(context, TorrentInfoWidget.class); AppWidgetManager manager = AppWidgetManager.getInstance(context); manager.updateAppWidget(myWidget, views); |
Et ça marchait très bien, sauf que je ne peux pas appeler ma classe qui va chercher la donnée sur internet, par-ce que je ne peux pas faire de requètes sur internet depuis mon thread UI…
Je suppose que je ne fais pas les choses comme il faut, si vous voyez des choses crades qui ne se font pas comme ça, et / ou si vous savez comment faire pour ma textView, je suis preneur
Cordialement, Krostar.