2011-04-14 74 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向你灌輸。由於此代碼是從我的項目的各個部分複製/粘貼的藉口錯字等,我會解決他們,因爲他們指出。