更新AppWidget定期从服务 [英] Update AppWidget Periodically from a service

查看:112
本文介绍了更新AppWidget定期从服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我想从我的AppWidget:

This is what I want from my AppWidget:

  1. 在配置活动启动后,当小部件添加到屏幕//好为止
  2. 在配置被保存后,启动服务的更新微件//好为止
  3. 在定期安排警报,运行更新插件的服务。 //有麻烦在这里

这是严重地给我花白的头发已经,我不知道该怎么办了。如何设置的更新速率从服务的AppWidget?我可以从服务更新的部件,但是当我尝试设置了警钟,它并没有得到对AppWidget的的onReceive()方法。

This is seriously giving me grey hair already, and I don't know what to do anymore. How do you set the update rate for an AppWidget from a service? I can update the widget from the service, but when I try to set the alarm, it does not get to the onReceive() method on the AppWidget.

下面是code的服务更新:

Here is the code for the service update:

Intent updateWidget = new Intent();
updateWidget.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
updateWidget.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{appWidgetId});
Uri data = Uri.withAppendedPath(Uri.parse(WeatWidgetProvider.URI_SCHEME +
 "://widget/id/"), String.valueOf(appWidgetId));
updateWidget.setData(data);
PendingIntent updatePend = PendingIntent.getBroadcast(this, 0, updateWidget, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager)getSystemService(ALARM_SERVICE);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()+ updateRate, updateRate, updatePend);

而在的onReceive() WidgetProviderClass的:

And in the onreceive() of WidgetProviderClass:

public void onReceive(Context context, Intent intent){
  super.onReceive(context, intent);
  Log.d("OnReceive", "OnReceive called");
  String action = intent.getAction();
  Log.d("Action", "OnReceive:Action: " + action);
  if(AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)){
    int appwidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
    if(appwidgetId != AppWidgetManager.INVALID_APPWIDGET_ID){
      this.onDeleted(context, new int[] {appwidgetId});
    }
  } else if(AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)){
    if(!URI_SCHEME.equals(intent.getScheme())){
      final int[] appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
      for(int appWidgetId:appWidgetIds){
        SharedPreferences prefs = context.getSharedPreferences(WeatForecastConfigure.WEATHER_PREF_NAME, Context.MODE_PRIVATE);
        update = prefs.getInt(WeatForecastConfigure.REFRESH_UPDATE, -1);
        System.out.println(update);
        if(update != -1){
          Intent widgetUpdate = new Intent();
          widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
          widgetUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { appWidgetId });
          // make this pending intent unique by adding a scheme to it
          widgetUpdate.setData(Uri.withAppendedPath(Uri.parse(WeatWidgetProvider.URI_SCHEME +
           "://widget/id/"), String.valueOf(appWidgetId)));
          PendingIntent newPending = PendingIntent.getBroadcast(context.getApplicationContext(), 0, widgetUpdate, PendingIntent.FLAG_UPDATE_CURRENT);
          // schedule the updating
          AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
          alarms.setRepeating(AlarmManager.ELAPSED_REALTIME,
           SystemClock.elapsedRealtime(), WeatForecastConfigure.convertToMillis(update), newPending);
        }
      }
    }
    super.onReceive(context, intent);
  }else{
    super.onReceive(context, intent);
  }
}

有关的OnUpdate()注释行是故意的。

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
  Log.d("OnUpdate", "OnUpdate called");
  for (int appWidgetId : appWidgetIds) {
    // context.startService(new Intent(context,WeatService.class));
  }
  //super.onUpdate(context, appWidgetManager, appWidgetIds);
}

请帮忙。我不知道如何设置报警更新。无论是我从配置类或从服务做到这一点,这是行不通的。谢谢你。

Please help. I have no idea how to set the alarm to update. Whether I do it from the configuration class or from a service, it does not work. Thanks.

推荐答案

我写了这一切,并意识到它可能只是迷惑你多一些,很好哦。

I wrote all this, and realized it will probably just confused you more, oh well.

下面是我如何更新我的小部件的骨架,它是松散的基础上这一code的 HTTP://$c$c.google.com/p/android-sky/source/browse/#svn%2Ftrunk%2FSky (特别是该UpdateService类。

Here is the skeleton of how I update my widgets, it is loosely based on this code http://code.google.com/p/android-sky/source/browse/#svn%2Ftrunk%2FSky (particularly the UpdateService class.

的主要区别是我的code

