我有一个widgetProvider。我还有一个服务类来完成小部件的计算。
小部件在初始化时运行正常。当我尝试在我想要做出反应的广播事件(时间变化)之后从onReceive方法中调用服务时,我收到错误。
如何在收到广播事件后从onReceive更新小部件?
这是我的小部件
public class HijriWidget extends AppWidgetProvider{
...
@Override
public void onReceive(Context context, Intent intent) {
if(Intent.ACTION_TIME_CHANGED.equals(intent.getAction())||Intent.ACTION_DATE_CHANGED.equals(intent.getAction())){
//THE CODE BELOW LEADS TO AN EXCEPTION. HOW CAN I UPDATE THE WIDGET HERE?
RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.widget);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
appWidgetManager.updateAppWidget(appWidgetId, remoteView);
}
super.onReceive(context, intent);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
PendingIntent updatepending = HijriWidget.makeControlPendingIntent(context,RefreshService.UPDATE, appWidgetId);
pi = updatepending;
try {
updatepending.send();
} catch (CanceledException e) {
e.printStackTrace();
}
setAlarm(context, appWidgetId, 5*60*1000);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public static PendingIntent makeControlPendingIntent(Context context, String command, int appWidgetId) {
Intent active = new Intent(context,RefreshService.class);
active.setAction(command);
active.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
//this Uri data is to make the PendingIntent unique, so it wont be updated by FLAG_UPDATE_CURRENT
//so if there are multiple widget instances they wont override each other
Uri data = Uri.withAppendedPath(Uri.parse("hijriwidget://widget/id/#"+command+appWidgetId), String.valueOf(appWidgetId));
active.setData(data);
return(PendingIntent.getService(context, 0, active, PendingIntent.FLAG_UPDATE_CURRENT));
}
public static void setAlarm(Context context, int appWidgetId, int updateRate) {
PendingIntent newPending = makeControlPendingIntent(context,RefreshService.UPDATE,appWidgetId);
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
if (updateRate >= 0) {
alarms.set( AlarmManager.RTC, calendar.getTimeInMillis(), newPending);
//alarms.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), updateRate, newPending);
} else {
// on a negative updateRate stop the refreshing
alarms.cancel(newPending);
}
}
}
这是我的服务
public class RefreshService extends Service {
@Override
public void onStart(Intent intent, int startId) {
int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
RemoteViews remoteView = new RemoteViews(getApplicationContext() .getPackageName(), R.layout.widget);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
final Calendar c = Calendar.getInstance();
int mYear = c.get(Calendar.YEAR);
int mMonth = c.get(Calendar.MONTH);
int mDay = c.get(Calendar.DAY_OF_MONTH);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
mMonth++;
HijriCalendar hc =new HijriCalendar( mYear,mMonth,mDay);
remoteView.setTextViewText(R.id.TextView02,hc.getHijriMonth()+"/"+hc.getHijriDay());
remoteView.setTextColor(R.id.TextView02, Color.BLACK);
remoteView.setTextViewText(R.id.TextView01, hc.getHijriYear()+"");
remoteView.setTextColor(R.id.TextView01, Color.WHITE);
appWidgetManager.updateAppWidget(appWidgetId, remoteView);
super.onStart(intent, startId);
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
任何帮助将不胜感激。感谢。
更新:
我发现了问题。检查下面的答案。
答案 0 :(得分:2)
我猜你已经弄明白了,但原始代码中的问题是ACTION_TIME_CHANGED意图不包含AppWidgetManager.EXTRA_APPWIDGET_ID额外信息,因此getInt()抛出了nullpointerexception。
注意:有一种更简单的方法可以解决此问题:updateAppWidget的覆盖之一采用组件名而不是窗口小部件ID,因此您可以创建一个通用函数来更新窗口小部件并从onReceive和onUpdate调用它,例如:
private static void updateWidget(Context context) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
// ... code here to build your remoteviews ...
ComponentName widgetComponent = new ComponentName(PACKAGE, PACKAGE+"."+CLASS);
appWidgetManager.updateAppWidget(widgetComponent, remoteView);
}
然后你永远不必担心widget ID。当然,只有在您不关心支持多个同步小部件时,这才有效。
答案 1 :(得分:0)
更新:
我已将下面的代码放在onReceive方法中,它对我有用
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisAppWidget = new ComponentName(PACKAGE, PACKAGE+"."+CLASS);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
try {
onUpdate(context, appWidgetManager, appWidgetIds);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}