Comment mettre à jour App Widget avec la vue liste d’une activité

Je sais que cela a souvent été demandé, mais j’ai parcouru la documentation de fond en comble, lu toutes les réponses ici et aucune d’entre elles n’a aidé. Pour être honnête, chaque réponse dit quelque chose de différent sur la façon d’aborder cela.

Revenons maintenant à ma question. Je souhaite mettre à jour la vue de la liste des widgets à partir d’une activité et j’ai créé WidgetProvider#sendUpdateBroadcastToAllWidgets() à cette fin, que j’appelle depuis l’activité.

Il appelle finalement onUpdate() pour que la diffusion soit reçue correctement. Mais les vues ne sont pas rafraîchies.

J’ai également essayé d’appeler AppWidgetManager#notifyAppWidgetViewDataChanged() et d’actualiser les données dans WidgetFactory#onDataSetChanged() mais la méthode n’a jamais été appelée.

Je suppose donc que tout cela ne fonctionne pas car la fabrique de vues distantes est mise en cache, mais je ne sais pas comment y remédier de manière fiable. Des pensées?

Et qu’en est-il des contextes? Je dois toujours en fournir un, mais peu importe lequel. Est-ce que ça importe?

Merci

FOURNISSEUR

 public class WidgetProvider extends AppWidgetProvider { public static void sendUpdateBroadcastToAllWidgets(Context context) { int allWidgetIds[] = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, WidgetProvider.class)); Intent intent = new Intent(context, WidgetProvider.class); intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds); context.sendBroadcast(intent); } @Override public void onUpdate(Context context, AppWidgetManager widgetManager, int[] widgetIds) { for (int id : widgetIds) { updateWidget(context, widgetManager, id); } super.onUpdate(context, widgetManager, widgetIds); } @Override public void onDeleted(Context context, int[] widgetIds) { WidgetPreferences prefs = new WidgetPreferences(context); for (int widgetId : widgetIds) { prefs.getWidgetPreferences(widgetId).edit().clear().commit(); } super.onDeleted(context, widgetIds); } private static void updateWidget(Context context, AppWidgetManager widgetManager, int widgetId) { RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget); // set list adapter Intent serviceIntent = new Intent(context, WidgetService.class); serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME))); views.setRemoteAdapter(android.R.id.list, serviceIntent); views.setEmptyView(android.R.id.list, android.R.id.empty); // set widget title WidgetDataCategory category = new WidgetPreferences(context).getSavedCategory(widgetId); views.setTextViewText(R.id.titleText, context.getSsortingng(category.titleResourceId())); // set onclick listener - we create a pending intent template and when an items is clicked // the intent is filled with missing data and sent Intent startActivityIntent = new Intent(context, SimplePersonDetailActivity.class); startActivityIntent.setData(Uri.parse(startActivityIntent.toUri(Intent.URI_INTENT_SCHEME))); startActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivityIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, startActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT); views.setPendingIntentTemplate(android.R.id.list, pendingIntent); // all hail to Google widgetManager.updateAppWidget(widgetId, views); } } 

USINE

 public class WidgetFactory implements RemoteViewsService.RemoteViewsFactory { private Context context; private List people = new ArrayList(); public WidgetFactory(Context context, Intent intent) { this.context = context; int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); if (widgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { WidgetPreferences prefs = new WidgetPreferences(context); WidgetDataCategory category = prefs.getSavedCategory(widgetId); int numberOfItemsToShow = prefs.getSavedLimit(widgetId); people = category.filterAndSlice(new PersonDao(context).getAllForGroup(Constants.SIMPLE_GROUP_ID), numberOfItemsToShow); } } @Override public void onCreate() {} @Override public void onDataSetChanged() {} @Override public void onDestroy() {} @Override public int getCount() { return people.size(); } @Override public RemoteViews getViewAt(int position) { Person person = people.get(position); BigDecimal amount = ListViewUtil.sumTransactions(new TransactionDao(context).getAllForPerson(person)); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.item_widget); remoteViews.setTextViewText(R.id.nameText, person.getName()); remoteViews.setTextViewText(R.id.amountText, MoneyFormatter.withoutPlusPrefix().format(amount)); // fill details for the onclick listener (updating the pending intent template // set in the WidgetProvider) Intent listenerIntent = new Intent(); listenerIntent.putExtra(Constants.PERSON_ID, people.get(position).getId()); remoteViews.setOnClickFillInIntent(R.id.widgetItem, listenerIntent); return remoteViews; } @Override public RemoteViews getLoadingView() { return null; } @Override public int getViewTypeCount() { return 1; } @Override public long getItemId(int position) { return position; } @Override public boolean hasStableIds() { return true; } } 

Je dirais que la méthode notifyAppWidgetViewDataChanged devrait fonctionner pour vous.

Vous devez créer AppWidgetManager et obtenir appWidgetIds , puis simplement appeler notifyAppWidgetViewDataChanged sur votre AppWidgetManager .

Pseudo-code,

 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); int appWidgetIds[] = appWidgetManager.getAppWidgetIds( new ComponentName(context, WidgetProvider.class)); appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.listview); 

Pour plus d’informations, vous pouvez consulter ma réponse ici, qui contient une démo sur github.

J’ai eu une implémentation de widget dans mon projet. J’ai modifié le code ci-dessous afin que les données du widget puissent être modifiées à partir de l’une de mes activités dans l’application. Afficher uniquement le code essentiel pour votre cas d’utilisation spécifique.

Ici, j’ai un bouton avec du texte dans mon widget. En cliquant sur le bouton de connexion dans mon activité, je modifie le texte du bouton dans mon widget

Ci-dessous ma classe AppWidgetProvider.java

 public class AppWidgetTrackAsset extends AppWidgetProvider{ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // Perform this loop procedure for each App Widget that belongs to this provider final int N = appWidgetIds.length; for (int i=0; i 

Ci-dessous, mon activité où je mets à jour le texte du bouton du widget en cliquant sur mon bouton de connexion.
LoginActivity.java

 public class LoginActivity extends AppCompatActivity implements View.OnClickListener{ Button loginButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); loginButton=(Button)findViewById(R.id.loginButton); loginButton.setOnClickListener(this); } @Override public void onClick(View v) { if(v.getId() == R.id.loginButton){ updateWidget(); } } private void updateWidget(){ try { Intent updateWidget = new Intent(this, AppWidgetTrackAsset.class); updateWidget.setAction("update_widget"); PendingIntent pending = PendingIntent.getBroadcast(this, 0, updateWidget, PendingIntent.FLAG_CANCEL_CURRENT); pending.send(); } catch (PendingIntent.CanceledException e) { Log.e(Constants.UI_LOG,"Error widgetTrial()="+e.toSsortingng()); } } } 

La disposition pour le widget de l'application va comme ceci

app_widget_track_asset.xml

    

Ci-dessous la partie essentielle du fichier manifeste pour le widget