2011-04-14 31 views
4

这是我从我的AppWidget想:从服务更新AppWidget定期

  1. 配置活动启动后,当小部件添加到屏幕//好为止
  2. 保存配置后,一服务开始更新小部件//目前为止不错
  3. 定期安排警报以运行更新小部件的服务。 //在这里遇到麻烦

这已经严重地让我灰白的头发了,我不知道该怎么做了。你如何设置一个服务的AppWidget更新率?我可以从服务更新小部件,但是当我尝试设置警报时,它不会到达AppWidget上的onReceive()方法。

下面是服务更新的代码:在WidgetProviderClass的onreceive()

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

和:

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

请帮忙。我不知道如何设置闹钟更新。无论是从配置类还是从服务中执行,它都不起作用。谢谢。

+0

请任何人指导我或显示犯错的地方。我知道我离我想要的不太远,但是整个概念开始混淆了我。我看了各种教程,但似乎没有任何工作。 – irobotxxx 2011-04-14 17:09:24

回答

0

我认为你需要使用一个标准的URI方案在你的意图是这样的:

intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); 
0

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

下面是我如何更新我的小部件的骨架,它大致是基于该代码http://code.google.com/p/android-sky/source/browse/#svn%2Ftrunk%2FSky(特别是UpdateService类。

的主要区别是我的代码

  1. 启动服务来执行更新
  2. 设置报警(广播未决的意图),以提醒小部件对未来更新
  3. 更新微件和停止服务
  4. 接收更新广播(在供应商的onReceive),然后重新启动该服务

你似乎想要告诉的AppWidgetProvider通过的onUpdate开球,我不知道这是否可能?

这里是我如何做到这一点半伪代码:

UpdateService类:

//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类:

@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:

<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> 

希望我没有c向你灌输。由于此代码是从我的项目的各个部分复制/粘贴的借口错字等,我会解决他们,因为他们指出。