App Widgets
App Widgets are miniature application views that can be embedded in other applications (such as the Home screen) and receive periodic updates. These views are referred to as Widgets in the user interface, and you can publish one with an App Widget provider. An application component that is able to hold other App Widgets is called an App Widget host.
翻譯:App Widgets是一個顯示在別的application中(比如顯示在桌面程序)的微型application views,並且定期接受更新。這個views在用戶界面被叫Widgets,你可以發布一個自己應用的Widget。Widget的application稱為App Widget host。
1、AppWidget 框架類
2、AppWidget 框架的主要類介紹
3、創建步驟和代碼
1、AppWidget 框架類
- 1、AppWidgetProvider :繼承自 BroadcastRecevier , 在AppWidget 應用 update、enable、disable 和 delete 時接收通知。其中,onUpdate、onReceive 是最常用到的方法,它們接收更新通知。
- 2、 AppWidgetProvderInfo:描述 AppWidget 的大小、更新頻率和初始界面等信息,以XML 文件形式存在於應用的 res/xml/目錄下。
- 3、AppWidgetManger :負責管理 AppWidget ,向 AppwidgetProvider 發送通知。
- 4、RemoteViews :一個可以在其他應用進程中運行的類,向 AppWidgetProvider 發送通知。
2、AppWidget 框架的主要類介紹
1) AppWidgetManger 類
- bindAppWidgetId(int appWidgetId, ComponentName provider)
通過給定的ComponentName 綁定appWidgetId - getAppWidgetIds(ComponentName provider)
通過給定的ComponentName 獲取AppWidgetId - getAppWidgetInfo(int appWidgetId)
通過AppWidgetId 獲取 AppWidget 信息 - getInstalledProviders()
返回一個List<AppWidgetProviderInfo>的信息 - getInstance(Context context)
獲取 AppWidgetManger 實例使用的上下文對象 - updateAppWidget(int[] appWidgetIds, RemoteViews views)
通過appWidgetId 對傳進來的 RemoteView 進行修改,並重新刷新AppWidget 組件 - updateAppWidget(ComponentName provider, RemoteViews views)
通過 ComponentName 對傳進來的 RemoeteView 進行修改,並重新刷新AppWidget 組件 - updateAppWidget(int appWidgetId, RemoteViews views)
通過appWidgetId 對傳進來的 RemoteView 進行修改,並重新刷新AppWidget 組件
2) 繼承自 AppWidgetProvider 可實現的方法為如下:
- 1、onDeleted(Context context, int[] appWidgetIds)
- 2、onDisabled(Context context)
- 3、onEnabled(Context context)
- 4、onReceive(Context context, Intent intent)
Tip:因為 AppWidgetProvider 是繼承自BroadcastReceiver 所以可以重寫onRecevie 方法,當然必須在后台注冊Receiver - 5、onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
- 一般來說都是重寫onUpdate就夠了
3.應用創建Widget步驟如下:
1.創建一個繼承了AppWidgetProvider的類,AppWidgetProvider是BroadcastReceiver。所以創建的類也是BroadcastReceiver
2.在清單文件中注冊該類,需要注意的是該類的action為:android.appwidget.action.APPWIDGET_UPDATE。
1 <receiver android:name=".receiver.MyWidget"> 2 <intent-filter> 3 <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/> 4 </intent-filter> 5 6 <meta-data 7 android:name="android.appwidget.provider" 8 android:resource="@xml/myappwidget_info"/> 9 </receiver>
在清單文件中,該類需要meta-data,
name為:android.appwidget.provider
resource為:在res/xml下定義的一個xml文件
3.創建清單文件中的resource文件
在res/xml下創建一個根節點為appwidget-provider的XML文件
1 <?xml version="1.0" encoding="utf-8"?> 2 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 3 android:initialLayout="@layout/appwidget_view" 4 android:minWidth="250dp" 5 android:minHeight="40dp" 6 android:previewImage="@drawable/ic_launcher" 7 android:updatePeriodMillis="1800000"> 8 </appwidget-provider>
initialLayout:Widget的布局文件,確定Widget中有哪些組件,怎么排列
minWidth:最小寬度 計算公式為:(70XN)-30,N為打算在屏幕上占幾格,高度也是這么計算的
minHeight:最小高度
previewImage:選擇部件時 展示的圖像
updatePeriodMillis:更新時間間隔,單位毫秒。系統為了省電,默認是30分鍾更新一次,如果你設置的值比30分鍾小,系統也是30分鍾才會更新一次。因為需要頻繁更新的Widget,需要自己起一個service進行更新了。
只需要以上內容就可以使用Widget了,下面還有一些參數:
label: 選擇部件時看到標簽
icon: 選擇部件時看到圖標
resizeMode :調整size模式
configure: 如果需要在啟動前先啟動一個Activity進行設置,在這里給出Activity的完整類名
widgetCategory="keyguard|home_screen" widget:可添加的位置 鎖屏界面|桌面
這樣就可以完成一個Widget。在組件中就可以看到定義的Widget了,可以放在桌面程序上。
更新Widget需要用的AppWidgetManger類
以下為實現的代碼和更新Widget的代碼:
1.MyWidget.java
1 public class MyWidget extends AppWidgetProvider { 2 3 //當把桌面上的Widget全部都刪掉的時候,調用該方法 4 @Override 5 public void onDisabled(Context context) { 6 super.onDisabled(context); 7 Intent stopUpdateIntent = new Intent(context, UpdateWidgetService.class); 8 context.stopService(stopUpdateIntent); 9 } 10 11 //當Widget第一次創建的時候,該方法調用,然后啟動后台的服務 12 @Override 13 public void onEnabled(Context context) { 14 super.onEnabled(context); 15 Intent startUpdateIntent = new Intent(context, UpdateWidgetService.class); 16 context.startService(startUpdateIntent); 17 } 18 19 20 @Override 21 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 22 super.onUpdate(context, appWidgetManager, appWidgetIds); 23 } 24 25 //在Widget使用中,會多次調用該方法 26 @Override 27 public void onReceive(Context context, Intent intent) { 28 super.onReceive(context, intent); 29 Intent startUpdateIntent = new Intent(context, UpdateWidgetService.class); 30 context.startService(startUpdateIntent); 31 } 32 }
2.清單文件:
1 //桌面widget 2 <receiver android:name=".receiver.MyWidget"> 3 <intent-filter> 4 <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/> 5 </intent-filter> 6 7 <meta-data 8 android:name="android.appwidget.provider" 9 android:resource="@xml/myappwidget_info"/> 10 </receiver>
3.myappwidget_info.xml,resource文件,定義在res/xml下
1 <?xml version="1.0" encoding="utf-8"?> 2 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 3 android:initialLayout="@layout/appwidget_view" 4 android:minWidth="294dp" 5 android:minHeight="40dp" 6 android:previewImage="@drawable/ic_launcher" 7 android:updatePeriodMillis="1800000"> 8 </appwidget-provider>
4.appwidget_view.xml,Widget布局文件
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:background="@drawable/widget_bg_portrait" 6 android:gravity="center_vertical" 7 android:orientation="horizontal"> 8 9 <LinearLayout 10 android:id="@+id/ll_processinfo" 11 android:layout_width="0dp" 12 android:layout_height="match_parent" 13 android:layout_marginLeft="5dp" 14 android:layout_weight="1" 15 android:background="@drawable/widget_bg_portrait_child" 16 android:gravity="center_vertical" 17 android:orientation="vertical" 18 android:paddingBottom="1dp" 19 android:paddingTop="1dp"> 20 21 <TextView 22 android:id="@+id/tv_runprocessnumber" 23 android:layout_width="wrap_content" 24 android:layout_height="wrap_content" 25 android:layout_marginLeft="15dp" 26 android:text="正在運行軟件:14" 27 android:textColor="@color/black" 28 android:textSize="16sp"/> 29 30 <ImageView 31 android:layout_width="match_parent" 32 android:layout_height="wrap_content" 33 android:layout_marginBottom="1dp" 34 android:layout_marginTop="1dp" 35 android:src="@drawable/widget_bg_portrait_child_divider"/> 36 37 <TextView 38 android:id="@+id/tv_avalimem" 39 android:layout_width="match_parent" 40 android:layout_height="wrap_content" 41 android:layout_marginLeft="15dp" 42 android:text="可用內存:300.52MB" 43 android:textColor="@color/black" 44 android:textSize="16sp"/> 45 46 47 </LinearLayout> 48 49 50 <LinearLayout 51 android:layout_width="wrap_content" 52 android:layout_height="wrap_content" 53 android:gravity="center_vertical" 54 android:orientation="vertical"> 55 56 <LinearLayout 57 android:layout_width="wrap_content" 58 android:layout_height="wrap_content" 59 android:gravity="center_vertical" 60 android:orientation="horizontal" 61 > 62 63 <ImageView 64 android:layout_width="20dp" 65 android:layout_height="20dp" 66 android:src="@drawable/ic_launcher"/> 67 68 <TextView 69 android:layout_width="wrap_content" 70 android:layout_height="wrap_content" 71 android:text="手機安全衛士" 72 android:textColor="@color/white"/> 73 74 </LinearLayout> 75 76 <Button 77 android:id="@+id/btn_killall" 78 android:layout_width="wrap_content" 79 android:layout_height="wrap_content" 80 android:layout_centerVertical="true" 81 android:layout_marginTop="3dp" 82 android:background="@drawable/function_greenbutton_selector" 83 android:gravity="center_vertical" 84 android:text="一鍵清理" 85 android:textColor="@color/function_greenbutton_textcolor_selector"/> 86 87 88 </LinearLayout> 89 90 </LinearLayout>
5.UpdateWidgetService.java,后台更新Widget的服務
1 public class UpdateWidgetService extends Service { 2 3 private Timer timer; 4 private TimerTask task; 5 6 public UpdateWidgetService() { 7 } 8 9 @Override 10 public IBinder onBind(Intent intent) { 11 throw new UnsupportedOperationException("Not yet implemented"); 12 } 13 14 @Override 15 public void onCreate() { 16 timer = new Timer(); 17 task = new TimerTask() { 18 @Override 19 public void run() { 20 int runningTaskCount = SystemInfoUtils.getRunningTaskCount(UpdateWidgetService.this); 21 long avaliMem = SystemInfoUtils.getAvaliMem(UpdateWidgetService.this); 22 ComponentName componentName = new ComponentName(UpdateWidgetService.this, MyWidget.class); 23 RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.appwidget_view); 24 25 //設置Widget中Textview的顯示內容 26 remoteViews.setTextViewText(R.id.tv_runprocessnumber, "正在運行軟件:" + runningTaskCount); 27 remoteViews.setTextViewText(R.id.tv_avalimem, "可用內存:" + Formatter.formatFileSize(UpdateWidgetService.this, avaliMem)); 28 29 //點擊widget的一鍵清理按鈕,發送廣播,在AutoKillTaskReceiver廣播中殺掉所有的進程。 30 Intent intent = new Intent(UpdateWidgetService.this, AutoKillTaskReceiver.class); 31 PendingIntent pendingIntent = PendingIntent.getBroadcast(UpdateWidgetService.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 32 remoteViews.setOnClickPendingIntent(R.id.btn_killall, pendingIntent); 33 34 //點擊widget顯示信息部分,跳到程序管理頁面 35 Intent startActivityIntent = new Intent(UpdateWidgetService.this, TaskManagerActivity.class); 36 startActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 37 PendingIntent processInfoIntent = PendingIntent.getActivity(UpdateWidgetService.this, 0, startActivityIntent, PendingIntent.FLAG_ONE_SHOT); 38 remoteViews.setOnClickPendingIntent(R.id.ll_processinfo, processInfoIntent); 39 40 //由AppWidgetManager處理Wiget。 41 AppWidgetManager awm = AppWidgetManager.getInstance(getApplicationContext()); 42 awm.updateAppWidget(componentName, remoteViews); 43 44 } 45 }; 46 timer.schedule(task, 0, 3000); 47 super.onCreate(); 48 } 49 50 @Override 51 public void onDestroy() { 52 super.onDestroy(); 53 timer.cancel(); 54 task.cancel(); 55 timer = null; 56 task = null; 57 } 58 }
6.實現效果圖: