2010-07-27 9 views
7

Tengo un widgetProvider. También tengo una clase de servicio que hace el cálculo para el widget.Android Widget onReceive no puede llamar a la clase de servicio?

El widget funciona bien cuando se inicializa. Recibo un error cuando trato de llamar al servicio desde el método onReceive después de un evento de transmisión en el que quiero reaccionar (cambio de hora).

¿Cómo puedo actualizar el widget de onReceive después de recibir un evento de difusión?

Aquí está mi aparato

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

}

y aquí está mi servicio

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

se observará ninguna ayuda. Gracias.

ACTUALIZACIÓN:

que he encontrado el problema. Verifique mi respuesta a continuación.

+1

Lo excepción se obtiene? – Pentium10

+0

java.lang.RuntimeException: No se puede iniciar el receptor com.majjoodi.hijri.HijriWidget ... causada por: java.lang.NullPointerException en com.majjoodi.hijri.HijriWidget.onRecieve – Majjoodi

+0

consiguió las actualizaciones? – robertokl

Respuesta

0

ACTUALIZACIÓN:

He puesto el siguiente código en el método OnReceive y funcionó para mí

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

       } 
2

Supongo que ya se dio cuenta de esto, pero el problema en su código original era que el intento ACTION_TIME_CHANGED no incluye un AppWidgetManager.EXTRA_APPWIDGET_ID adicional, por lo que getInt() lanzaba una nullpointereception.

Nota: hay una manera un poco más fácil de resolver este problema: una de las modificaciones a updateAppWidget toma un nombre de componente en lugar de una identificación de widget, por lo que podría crear una función común para actualizar el widget y llamarlo desde onReceive y onUpdate, por ejemplo:

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

Entonces usted nunca tendrá que preocuparse por los identificadores de los widgets. Por supuesto, esto solo funciona si no te importa apoyar múltiples widgets simultáneos.

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

Cuestiones relacionadas