AppWidget为RemoteViews刷新Uri

时间:2014-09-20 02:33:07

标签: android uri android-appwidget remoteview

我创建了一个Appwidget,它显示了一个通过Uri提供给它的RemoteViews的图像文件(test.png)。 在onUpdate中,我运行一项更改文件内容的服务。我还为将调用onUpdate的图像设置了onClickListener。

- 如果我创建AppWidget的实例,它会显示最近更改的Uri文件版本。

- 如果我点击小部件,我的服务会对文件进行适当的更改(我可以使用文件浏览器验证),但它不会更新AppWidget中显示的图像。

- (最重要的是)如果我删除AppWidget并创建一个新的,它会显示图像文件的当前/正确版本。

我知道我的服务可能需要很长时间才能在第一次通过时生效,但它应该在onUpdate的下一次onClick /调用时显示最新的图像。 就目前而言,AppWidget仅显示第一次调用onUpdate时存在的图像文件的版本。

问题:

刷新Appwidget的RemoteView内容的正确方法是什么,我在这里的方法中遗漏了什么?

谢谢你的时间!

更新

我尝试从AppWidgetProvider.onReceive()调用AppWidgetManager.notifyAppWidgetViewDataChanged()方法,并且在onUpdate()之后仍然没有更改为RemoteViews内容。

public class CCWidgetProvider extends AppWidgetProvider {

  @Override
  public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) 
    {

    // Get all ids
    ComponentName thisWidget = new ComponentName(context,CCWidgetProvider.class);
    int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

    for (int widgetId : allWidgetIds)
        {
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout04);

        /*
         * it's here that I run a service that changes the content of the file /test/test.png
         */

        RelativeLayout RL_widget = new RelativeLayout(context);
        LayoutInflater inflater = (LayoutInflater)context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
        RL_widget = (RelativeLayout)inflater.inflate(R.layout.widget_main, null);

        Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+"/test/test.png");
        remoteViews.setImageViewUri(R.id.IV_widget_image,uri);


        Intent intent = new Intent(context, CCWidgetProvider.class);
        intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
        //PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        remoteViews.setOnClickPendingIntent(R.id.IV_widget_image, pendingIntent);

        appWidgetManager.updateAppWidget(widgetId, remoteViews);
    }
 }
} 

3 个答案:

答案 0 :(得分:2)

我发现有各种各样的东西可以使小工具变得困难。

:一种。 onUpdate并非真正的更新机制

与听起来相反,onUpdate仅在两种情况下被调用:

  1. 创建小部件时。
  2. 每当更新周期时间(小部件的xml定义文件文件中定义的updateMillis)过去时。
  3. 关键点:onUpdate在其他时间永远不会被调用。 (就我在实践中所见)。

    如果您希望窗口小部件在其他时间更新,则需要创建一个单独的机制,其中包含窗口小部件的知识和要触发的容量。通常这是Service,您可以在onUpdate例程中开始。这可能看起来像:

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds )
    {       
        // start the service in case it ain't started yet, this also force a widget update to ensure correct status on them
        Intent intent = new Intent(context, MyService.class);
        intent.putExtra('service.startCode', /*A number to identify what is going on*/);
        context.startService(intent);
    
        // Everything else is triggered from the service!!
    }
    

    然后,服务将内容设置为窗口小部件,并根据需要通过内部计时或使用Broadcast机制更新它们。

    <强> B中。您无法真正更新小部件

    在创建窗口小部件时创建remoteViews似乎合乎逻辑,然后在事情发生变化时更新窗口小部件或其中的视图。根据我的经验,这并不可预测。如果要更改窗口小部件中的任何内容,请创建新的remoteViews,将其正确填写,然后将其分配给窗口小部件。

答案 1 :(得分:1)

我使用RemoteView处理URI的方式遇到了一些设备依赖,并找到了这样的解决方案:

RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
Uri uri = Uri.parse("file://"+Environment.getExternalStorageDirectory().getPath()+"/test/test.png");

Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.crap);
bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
remoteViews.setImageViewBitmap(R.id.IV_widget_image, bitmap);

它也消除了循环RemoteViews的需要,就像我的另一个答案一样。

答案 2 :(得分:0)

当然不优雅或内存效率高,但我发现如果我复制了我的RemoteViews

RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout01);
RemoteViews remoteViews2 = new RemoteViews(context.getPackageName(),R.layout.widget_layout02);

复制它们周围的代码,并在图像更新之间间歇性地交换它们(有点像缓冲区),每次强制更新其内容时重置RemoteView!

现在适合我,请使用更正确的解决方案免费使用。