小部件不更新视图并且也没有显示错误
Posted
技术标签:
【中文标题】小部件不更新视图并且也没有显示错误【英文标题】:Widget not updating Views and showing no errors as well 【发布时间】:2013-06-26 09:29:19 【问题描述】:我正在开发一个小部件,它运行时没有任何错误,但我的小部件的 ImageView
没有更新,也没有给出任何错误。因此让我对自己做错了什么感到困惑。这是代码:-
BroadcastReceiver _broadcastReceiver;
GetDrawableResources getDrawableResources = new GetDrawableResources();
private final SimpleDateFormat _sdfWatchTime = new SimpleDateFormat("HH:mm");
@Override
public void onEnabled(final Context context)
super.onEnabled(context);
// TODO Auto-generated method stub
System.out.println("Entering onstart");
_broadcastReceiver = new BroadcastReceiver()
@Override
public void onReceive(Context ctx, Intent intent)
System.out.println("Registering BroadCast");
if (intent.getAction().compareTo(Intent.ACTION_TIME_TICK) == 0)
System.out.println(_sdfWatchTime.format(new Date()));
Bundle extras = intent.getExtras();
if (extras != null)
AppWidgetManager awm = AppWidgetManager
.getInstance(context);
ComponentName thisWidget = new ComponentName(
context.getPackageName(),
MainActivity.class.getName());
int[] appWidgetIds = awm.getAppWidgetIds(thisWidget);
onUpdate(context, awm, appWidgetIds);
;
context.getApplicationContext().registerReceiver(_broadcastReceiver,
new IntentFilter(Intent.ACTION_TIME_TICK));
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds)
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int awID : appWidgetIds)
updateAppWidget(context, appWidgetManager, awID);
private void updateAppWidget(Context context,
AppWidgetManager appWidgetManager, int awID2)
// TODO Auto-generated method stub
// class to get drawable images that will be used to denote hours and
// minutes
int time[] = new int[new GetTime().getTime(context
.getApplicationContext()).length];
// class to get each digit of time separately eg 10:10, separating 1 0 1
// 0 working correctly
time = new GetTime().getTime(context.getApplicationContext());
// changing views
System.out.println("awID for " + awID2);
RemoteViews views = new RemoteViews(context
.getPackageName(), R.layout.activity_main);
views.setImageViewResource(R.id.ivHour0,
getDrawableResources.setTimeDrawable(time[0]));
views.setImageViewResource(R.id.ivHour1,
getDrawableResources.setTimeDrawable(time[1]));
views.setImageViewResource(R.id.ivMinute0,
getDrawableResources.setTimeDrawable(time[2]));
views.setImageViewResource(R.id.ivMinute1,
getDrawableResources.setTimeDrawable(time[3]));
System.out.println("updating the views");
appWidgetManager.updateAppWidget(awID2, views);
我的 LogCat 中的输出
06-28 19:46:00.076: I/System.out(680): Registering BroadCast
06-28 19:46:00.086: I/System.out(680): 19:46
06-28 19:46:00.096: I/System.out(680): awID for 14
06-28 19:46:00.096: I/System.out(680): updating the views
06-28 19:47:00.086: I/System.out(680): Registering BroadCast
06-28 19:47:00.086: I/System.out(680): 19:47
06-28 19:47:00.096: I/System.out(680): awID for 14
06-28 19:47:00.096: I/System.out(680): updating the views
因此,appWidgetID 是正确的,并且函数正在按应有的方式执行,但视图没有更新。它们和以前一样。
【问题讨论】:
【参考方案1】:您的方法有一个有效的基础,但是您正在 onEnabled 方法中创建和注册您的 broadcastReceiver,而该方法又属于 WidgetProvider 类。
当 WidgetProvider 的方法 (onEnabled, onUpdate) 执行完毕后,WidgetProvider 类将被系统销毁,您的 broadcastReceiver 也将被销毁。如您所见,这里没有错误,但也没有收到。
为了做你想做的事,你需要一个更“稳定”的应用程序组件来保存你的广播接收器,这样的组件就是一个服务。即使您的应用程序停止,服务也会继续运行,因此它是此类作业的好组件。
所以为了回答你的问题,我建议你创建一个服务来创建和注册你的广播接收器,然后你从你的 widgetprovider 类的 onEnabled 方法启动服务,当用户从他的小部件中删除你的小部件时你可以停止服务主屏幕。
从我的建议开始的一个好地方是here...
编辑 Here 是来自 google 的 App Widgets 文档(大约在中间):
注意:由于 AppWidgetProvider 是 BroadcastReceiver 的扩展,因此无法保证您的进程在回调方法返回后继续运行(有关广播生命周期的信息,请参阅 BroadcastReceiver)。如果您的 App Widget 设置过程可能需要几秒钟(可能在执行 Web 请求时)并且您需要继续您的过程,请考虑在 onUpdate() 方法中启动服务。在服务中,您可以对 App Widget 执行自己的更新,而不必担心 AppWidgetProvider 由于应用程序无响应 (ANR) 错误而关闭。有关运行服务的 App Widget 示例,请参阅维基词典示例的 AppWidgetProvider。
我在我的 appwidget 中遇到过类似的问题,结果是我的 appwidgetprovider 的生命周期引起的,所以我基于此回答了你。但是,在您的观察中,您是对的,您的小部件至少应该在第一次更新时更新自身,所以更多地研究它我发现您正在使用自定义 getDrawableResources 类来获取您的资源(您可以用它编辑您的问题吗?代码?)并且您正在使用 getDrawableResources.setTimeDrawable(time[0]));为了得到drawable,也许你应该把它改成getDrawableResources.getTimeDrawable(time[0]))?
编辑 2
这是说明我的建议的代码。首先是我们注册 BatteryReceiver 的服务。
class FullWidgetBatteryChangedReceiver extends BroadcastReceiver
//----- BroadcastReceiver Overrides -----
@Override
public void onReceive(Context cx, Intent intent)
Log.d("BatteryChangedReceiver", "onReceive");
Commands.FullWidgetUpdate(cx, -1, 0); //<-- Update all widgets
//----- BroadcastReceiver Overrides END -----
public class myWidgetService extends Service
//----- Private Members -----
private FullWidgetBatteryChangedReceiver bcRCV;
//----- Private Members END -----
//----- Private Code -----
private void RegisterBatteryChangedReceiver()
Log.d(TAG, "RegisterBatteryChangedReceiver");
if (bcRCV == null)
Log.d(TAG, "BatteryChangedReceiver needs Registration and I am doing it...");
bcRCV = new FullWidgetBatteryChangedReceiver();
IntentFilter actions = new IntentFilter();
actions.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(bcRCV, actions);
else
Log.d(TAG, "BatteryChangedReceiver does not needs Registration");
private void UnRegisterBatteryChangedReceiver()
Log.d(TAG, "UnRegisterBatteryChangedReceiver");
if (bcRCV != null)
Log.d(TAG, "Assuming that BatteryChangedReceiver is registered and I am unregister it...");
unregisterReceiver(bcRCV);
bcRCV = null;
else
Log.d(TAG, "Assuming that BatteryChangedReceiver is NOT registered");
//----- Private Code END -----
//----- Service Overrides -----
@Override
public void onCreate()
super.onCreate();
@Override
public int onStartCommand(Intent intent, int flags, int startId)
RegisterBatteryChangedReceiver();
return Service.START_STICKY; //<-- This is important!!!
@Override
public IBinder onBind(Intent intent)
return null;
@Override
public void onDestroy()
UnRegisterBatteryChangedReceiver();
super.onDestroy();
//----- Service Overrides END -----
然后这里是完成服务操作的 myWidgetProvider:
public class myWidgetProvider extends AppWidgetProvider
//----- AppWidgetProvider Overrides -----
@Override
public void onEnabled(Context context)
super.onEnabled(context);
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
super.onUpdate(context, appWidgetManager, appWidgetIds);
// If no specific widgets requested, collect list of all
if (appWidgetIds == null)
appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, FullWidgetProvider.class));
// Εδώ κάνουμε update to Widget για κάθε id ξεχωριστά
for (int widgetId : appWidgetIds)
Commands.FullWidgetUpdate(context, widgetId, 0); //<-- Update το widgetId
context.startService(new Intent(context, myWidgetService.class));
@Override
public void onDeleted(Context context, int[] appWidgetIds)
super.onDeleted(context, appWidgetIds);
@Override
public void onDisabled(Context context)
super.onDisabled(context);
context.stopService(new Intent(context, FullWidgetService.class));
int[] appWidgetIds = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, FullWidgetProvider.class));
if (appWidgetIds.length != 0)
AppWidgetHost host = new AppWidgetHost(context, 0);
for (int widgetId : appWidgetIds)
host.deleteAppWidgetId(widgetId);
//----- AppWidgetProvider Overrides END -----
希望这会有所帮助...
【讨论】:
我不知道这些WidgetProvider类和broadcastReceiver在执行后被销毁了。我正在阅读有关该服务的信息,如果它解决了我的问题,请将答案标记为正确。谢谢 我想清除一些东西。你说在执行onEnabled之后,onUpdate和broadcastReciever被销毁但是每分钟我的broadcastReciever然后onUpdate然后最后updateAppWidget被调用。因此,如果每分钟调用一次 updateAppWidget,则必须更新视图,因为更新是在此方法中完成的。我说错了吗?getDrawableResources
是我制作的一个自定义类,它没有扩展或实现任何东西。这是一个简单的类。它根据 time[0] 发送返回图像的 id。例如,如果时间 [0] 为 8,则在 getDrawableResources
中运行的代码为案例 8:时间 = R.drawable.time_8;休息;
@RohanKandwal 是这样的,但看看我的第二次编辑,我在其中添加了一些代码来说明这种方法。谢谢。
@RohanKandwal Commands 是我创建的一个自定义静态类,目的是让事情井井有条。您可以将此行替换为您的 updatewidget 函数。对于给您带来的不便,我深表歉意,但我的代码仅用于说明目的,而不是完整的工作代码。顺便说一句,我很高兴你解决了你的问题。谢谢。以上是关于小部件不更新视图并且也没有显示错误的主要内容,如果未能解决你的问题,请参考以下文章
带有集合(ListView)的Android小部件不显示项目