【问题标题】:app widget setImageViewUri does not update the image应用小部件 setImageViewUri 不更新图像
【发布时间】:2011-10-26 09:56:46
【问题描述】:

我有一个应用小部件,它只包含一个图像视图。我重绘该图像并将其作为 png 存储在应用程序的私有内存中,然后我使用 uri (widget.setImageViewUri(R.id.widget_icon, uri)) 设置 RemoteViews 的图像,而不是自己发送位图,因为在非常罕见的情况下我得到的情况! Binder 交易失败!!!

问题是,随着图像随着时间的推移而变化,小部件的图像不会改变。我用根资源管理器检查了保存的 png,它已正确更新。但未显示正确的图像。每个小部件都显示从添加到主屏幕时开始的图像。如果我使用 setImageViewBitmap(...) 它可以正常工作,除了罕见的失败的活页夹事务。

我使用以下方法从服务更新小部件。它不适用于 android 2.3.7 和运行 2.2 的模拟器。可能是什么问题呢?它是否以某种方式缓存?

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);
  }
}

编辑: 我还尝试了自定义 ContentProvider 并设置“content://...”uri,但结果相同。小部件显示从添加到主屏幕时开始的图像,并且不会随着时间的推移而更新。

logcat 没有显示任何错误。

【问题讨论】:

  • 您的所有图标都使用相同的 URI(相同的文件名),这就是问题所在。 URI 在文件、资源中必须是唯一的……系统不会更新可绘制对象,而是使用第一个加载的对象及其预期行为。我认为最好使用 FileProvider,并提供多个文件。您可以删除过时的,并使用新的 URI 更新小部件。
  • @AnisBENNSIR 这个问题是五年前提出并解决的......
  • 对不起,赏金处于开放状态...我的评论将对新用户有用,接受的答案不是最佳解决方案。

标签: android widget uri android-appwidget android-imageview


【解决方案1】:

如果Uri 保持不变,Android 似乎不会更新图像。不过,我发现了一些技巧来解决这个问题。只需在widget.setImageViewUri(R.id.widget_icon, uri); 之前调用widget.setImageViewUri(R.id.widget_icon, Uri.parse(""));

它调用setImageViewUri() 两次,但似乎工作正常。不过,我很想听听更好的解决方法,因为我自己也遇到了这个问题。

【讨论】:

  • 我正在尝试这个,但我发送了一个空 Uri,它正在崩溃。一个空字符串解决了这个问题,谢谢!有某种缓存,如果需要应该可以关闭:(
  • 先设置一个空的uri然后设置为正确的uri解决了这个问题,但是它在每次小部件更新时都会在logcat中给出大量的警告,因为空的uri是无效的......所以这只是部分解决方案,但它有效。
  • 是的,这就是使用此解决方案的问题。就像我说的,这是一种 hack,我很想找到一种更好的方法,但我根本不知道有更好的方法。
  • 这种方法还有另一个问题。小部件在某些更新时闪烁。我想我必须保存图像两次,每次都分配第二张图像的 uri。
  • 我们距离这个答案已经过去了将近 6 年,直到现在这对我来说都很好。但最近我发现在某些情况下(Android O + Pixel 启动器),小部件更新过程似乎永远不会达到第二个(真正的)URI 加载......它在第一个(假)URI 之后失败,但没有加载真正的 URI,因此留下一个空白小部件。使用相同的代码、相同的设备和相同的操作系统但不同的启动器(Nova)它仍然可以正常工作。因此,这可能是特定于启动器的,但可能是由于使用了诸如使用无效 URI 之类的笨拙解决方案造成的。一定有更好的办法吗?
【解决方案2】:

它看起来像 setImageViewUri 缓存图像并且如果它们具有相同的名称则不会刷新它们。

不是最优雅的解决方案,但它可以工作,每秒钟都会使用不同的文件名。

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())); 

【讨论】:

  • 我很久以前就遇到过这个问题,但我目前的解决方案与您的解决方案相似,并结合了接受的答案。而不是设置空 uri 或旋转两个图像名称,我总是设置两个图像 uri 并将我的位图保存到它们。它可以工作,没有分支,也不会像空 uri 那样给 logcat 带来任何错误。
  • 这会增加存储使用量,如果代码被许多小部件使用,那不是一个好习惯,而是使用接受的答案并忘记日志。
  • 请您扩展您正在使用的解决方案 @shelll ?因此,您只需存储具有不同名称的位图的两个相同副本,并且类似于您接受的答案widget.setImageViewUri() 连续两次,分别指向两个位图?即与接受的答案相同,除了您使用指向位图相同副本的 URI 而不是空 URI,因此有效地连续两次加载相同的图像?
  • @drmrbrewer 是的,我就是这么做的。我用不同的名称存储位图两次。图像很小,因此没有存储问题。没有闪烁,就像“空网址”技巧一样。并且 logcat 中没有警告。
  • @drmrbrewer 我不想为这么小的问题制定复杂的逻辑。一直保存两个图像并始终设置 uri 两次是防弹的。我的应用安装在超过 20 万台设备上,没有任何用户抱怨存储问题:)
【解决方案3】:

我希望这对其他人有所帮助。我试图在删除列表视图中使用该方法,但它从未奏效。但是使用位图对我有用。我能够更新任何记录中的图片并且它们正在更新并且没有缓存。这是我使用的静态方法。

public static Bitmap getBitmap( String imageLocation ) {

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.ARGB_8888;

    return BitmapFactory.decodeFile(imageLocation, options);
}

然后

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 2011-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-07
    • 2012-08-23
    相关资源
    最近更新 更多