The main difference is my code

  1. 在开始执行更新服务
  2. 设置报警(广播挂起的意图),提醒有关下次更新的窗口小部件
  3. 更新窗口小部件并停止服务
  4. 在接收更新的广播(在供应商的onReceive),然后重新启动该服务

您似乎在试图告诉AppWidgetProvider开球通过的onupdate,我不知道这是否可能?

You seem to be trying to tell the AppWidgetProvider to kickoff through the onUpdate, I'm not sure if this is even possible?

下面是我如何做到这一点半伪code:

Here is how I do it in semi pseudo code:

UpdateService类:

UpdateService class:

 //based on (an old) example http://code.google.com/p/android-sky/source/browse/#svn%2Ftrunk%2FSky however other methods I have tried have not been as reliable as this
 public void run() {
     //set the alarm for the next update
     AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
 long millis = System.currentTimeMillis();

     //one alarm to update them all, if you wanted to you could
     //add an extra appWidgetId then you might need to encode the intent
     //however so it is a unique PendingIntent
     Intent updateIntent = new Intent(ACTION_UPDATE_ALL);  //ACTION_UPDATE_ALL should be a constant somewhere that can be used to resolve this action com.packagename.ACTION_UPDATE_ALL
     PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, updateIntent, 0);
     // Schedule alarm, and force the device awake for this update
     alarmManager.set(AlarmManager.RTC, millis + updateFrequency * DateUtils.MINUTE_IN_MILLIS, pendingIntent);
     Log.d(TAG, "Next update should be at: " + DateFormat.format("h:mm:ss", millis + updateFrequency * DateUtils.MINUTE_IN_MILLIS));


     while (hasMoreUpdates()) {
        int appWidgetId = getNextUpdate();
        if (!(appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID)) {
            Uri appWidgetUri = ContentUris.withAppendedId(Agenda.getContentUri(context), appWidgetId);

            AppWidgetProviderInfo info = manager.getAppWidgetInfo(appWidgetId);  
            String providerName = info.provider.getClassName();
            //if the provider matches one of my widget classes, call the update method
            if (providerName.equals(Widget_4_1.class.getName())) {
                 remoteViews = Widget_4_1.buildUpdate(context, appWidgetUri, dateRows);
            }

            //perform more actions such as sending remoteViews to the AppWidgetManager
        }
    }
}

Widget_4_1类:

Widget_4_1 class:

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) {

    // If no specific widgets requested, collect list of all
    if (appWidgetIds == null) {
        appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(
                context, AbstractWidget.class));
    }

    UpdateService.requestUpdate(appWidgetIds);
    Intent i = new Intent();
    i.setComponent(new ComponentName(context, UpdateService.class));
    context.startService(i);
}

//called from service
public static RemoteViews buildUpdate(Context context, Uri appWidgetUri) {
    int appWidgetId = (int) ContentUris.parseId(appWidgetUri);
    RemoveViews remoteViews = someMethodToBuildView(appWidgetId );
    //return view to service
    return remoteViews;
}

public void onReceive(Context context, Intent intent) {

final String action = intent.getAction();

    //when the alarm triggers, just update all your widgets, why handle them separately?
if (action.equals(ACTION_UPDATE_ALL)) {
        AppWidgetManager manager = AppWidgetManager.getInstance(context);
    int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass()));
    if(appWidgetIds.length>0){
            UpdateService.requestUpdate(appWidgetIds);
    Intent updateIntent = new Intent(context, UpdateService.class);
            updateIntent.setAction(action);

        context.startService(updateIntent);
    }
    }
    //else you could catch a specific action for updating a single widget and
    //tell your update service to do it manually
}

AndroidManifest.xml中:

AndroidManifest.xml:

<application> 
     ...
    <receiver android:name="com.mypackage.Widget_4_1"
        android:label="@string/agenda_widget_name_4_1">
    <intent-filter>
            <!-- IMPORTANT, needs to match the ACTION_UPDATE_ALL string (e.g. a constant somewhere) -->
        <action android:name="com.packagename.UPDATE_ALL" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider"
            android:resource="@xml/widget_4_1" />
</receiver>
    ...
</application> 

希望我没有让你感到困惑。

Hope I haven't confused you.

由于这code是复制/从我的项目的借口错字的等等,我会解决这些问题各部分粘贴为他们指出了。

As this code is copy/pasted from various parts of my project excuse typo's etc, I will fix them as they are pointed out.

这篇关于更新AppWidget定期从服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