最近幾天一直想做一個類似於時鐘的App Widget的效果,然後就開始設計,看了google 的有關文檔,按照步驟先弄出了一個沒有任何實際效果的widget,
又瞭解到相關的AppWidgetProvider其實是一個廣播接收者,可以接收特定的廣播事件,大致有以下幾個:
1.AppWidgetManager.ACTION_APPWIDGET_UPDATE,對應調用onUpdate()方法;
2.AppWidgetManager.ACTION_APPWIDGET_DELETED,對用調用onDeleted()方法;
3.AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED,對用調用onAppWidgetOptionsChanged()方法;
4.AppWidgetManager.ACTION_APPWIDGET_ENABLED,對用調用onEnabled()方法;
5.AppWidgetManager.ACTION_APPWIDGET_DISABLED,對用調用onDisabled()方法;
具體實現過程:其實每次在調用不同生命週期方法時,都會先調用onReceive()方法,因爲它是廣播接收者,在onReceive()方法中根據開啓廣播的意圖的action來調用相應的方法,附onReceive()方法的源碼:
public void onReceive(Context context, Intent intent) {
// Protect against rogue update broadcasts (not really a security issue,
// just filter bad broacasts out so subclasses are less likely to crash).
String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
Bundle extras = intent.getExtras();
if (extras != null) {
int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
if (appWidgetIds != null && appWidgetIds.length > 0) {
this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds);
}
}
} else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
Bundle extras = intent.getExtras();
if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
final int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
this.onDeleted(context, new int[] { appWidgetId });
}
} else if (AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED.equals(action)) {
Bundle extras = intent.getExtras();
if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)
&& extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS)) {
int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
Bundle widgetExtras = extras.getBundle(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS);
this.onAppWidgetOptionsChanged(context, AppWidgetManager.getInstance(context),
appWidgetId, widgetExtras);
}
} else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) {
this.onEnabled(context);
} else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) {
this.onDisabled(context);
} else if (AppWidgetManager.ACTION_APPWIDGET_RESTORED.equals(action)) {
Bundle extras = intent.getExtras();
if (extras != null) {
int[] oldIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS);
int[] newIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
if (oldIds != null && oldIds.length > 0) {
this.onRestored(context, oldIds, newIds);
this.onUpdate(context, AppWidgetManager.getInstance(context), newIds);
}
}
}
}
另外在調試該應用的時候,出現了一個問題困擾我老半天,我在onEnable()方法中添加了斷點,然後開啓真機調試,但是一進入調試界面,在android studio 的調試視圖上,當程序運行到斷點時,過幾秒會自動退出調試過程,並且顯示“frame is not available”,就算重啓軟件,重新連接手機也是同樣的問提,簡直打擊我的積極性。而後我在stackoverflow上提出了這個問題,經過大神的不懈指導,終於發現了問題所在。
因爲AppWidgetProvider是一個廣播接受者, 所以當它的onEnabled()方法調用時,是因爲收到了相應的廣播,又因爲廣播接收者是在主線程中處理廣播事件,所以當一個廣播10秒鐘之內沒有得到響應的話,就會出現ANR異常,因爲我在onEnabled()方法中加了斷點,程序阻塞在這裏,這樣這個廣播事件沒有得到及時的相應,故程序會崩潰,故而debugger會停止。以後這種問題一定要多加註意!