Android onReceive widget can't call service class?

I have a widgetProvider. I also have a class of service that computes for the widget.

The widget works great on initialization. I get an error when I try to call a service from the onReceive method after the translation event that I want to respond to (time change).

How to update a widget from onReceive after receiving a broadcast event?

Here is my widget

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

}

and here is my service

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

Any help would be appreciated. Thanks.

UPDATE:

I found a problem. Check out my answer below.

+7
android widget
source share
2 answers

UPDATE:

I put the code below in the onReceive method and worked for me

 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(); } 
0
source share

I assume you understand this, but the problem in the source code was that the intent of ACTION_TIME_CHANGED does not include the AppWidgetManager.EXTRA_APPWIDGET_ID application, so getInt () throws a nullpointer exception.

Note. There is a slightly simpler way to solve this problem: one of the updateAppWidget overrides accepts the name of the component instead of the widget ID, so you can create a general function to update the widget and call it from both onReceive and onUpdate, for example:

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

Then you never have to worry about widget IDs. Of course, this only works if you do not need to support multiple widgets at the same time.

See: http://developer.android.com/reference/android/appwidget/AppWidgetManager.html#updateAppWidget%28android.content.ComponentName,%20android.widget.RemoteViews%29

+2
source share

All Articles