Android widgetタイミング更新およびイベント処理


最近プロジェクトでwidgetが使用され、widgetのタイミング更新とイベント監視と処理に関連しています.具体的な効果は以下の通りです.
機能:
タイミング更新の実装
同じグループのデータを表示でき、update時にデータソースを更新できます
イベントを傍受し、異なる反応を起こすことができます.
 
実装分析:
SDK1.5以降android:updatePeriodMillisは失効し、デフォルト更新に変更され、カスタムタイミング更新を実現するためにタイマーアクティブ更新が使用された.
Widgetは他のアプリケーションによって管理されており、共有データは非常に困難であり、sharedpreferencesにデータを書き込み、データソースを記録します.
Widgetの各種状態はメッセージ制御であり,イベント管理を容易にするために受信機をシステムに登録する.
 
まずAndroidManifestでxmlファイルにwidgetを登録するには:
  •         android:name=".widget"
  •        android:label="@string/app_name"
  •        >
  •        
  •             
  •        
  •        
  •                 android:name="android.appwidget.provider"
  •                 android:resource="@xml/widget"
  •                 />

  • res/xml/widget.xml widget :
  • <appwidget-provider
  •         xmlns:android="http://schemas.android.com/apk/res/android"
  •         android:minWidth="294dip"
  •         android:minHeight="72dip"
  •         android:updatePeriodMillis="5000"      
  •         android:initialLayout="@layout/appwidget"
  •         >
  • </appwidget-provider>

  •       ,   widget                ,             sheme   :
  • public static final String URI_SCHEME = "widget";
  • public void onReceive(Context context, Intent intent) {
  •         if(AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(intent.getAction()))
  •        
  •                 final int[] appWidgetIds = intent.getExtras().getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
  •                 for (int appWidgetId : appWidgetIds)

  •  
  •                 {

  •  
  •                         if(appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID)

  •  
  •                                 continue;

  •  
  • //schemeはURI_に等しくないSCHEMEは、このメッセージがシステム
  • からのものであることを示す
     
  • //タイミング更新またはwidget初回作成またはシステム再起動
  •  
  •                         if (!URI_SCHEME.equals(intent.getScheme())) {

  •  
  •                                 setAlarm(context, appWidgetId, updateTime);

  •  
  •                         }

  •  
  •                         else {

  •  
  • //ここで更新時間を変更できます.必要に応じて
  •  
  • //例:
  •  
  •                         //setAlarm(context, appWidgetId, theValueComeFromPreference

  •  
  •                         }

  •  
  •                 }

  •  
  •                 super.onReceive(context, intent);

  •  
  •         }

  •  
  • }
  • private void setAlarm(Context context, int appWidgetId, int updateRateSeconds) {
  •         Intent widgetUpdate = new Intent();
  •         widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
  •         widgetUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { appWidgetId });
  •         //给来自计时器的消息加标识
  •         widgetUpdate.setData(Uri.withAppendedPath(Uri.parse(URI_SCHEME + "://widget/id/"), String.valueOf(appWidgetId)));
  •         PendingIntent newPending = PendingIntent.getBroadcast(context, 0, widgetUpdate, PendingIntent.FLAG_UPDATE_CURRENT);
  •         AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
  •         if (updateRateSeconds >= 0) {
  •                 alarms.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), updateRateSeconds, newPending);
  •         } else {
  •                 alarms.cancel(newPending);
  •         }
  • }
  •            ,   AndroidManifest.xml      :

  •             android:name=".widget"
  •             android:label="@string/app_name"
  •             >
  •             
  •                     
  •                     
  •             
  •             
  •                     android:resource="@xml/widget"
  •                     />

  • タイミング更新が実現しました.次に、インタフェースを示します.
  • public static final String PREFS_NAME = "com.example.widget_preferences";
  • public static final String PREFS_WIDGET_DATA = "WidgetData-%d";
  • public static final String PREFS_CURRENT_INDEX = "CurrentIndex-%d";
  • private static final String ACTION_WIDGET_CONTROL = "com.example.widget.WIDGET_CONTROL";
  • public void onUpdate(Context context, AppWidgetManager appWidgetManager,
  •             int[] appWidgetIds) {
  •         // TODO Auto-generated method stub
  •         final int N = appWidgetIds.length;
  •         SharedPreferences shared = context.getSharedPreferences(PREFS_NAME, 0);
  •         SharedPreferences.Editor editor = shared.edit();
  •         for(int i = 0; i < N; i++)
  •         {
  •                 if(appWidgetIds[i] == AppWidgetManager.INVALID_APPWIDGET_ID)
  •                         continue;
  •                 int appWidgetId = appWidgetIds[i];
  •                 String widgetDataStr = “data1=value|||data2=value|||data3=value|||data4=value”;
  •                 editor.putString(String.format(PREFS_WIDGET_DATA, appWidgetIds[i]), widgetDataStr);
  •                 editor.putInt(String.format(PREFS_CURRENT_INDEX, appWidgetIds[i]), 0);
  •                 updateDisplay(context, appWidgetId, getDataByKey(widgetDataStr, 0));
  •         }
  •         editor.commit();
  • }
  • private String[] getDataByKey(String dataStr, int index)
  • {
  •         String[] strArr= dataStr.split("//|//|//|");
  •         if(index < 0)
  •                 index = 0;
  •         if(index >= strArr.length)
  •                 index = strArr.length - 1;
  •         strArr = strArr[index].split("=", 2);
  •         if(strArr.length == 2)
  •                 return strArr;
  •         return new String[]{"",""};
  • }
  • public void updateDisplay(Context context, int appWidgetId, String[] playData)
  • {
  •         RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.appwidget);
  •         remoteView.setTextViewText(R.id.widget_word, playData[0]);
  •         remoteView.setTextViewText(R.id.widget_meaning, playData[1]);
  •         remoteView.setOnClickPendingIntent(R.id.widget_back, makeControlPendingIntent(context, "back", appWidgetId));
  •         remoteView.setOnClickPendingIntent(R.id.widget_next, makeControlPendingIntent(context, "next", appWidgetId));
  •         AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, remoteView);
  • }
  • public PendingIntent makeControlPendingIntent(Context context, String command, int appWidgetId)
  • {
  •         Intent action = new Intent();
  •         action.setAction(ACTION_WIDGET_CONTROL);
  •         action.putExtra(EXTRA_APPWIDGET_ID, appWidgetId);
  •         Uri data = Uri.withAppendedPath(Uri.parse(URI_SCHEME + "://widget/id/#" + command), String.valueOf(appWidgetId));
  •         action.setData(data);
  •         return (PendingIntent.getBroadcast(context, 0, action, PendingIntent.FLAG_ONE_SHOT));
  • }

  • これによりwidgetは正常に表示されます.もちろん、イベントを処理するメッセージはまだ受け入れられません.次に受信機を登録します.
     
    
      
      
      
      
    1. <receiver
    2.         android:name=".widget"
    3.        android:label="@string/app_name"
    4.         >
    5.         <intent-filter>
    6.                 <action android:name="com.example.widget.WIDGET_CONTROL"  />
    7.                 <data android:scheme="widget" />
    8.         </intent-filter>
    9.         <meta-data android:name="android.appwidget.provider"
    10.                 android:resource="@xml/widget"
    11.                 />
    12. </receiver>
    , :
    1. public void onReceive(Context context, Intent intent)
    2. if(ACTION_WIDGET_CONTROL.equals(action))
    3. {
    4.         final int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
    5.         if(appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID)
    6.         {
    7.                 String controlType = intent.getData().getFragment();
    8.                 SharedPreferences shared = context.getSharedPreferences(PREFS_NAME, 0);
    9.                 int index = shared.getInt(String.format(PREFS_CURRENT_INDEX, appWidgetId), 0);
    10.                 int size = Integer.parseInt(shared.getString(String.format(PREFS_DATA_SIZE, appWidgetId), "20"));
    11.                 if(controlType.equalsIgnoreCase("next"))
    12.                 {
    13.                     index++;
    14.                     if(index >= size)
    15.                         index = 0;
    16.                 }
    17.                 else if(controlType.equalsIgnoreCase("back"))
    18.                 {
    19.                     index--;
    20.                     if(index < 0)
    21.                         index = size - 1;
    22.                 }
    23.                 shared.edit().putInt(String.format(PREFS_CURRENT_INDEX, appWidgetId), index).commit();
    24.                 updateDisplay(
    25.                         context,
    26.                         appWidgetId,
    27.                         getDataByKey(shared.getString(String.format(PREFS_WIDGET_DATA, appWidgetId),""), index)
    28.                         );
    29.             }
    30. }
    31. }
    32. , :
    33. public void onDeleted(Context context, int[] appWidgetIds) {
    34.         // TODO Auto-generated method stub
    35.         SharedPreferences shared = context.getSharedPreferences(PREFS_NAME, 0);
    36.         for(int appWidgetId : appWidgetIds)
    37.         {
    38.                 setAlarm(context, appWidgetId, -1);
    39.                 shared.edit().remove(String.format(PREFS_WIDGET_DATA, appWidgetId))
    40.                          .remove(String.format(PREFS_CURRENT_INDEX, appWidgetId))
    41.                          .commit();
    42.         }
    43.         super.onDeleted(context, appWidgetIds);
    44. }