11
votes

L'application widget SettimageViewuri ne met pas à jour l'image

i ont un widget application, qui ne contient qu'une seule imageview. i redessiner cette image et le stocker dans la mémoire au format PNG privé des applications puis-je configurer l'image de RemoteViews avec le uri (widget.setImageViewUri (R.id.widget_icon, uri)) au lieu de sendding le bitmap elle-même, parce que très rare situations que je reçois !!! ECHEC TRANSACTION BINDER !!!

le problème est que l'image change au fil du temps, l'image du widget ne change pas. J'ai vérifié le .png enregistré avec l'explorateur racine et il est mis à jour correctement. mais l'image correcte est pas affichée. Chaque widget montre l'image du moment où il a été ajouté à l'écran d'accueil. si je l'utilise setImageViewBitmap (...) cela fonctionne correctement, à l'exception des rares transactions de liant ayant échoué. p>

i mettre à jour le widget d'un service avec la méthode ci-dessous. il ne fonctionne pas sur Android 2.3.7 et aussi avec l'émulateur en cours d'exécution 2.2. quel pourrait être le problème? est-il mis en mémoire cache en quelque sorte p>

public void updateWidget(Context context) {
  // redraws the widget's image
  updateIcon();

  OutputStream stream;
  try {
    stream = context.openFileOutput("icon.png", Context.MODE_WORLD_READABLE);
  }
  catch (FileNotFoundException ex) {
    ex.printStackTrace();
    return;
  }

  m_Icon.compress(CompressFormat.PNG, 100, stream);

  try {
    stream.close();
  }
  catch (IOException ex) {
    ex.printStackTrace();
  }

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

  Intent intent = new Intent(context, MyDialog.class);
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

  PendingIntent clickIntent = PendingIntent.getActivity(context, 0, intent, 0);

  File file = new File(context.getFilesDir().getAbsolutePath() + File.separator + "icon.png");
//      Uri uri = Uri.fromFile(file);

  // update all widgets on home screen
  for (int wid : appWidgetIds) {
    RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.widget);
    widget.setOnClickPendingIntent(R.id.widget_layout, clickIntent);

    // === EDIT ===
    // Uri.fromFile(file); does not work correctly on android 2.1, only 2.2 and up
    // widget's image will disappear
//        widget.setImageViewUri(R.id.widget_icon, uri);
    widget.setImageViewUri(R.id.widget_icon, Uri.parse(file.getPath()));

    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, wid);

    appWidgetManager.updateAppWidget(wid, widget);
  }
}


3 commentaires

Vous utilisez le même URI (même nom de fichier) pour toute votre icône, et c'est le problème. L'URI doit être unique par fichier, ressource ... Le système ne mettez pas à jour le sort et utiliser le premier chargé et son comportement attendu. Je pense qu'il est préférable d'utiliser FileProvider et de fournir plusieurs fichiers. Vous pouvez supprimer obsolète et mettre à jour le widget avec la nouvelle URI.


@Anisbennsir Cette question a été posée et résolue il y a cinq ans ...


Désolé, mais la prime est en état d'ouverture ... Peut-être que mon commentaire sera utile pour le nouvel utilisateur que la réponse acceptée n'est pas la meilleure solution.


3 Réponses :


9
votes

Si le URI reste inchangé, il semble que Android ne mettra pas à jour l'image. J'ai trouvé un peu de hack pour me contenter de cela. Il suffit d'appeler widget.setimagevievuri (r.id.widget_icon, uri.parse ("")); avant widget.setimageviewuri (r.id.widget_icon, uri); .

Ça appelle SetImageViewuri () deux fois, mais semble fonctionner correctement. J'aimerais entendre une meilleure façon de le réparer cependant, car je ressens moi-même cette question.


6 commentaires

