应用程序小组件更新头痛:Binder事务,RemoteViews,setImageURI和方向更改失败

时间:2013-02-12 02:12:29

标签: android orientation screen-orientation android-appwidget remoteview

我遇到了更新AppWidgets的问题,而android中的一系列限制/错误阻止了我找到解决方法。

我的应用小部件是可以设置的,所以我需要能够在运行时更新它上面的图像视图(以及文本视图和意图)。我正在更新多达9个图像视图,但我使用的图形大小相当适中(最大11kb pngs)。我通过RemoteViews对象推送的数据总大小应小于100kb,完全在1mb的限制范围内。我认为屏幕上的实际可绘制资源最终会比原来的png更大,但是10%的限制似乎足以说明这一点。但是,对于某些手机和发射器,我收到了“FAILED BINDER TRANSACTION”错误。

我找到了两个解决方案:

1)使用setImageViewUri(调用setImageURI)而不是使用RemoteViews对象的setImageViewResource,这样就可以通过RemoteViews对象发送drawable,而是从URI加载图像。解决内存错误(请参阅https://groups.google.com/forum/#!topic/android-developers/KKEyW6XdDvg/discussion

2)将应用程序窗口小部件的更新划分为多个RemoteViews调用。所以我更新了3个图像,调用updateAppWidget,创建一个新的RemoteViews对象,更新接下来的3个图像,调用updateAppWidget等。

第一种方法的问题在于它仅适用于中密度设备。由于android代码库中的错误,所有其他设备都会错误地缩放图像(请参阅错误报告:http://code.google.com/p/android/issues/detail?id=22590

第二种方法的问题是,当屏幕方向改变时,android会使用它存储在某个秘密位置的最后一个RemoteViews调用来销毁并重新创建窗口小部件视图。这个mew appwidget没有完全重绘,因为我拆开了我的RemoteView调用,小部件最终无法使用。似乎没有可靠的方法来确定android何时销毁和重新创建appwidgets - 服务中的onConfigurationChanged并不总是触发,并且我没有发现任何活动级别调用(即onUpdate,onReceive)。为了能够在方向更改时完全正确地重新绘制窗口小部件,我只能使用一个RemoteViews(updateAppWidget)调用,因此此解决方案将无法正常工作。

有谁知道如何解决这个问题?我想知道是否有可能实现我自己的RemoteViews调用非bug的setImageURI函数(在自定义ImageView类中),以便正确地进行缩放。似乎很多工作只是更新了一些小部件,我不确定android会让我以这种方式扩展RemoteViews / ImageView。

当屏幕方向改变并且强制它重绘整个小部件时,是否有拦截android?

很想听到任何其他建议或解决方法的想法!感谢。

1 个答案:

答案 0 :(得分:0)

我在开发集合的AppWidgets时遇到了同样的问题。很多时候会发生以下情况:

  • 轮换时,ListView完全消失;
  • 按钮侦听器(实际上称为PendingIntents)停止响应;
  • 通过setImageViewResource的图片更改未得到更新;

..等等。我得出了与你相同的结论: android使用最后一个RemoteViews调用来破坏和重新创建窗口小部件视图,它将它存储在一些秘密的地方。在确认之后,这是精确计时AppWidgetManager.getInstance(context).updateAppWidget()的调用的问题,因为我想在告诉ListView之后禁用 clickListeners(或PendingIntents)刷新自身(这是一个调用Web服务和检索非常重要数据量的网络操作),并希望在ListView完成加载后启用监听器,同时保持RemoteViews完全加载以便处理轮换。

我接近放弃和使用作为替代品......

  

当屏幕方向改变并且强制它重绘整个小部件时,是否有拦截android?

.. 确实拦截Android轮换更改的服务,与AppWidget不同。如果你的选项用完了,我建议你试试看:

public class MyWidget extends AppWidgetProvider {
@Override
    public void onConfigurationChanged(Configuration newConfig)
    {
                // insert code here
    }
}

详细了解该服务here in StackOverflow