【问题标题】:Android Widget onReceive can't call Service class?Android Widget onReceive 不能调用Service 类?
【发布时间】:2010-07-27 18:49:59
【问题描述】:

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

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

更新:

我发现了问题。请在下面查看我的答案。

【问题讨论】:

  • java.lang.RuntimeException:无法启动接收器 com.majjoodi.hijri.HijriWidget ... 原因:com.majjoodi.hijri.HijriWidget.onRecieve 处的 java.lang.NullPointerException
  • robertokl,在帖子中查看我的更新。

标签: android widget


【解决方案1】:

我猜你已经想通了,但是你原始代码中的问题是 ACTION_TIME_CHANGED 意图不包含额外的 AppWidgetManager.EXTRA_APPWIDGET_ID,所以 getInt() 抛出了一个空指针异常。

注意:有一个稍微简单的方法可以解决这个问题: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);
}

那么您就不必担心小部件 ID。当然,这仅在您不关心同时支持多个小部件时才有效。

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

【讨论】:

    【解决方案2】:

    更新:

    我已将以下代码放在 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();
    
                    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-06
      • 1970-01-01
      • 1970-01-01
      • 2016-02-22
      • 1970-01-01
      • 2018-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多