2010-07-27 4 views
7

Ich habe einen WidgetProvider. Ich habe auch eine Serviceklasse, die die Berechnung für das Widget durchführt.Android Widget onReceive kann Service Class nicht aufrufen?

Das Widget funktioniert ordnungsgemäß, wenn es initialisiert wird. Ich erhalte einen Fehler, wenn ich versuche, den Dienst innerhalb der onReceive-Methode nach einem Broadcast-Ereignis aufzurufen, auf das ich reagieren möchte (Zeitänderung).

Wie kann ich das Widget von onReceive nach Erhalt eines Broadcast-Ereignisses aktualisieren?

Hier ist mein 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); 
      } 
     } 

}

und hier ist mein 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; 
} 

Jede Hilfe geschätzt wird. Vielen Dank.

UPDATE:

ich das Problem gefunden haben. Überprüfen Sie meine Antwort unten.

+1

Welche Ausnahme, die Sie bekommen? – Pentium10

+0

java.lang.RuntimeException: Kann Empfänger starten com.majjoodi.hijri.HijriWidget ... Verursacht durch: java.lang.NullPointerException bei com.majjoodi.hijri.HijriWidget.onRecieve – Majjoodi

+0

keine Updates erhalten? – robertokl

Antwort

0

UPDATE:

ich den Code unten in der OnReceive Methode gesetzt haben und es funktionierte für mich

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

Ich denke, Sie haben das herausgefunden, aber das Problem in Ihrem ursprünglichen Code war, dass der ACTION_TIME_CHANGED-Intent keinen AppWidgetManager.EXTRA_APPWIDGET_ID extra enthält, also warf getInt() eine Nullpointerexpektion.

Hinweis: Es gibt eine etwas einfachere Möglichkeit, dieses Problem zu lösen: Eine der Überschreibungen von updateAppWidget verwendet einen Komponentennamen anstelle einer Widget-ID. Sie können also eine allgemeine Funktion zum Aktualisieren des Widgets erstellen und sie sowohl onReceive als auch aufrufen onUpdate, zB:

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

Dann müssen Sie sich nie um Widget-IDs kümmern. Natürlich funktioniert das nur, wenn Sie nicht gleichzeitig mehrere simultane Widgets unterstützen wollen.

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

Verwandte Themen