2010-07-27 59 views
7

我有一个widgetProvider。我也有一个服务类来完成小部件的计算。Android Widget onReceive无法调用服务类?

小部件在初始化时运行良好。当我想在发生广播事件(时间变化)后尝试从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; 
} 

任何帮助将不胜感激。谢谢。

更新:

我发现了这个问题。在下面检查我的答案。

+1

你得到什么异常? – Pentium10 2010-07-27 19:07:26

+0

了java.lang.RuntimeException:无法启动接收机com.majjoodi.hijri.HijriWidget ... 引起的:在com.majjoodi.hijri.HijriWidget.onRecieve – Majjoodi 2010-07-28 14:53:31

+0

显示java.lang.NullPointerException 得到的最新消息? – robertokl 2010-08-11 20:16:30

回答

0

UPDATE:

我已经把下面的代码中的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(); 

       } 
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。当然,这只有在你不关心支持多个同时部件的情况下才有效。

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