<receiver android:name=".receiver.GoldWidgetProvider"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="com.fuqi.gold.action_updatewidget" /> <action android:name="com.fuqi.gold.action_click_updatewidget" /> <action android:name="com.fuqi.gold.action_to_buygold" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/goldwidget_provider_info" /> </receiver>
這個就至關於一個廣播接收者,而後android:name屬性指定在第四步的時候建立的文件名html
android:resource="@xml/example_appwidget_info"/>是widget的配置文件java
在項目的 res/xml/ 目錄下。若是沒有xml目錄,須要新建一個android
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="40dp" android:minHeight="40dp" android:updatePeriodMillis="86400000" android:previewImage="@drawable/preview" android:initialLayout="@layout/example_appwidget" android:resizeMode="horizontal|vertical" android:widgetCategory="home_screen"> </appwidget-provider>
initialLayout是widget的佈局文件app
previewImage就是widget的預覽效果ide
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/widget_margin"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:background="@drawable/my_widget_background"> … </LinearLayout> </FrameLayout>
這個類實際上是繼承至廣播接收者的函數
public class AppWidgetProvider extends BroadcastReceiver {
而後呢,咱們通常只須要用到onUpdate()方法,這個方法的更新時間,是你在example_appwidget_info配置文件中設置的android:updatePeriodMillis屬性決定的,這個地方有個坑,稍候再說佈局
public class GoldWidgetProvider extends AppWidgetProvider { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N = appWidgetIds.length; for (int i=0; i<N; i++) { int appWidgetId = appWidgetIds[i]; Intent intent = new Intent(context, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout); views.setOnClickPendingIntent(R.id.button, pendingIntent); widget appWidgetManager.updateAppWidget(appWidgetId, views); } } }
// 重寫OnReceiver方法 @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); String action = intent.getAction(); // 須要在Manifest中註冊這個Action if (ACTION_UPDATE_WIDGET.equals(action)) { // update widget RemoteViews views = getRemoteViews(context, null); ComponentName name = new ComponentName(context, GoldWidgetProvider.class); AppWidgetManager.getInstance(context).updateAppWidget(name, views); }else if (ACTION_CLICK_UPDATE_WIDGET.equals(action)){ RemoteViews remoteViews = getRemoteViews(context, "正在刷新..."); ComponentName name = new ComponentName(context, GoldWidgetProvider.class); AppWidgetManager.getInstance(context).updateAppWidget(name, remoteViews); Intent goldPrice = new Intent(context, GoldPriceService.class); context.startService(goldPrice); } } public static RemoteViews getRemoteViews(Context context, String updating) { RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.goldwidget); //1,設置金價 if (TextUtils.isEmpty(updating)) { String buyGoldPrice = ShaPreUtils.getBuyGoldPrice(context); views.setTextViewText(R.id.widget_tv_goldprice, buyGoldPrice); } else { views.setTextViewText(R.id.widget_tv_goldprice, updating); } //2,設置持有金 if (GoldApplication.getInstance().isLogined()) { String total = GoldApplication.getInstance().getUserLoginInfo().getAccountInfo().getTotal(); ShaPreUtils.putTotalGold(context,total); views.setTextViewText(R.id.widget_tv_total, total); views.setViewVisibility(R.id.widget_total_layout,View.VISIBLE); }else if (TextUtils.isEmpty(ShaPreUtils.getTotalGold(context))){ views.setViewVisibility(R.id.widget_total_layout,View.GONE); }else{ views.setViewVisibility(R.id.widget_total_layout,View.VISIBLE); views.setTextViewText(R.id.widget_tv_total,ShaPreUtils.getTotalGold(context)); } //3,點擊事件 Intent toStartActivity = new Intent(context, AppStart.class); views.setOnClickPendingIntent(R.id.widget_to_app, PendingIntent.getActivity(context, 0, toStartActivity, 0)); // 買金的時候發送一個廣播,當前類接收 Intent to_buygold = new Intent(context, GoldWidgetProvider.class); to_buygold.setAction(ACTION_TO_BUYGOLD); views.setOnClickPendingIntent(R.id.widget_to_buygold, PendingIntent.getBroadcast(context, 0,to_buygold , 0)); // 主動刷新廣播 Intent layout = new Intent(context, GoldWidgetProvider.class); layout.setAction(ACTION_CLICK_UPDATE_WIDGET); views.setOnClickPendingIntent(R.id.widget_layout, PendingIntent.getBroadcast(context, 0, layout, 0)); return views; }
一開始的時候照着官方文檔在appwidget_info xml文件裏設置了這個屬性,在添加到桌面上的時候老是不成功,將這個屬性去掉就能夠了,不知道這個屬性具體怎麼用,有知道的麻煩告訴我一聲,感激涕零...
查看官方文檔法相這個屬性是給widget設置一個config,具體怎麼使用能夠查看官方文檔ui
updateAppWidget(int[] appWidgetIds, RemoteViews views)code
updateAppWidget(ComponentName provider, RemoteViews views) {xml
updateAppWidget(int[] appWidgetIds, RemoteViews views)代碼以下:
// 更新 widget 的廣播對應的action private final String ACTION_UPDATE_ALL = "com.skywang.widget.UPDATE_ALL"; // 保存 widget 的id的HashSet,每新建一個 widget 都會爲該 widget 分配一個 id。 private static Set idsSet = new HashSet(); @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Log.d(TAG, "onUpdate(): appWidgetIds.length="+appWidgetIds.length); // 每次 widget 被建立時,對應的將widget的id添加到set中 for (int appWidgetId : appWidgetIds) { idsSet.add(Integer.valueOf(appWidgetId)); } } @Override public void onDeleted(Context context, int[] appWidgetIds) { Log.d(TAG, "onDeleted(): appWidgetIds.length="+appWidgetIds.length); // 當 widget 被刪除時,對應的刪除set中保存的widget的id for (int appWidgetId : appWidgetIds) { idsSet.remove(Integer.valueOf(appWidgetId)); } super.onDeleted(context, appWidgetIds); } //接收廣播的回調函數 @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (ACTION_UPDATE_ALL.equals(action)) { // 「更新」廣播 updateAllAppWidgets(context, AppWidgetManager.getInstance(context), idsSet); } } // 更新全部的 widget private void updateAllAppWidgets(Context context, AppWidgetManager appWidgetManager, Set set) { Log.d(TAG, "updateAllAppWidgets(): size="+set.size()); // widget 的id int appID; // 迭代器,用於遍歷全部保存的widget的id Iterator it = set.iterator(); while (it.hasNext()) { appID = ((Integer)it.next()).intValue(); if (DEBUG) Log.d(TAG, "onUpdate(): index="+index); // 獲取 example_appwidget.xml 對應的RemoteViews RemoteViews remoteView = getRemoteViews(context,""); // 更新 widget appWidgetManager.updateAppWidget(appID, remoteView); } }
上面這些代碼有個隱患,在應用退出後,或是被第三方軟件殺死,點擊桌面widget就不會更新了。緣由是updateid我是用static的set集合保存的,應用退出後,這個set集合就被清空了,後面又換成了updateAppWidget(ComponentName)方法後就行了。
RemoteViews views = getRemoteViews(context, null); ComponentName name = new ComponentName(context, GoldWidgetProvider.class); AppWidgetManager.getInstance(context).updateAppWidget(name, views);
Intent intent = new Intent(ACTION_CLICK_UPDATE_WIDGET); views.setOnClickPendingIntent(R.id.widget_layout, PendingIntent.getBroadcast(context, 0, intent, 0));
上面這種寫法在應用退出後在有些手機上收不到廣播,而後換成下面這種寫法
Intent layout = new Intent(context, GoldWidgetProvider.class); layout.setAction(ACTION_CLICK_UPDATE_WIDGET); views.setOnClickPendingIntent(R.id.widget_layout, PendingIntent.getBroadcast(context, 0, layout, 0));