Android Widget onReceive无法调用Service类?

时间:2010-07-27 18:49:59

标签: android widget

我有一个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;
}

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

更新:

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

2 个答案:

答案 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。当然,只有在您不关心支持多个同步小部件时,这才有效。

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

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

                }