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" /> <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>
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);
}
}
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は正常に表示されます.もちろん、イベントを処理するメッセージはまだ受け入れられません.次に受信機を登録します.
機能:
タイミング更新の実装
同じグループのデータを表示でき、update時にデータソースを更新できます
イベントを傍受し、異なる反応を起こすことができます.
実装分析:
SDK1.5以降android:updatePeriodMillisは失効し、デフォルト更新に変更され、カスタムタイミング更新を実現するためにタイマーアクティブ更新が使用された.
Widgetは他のアプリケーションによって管理されており、共有データは非常に困難であり、sharedpreferencesにデータを書き込み、データソースを記録します.
Widgetの各種状態はメッセージ制御であり,イベント管理を容易にするために受信機をシステムに登録する.
まずAndroidManifestでxmlファイルにwidgetを登録するには:
res/xml/widget.xml widget :
, widget , sheme :
, AndroidManifest.xml :
タイミング更新が実現しました.次に、インタフェースを示します.
これによりwidgetは正常に表示されます.もちろん、イベントを処理するメッセージはまだ受け入れられません.次に受信機を登録します.
- <receiver
- android:name=".widget"
- android:label="@string/app_name"
- >
- <intent-filter>
- <action android:name="com.example.widget.WIDGET_CONTROL" />
- <data android:scheme="widget" />
- </intent-filter>
- <meta-data android:name="android.appwidget.provider"
- android:resource="@xml/widget"
- />
- </receiver>
, :
- public void onReceive(Context context, Intent intent)
- if(ACTION_WIDGET_CONTROL.equals(action))
- {
- final int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
- if(appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID)
- {
- String controlType = intent.getData().getFragment();
- SharedPreferences shared = context.getSharedPreferences(PREFS_NAME, 0);
- int index = shared.getInt(String.format(PREFS_CURRENT_INDEX, appWidgetId), 0);
- int size = Integer.parseInt(shared.getString(String.format(PREFS_DATA_SIZE, appWidgetId), "20"));
- if(controlType.equalsIgnoreCase("next"))
- {
- index++;
- if(index >= size)
- index = 0;
- }
- else if(controlType.equalsIgnoreCase("back"))
- {
- index--;
- if(index < 0)
- index = size - 1;
- }
- shared.edit().putInt(String.format(PREFS_CURRENT_INDEX, appWidgetId), index).commit();
- updateDisplay(
- context,
- appWidgetId,
- getDataByKey(shared.getString(String.format(PREFS_WIDGET_DATA, appWidgetId),""), index)
- );
- }
- }
- }
- , :
- public void onDeleted(Context context, int[] appWidgetIds) {
- // TODO Auto-generated method stub
- SharedPreferences shared = context.getSharedPreferences(PREFS_NAME, 0);
- for(int appWidgetId : appWidgetIds)
- {
- setAlarm(context, appWidgetId, -1);
- shared.edit().remove(String.format(PREFS_WIDGET_DATA, appWidgetId))
- .remove(String.format(PREFS_CURRENT_INDEX, appWidgetId))
- .commit();
- }
- super.onDeleted(context, appWidgetIds);
- }