J'essayais pour cela, mais j'envoyais une URI NULL, qui vous écrasait. Une chaîne vide a résolu ce problème, merci! Il y a une sorte de cache, qui devrait pouvoir éteindre si nécessaire :(


Réglage d'une uri vide Tout d'abord, puis à corriger l'URI résoue le problème, mais cela donne d'énormes avertissements dans LOGCAT sur chaque mise à jour de widget, car l'URI vide n'est pas valide ... Ce n'est donc qu'une solution partielle, mais cela fonctionne.


Oui, c'est la question avec l'utilisation de cette solution. Comme je l'ai dit, c'est un hack, et j'aimerais aimer trouver une meilleure façon, mais je ne sais tout simplement pas d'une meilleure façon de le faire.


Il y a un autre problème avec cette approche. Le widget scintille sur certaines mises à jour. Je pense que je devrai enregistrer l'image deux fois et chaque fois attribuer l'URI de la deuxième image.


Je n'ai pas vécu cela, je dois dire.


Nous sommes maintenant près de 6 ans de cette réponse, qui a bien fonctionné pour moi jusqu'à présent. Mais récemment, je constate que dans certaines circonstances (Android O + Pixel Launcher), la procédure de mise à jour du widget ne semble jamais atteindre la deuxième charge URI (authentique) ... elle échoue après la première (fausse) uri mais ne charge pas le Uri véritable, laissant ainsi un widget vierge. Avec le même code et le même dispositif et le même système d'exploitation, mais différent de lanceur (NOVA) fonctionnent toujours bien. Cela peut donc être spécifique à un lanceur, mais résulte probablement de l'utilisation d'une solution kludgy comme l'utilisation d'une URI invalide. Il doit y avoir une meilleure façon?



2
votes

Eh bien, il ressemble à SetImageViewuri caches images et ne les rafraîchit pas si le même nom a le même nom.

Pas la solution la plus élégante mais cela fonctionne, chaque seconde, il utilisera un nom de fichier différent. P>

String filename = new String("bitmap-1.png");
// rotate files, due to not being refreshed if same name 
if ( context.deleteFile(filename) ) {
   filename = new String("bitmap-0.png");
}
FileOutputStream out = context.openFileOutput(filename, Context.MODE_WORLD_READABLE);
bitmap.compress(Bitmap.CompressFormat.PNG, 80, out);
file = context.getFileStreamPath(filename);
out.close();
updateViews.setImageViewUri(R.id.image1,Uri.parse(file.toString())); 


7 commentaires

J'ai eu ce problème il y a longtemps, mais ma solution actuelle est similaire à celle combinée à la réponse acceptée. Au lieu de régler URI vide ou de rotation de deux noms d'image, je viens de définir toujours deux URI d'image et sauvegardez mon bitmap sur les deux. Cela fonctionne, il n'y a pas de branche et ne donne aucune erreur de logcat comme URI vide.


Cela gonflera l'utilisation du stockage, penser si le code est utilisé par de nombreux widgets, ce n'est pas une bonne pratique, utilisez plutôt la réponse acceptée et oubliez le journal.


S'il vous plaît pouvez-vous élargir la solution que vous utilisez @shelll? Donc, vous stockez seulement deux copies identiques du bitmap avec des noms différents, et semblable à la réponse acceptée que vous faites widget.setImageViewUri () deux fois de suite, en montrant les deux bitmaps respectivement? dire que même réponse acceptée sauf qu'au lieu d'un URI vide que vous utilisez un URI qui pointe vers une copie identique du bitmap, de manière efficace, il se charge de la même image deux fois de suite?


@drmrbrewer Oui, je fais exactement ça. Je stocke deux fois le bitmap avec des noms différents. Les images sont petites, donc aucune préoccupation de stockage. Il n'y a pas de scintillement, comme avec l'astuce "URL vide". Et il n'y a pas d'avertissements dans le logcat.


Ok merci @shelll je vais essayer de la mettre en œuvre. Comme mentionné dans mon commentaire sur la solution acceptée, c'était bien pour moi (sans scintillement) jusqu'à ce que je touche une combinaison de périphérique / système d'exploitation / lanceur particulier, j'ai donc besoin d'essayer quelque chose de différent. Toute raison que vous ne faites pas simplement tourner entre deux noms de fichiers, ne gardant que un bitmap au stockage à tout moment (supprimant l'autre) et utiliser uniquement un setImageVieven ( ) plutôt que deux? Autre que l'ajout de complexité (pour peu de gain, si les images sont petites de toute façon)?


@drmrbrewer Je ne voulais pas faire une logique complexe pour un tel problème. Avoir deux images sauvegardées tout le temps et régler toujours l'URI deux fois la preuve de balle. Mon application a été installée sur plus de périphériques 200K sans aucune plainte d'utilisateur sur les problèmes de stockage :)


Cela devrait être la meilleure réponse pour 2018. Autre réponse acceptée a quelques problèmes avec certains appareils.



0
votes

J'espère que cela aidera quelqu'un d'autre. J'essayais d'utiliser cette méthode dans une vue de liste Supprimer la liste, mais elle n'a jamais fonctionné. Mais utiliser des bitmaps a fonctionné pour moi. J'ai pu mettre à jour des images dans l'un des archives et ils sont mis à jour et il n'y avait pas de mise en cache. Ceci est la méthode statique que j'ai utilisée. XXX PRE>

ALORS P>

bitmap = BitmapUtils.getBitmap( address.getPhotoLocation() );
row.setImageViewBitmap( R.id.row_image, bitmap );


0 commentaires