App Widget

開發APP Widget的步驟java


一、繼承AppWidgetProvider類,android

public class MyWidget extends AppWidgetProvider{
<!-- 每個Widget放置到桌面上時調用,每一次updatePeriodMillis時間到了以後也會被調用-->    
public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds)
<!-- 移除widget時調用-->
public void onDeleted(Context context, int[] appWidgetIds)
<!-- 無論添加多少個widget,都只會調用一次 -->
public void onEnabled(Context context)
<!-- 當最後一個widget從桌面刪除的時候調用-->
public void onDisabled(Context context)

<!-- 可用作Widget上的按鍵響應處理-->
public void onReceive(Context context, Intent intent)
    
}

通常在onUpdate中進行widget中按鍵的事件處理,和初始化值。app



二、AppWidgetProvider是一個Broadcast,須要在Mainfest.xml中註冊。ide

 <receiver android:name="繼承AppWidgetProvider的類">
           <intent-filter >
               <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
           </intent-filter>
           <meta-data android:name="android.appwidget.provider"
               android:resource="@xml/widget_config"/>
 </receiver

   三、 <meta-data>中的android:resource引用的是Widget的配置文件,須要在res/xml下新建,若是xml目錄不存在,也須要新建。
佈局

 widget_config文件
測試

<?xml version="1.0" encoding="UTF-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="40dp"  <!-- 顯示在桌面上最小的的寬,高,不能大於4*4的格子-->
    android:minHeight="20dp" 
    android:updatePeriodMillis="1000000"  <!-- widget的更新間隔時間-->
    android:previewImage="@drawable/l7"  <!-- 預覽圖-->
    android:initialLayout="@layout/my_widgets_layout" <!-- 在桌面的顯示佈局,在3.0版本以後可使用,默認以應用圖標顯示。-->
    android:resizeMode="horizontal|vertical"  <!-- 在桌面可調整的方向-->
     android:configure="cn.fly.widgets.MyWidgetsConfigActivity"> <!-- 當widget在拖到桌面上時,顯示的配置文件-->
     
    <!--加上如下配置,在4.2版本能夠放到鎖屏界面上,4.2如下的版本默認是放主屏幕
    android:widgetCategory ="home_screen|keyguard" 
    android:initialKeyguardLayout="" 在鎖屏界面上顯示的佈局
     -->
</appwidget-provider>

設置了updatePeriodMillis後,就算手機處於待機狀態,也會喚醒手機去執行更新操做,若是widget更新頻繁,這會對手機電池壽命形成影響,因此針對這種狀況,可使用AlarmManager來執行定時更新操做,將AlarmManager的Type設置爲 ELAPSED_REALTIME 或者 RTC,就能夠保證手機在喚醒的狀態下執行更新,updatePeriodMillis則須要設置爲0。this


在桌面顯示的佈局文件的跟節點必須是經常使用佈局例如:Framelayout,linearLayout,viewStub等,不能使用自定義佈局。調試


在4.0之後的版本,widget放置到桌面上是能夠根據其餘的widget或者快捷圖標來擴充邊距,使添加的widget可以在桌面視覺上達到協調,可是4.0如下的版本須要本身來設置Padding,使widget能和其餘桌面圖標達到視覺協調。component


作完以上的操做,一個簡單的widget的就完成了,根據應用需求咱們會遇到如下的一些狀況。xml

1、相應widget的按鍵事件

    由於widget不是運行在自身的應用的進程中,因此是經過如下方式來處理事件。

  RemoteView 進行佈局引用。

   PendingIntent  進行事件分發。

//這段代碼通常寫在onUpdate中,所處理的事情是按button更改Textview的顯示
final int N = appWidgetIds.length;
for(int i = 0;i< N;i++){
    Intent intent = new Intent("自定義action用來標示這個intent");
    intent.setClass(context, MyWidgets.class);
    //發送廣播,在onReceive()中進行處理PendingIntent也能夠啓動Activity,也能夠//啓動Service
    PendingIntent mPendingIntent = PendingIntent.getBroadcast(context, 
					0, intent, 0);
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
					"widget佈局引用");
    //button按鍵處理
    remoteViews.setOnClickPendingIntent(R.id.btn_click, mPendingIntent);
    appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews);
}

  在onReceive()的處理

String action = intent.getAction();
if(action.equals("比較發送的action")){
    RemoteViews remoteViews  = new RemoteViews(context.getPackageName(),"widget佈局引用");
    //更改文本顯示
    remoteViews.setTextViewText(R.id.tv, "測試");
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 
    ComponentName componentName = new ComponentName(context,MyWidgets.class);
    appWidgetManager.updateAppWidget(componentName, remoteViews); 
		}

2、widget添加上桌面上時的配置頁面

這個配置頁面是一個activity,因此須要在mainfest.xml中進行配置

一、在啓動這個配置頁面的時候,須要在oncreate()方法裏面寫上setResult(RESULT_CANCELED);這樣作是爲了防止配置頁面尚未顯示出來,用戶就按了返回鍵,

setResult(RESULT_CANCELED);
super.onCreate(savedInstanceState);

二、須要獲取widgetId

Intent intent = getIntent();
Bundle extra = intent.getExtras();
if(extra !=null){
    mAppWidgetId  = extra.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}

若是mAppWidgetId爲INVALID_APPWIDGET_ID則退出頁面顯示。

三、當配置頁面顯示後,用戶作完了配置退出頁面時,須要將這些配置信息更新到桌面的widget,照着官方給出的文檔上來操做的話,只能顯示widget可是配置並無生效,參考了appdemo中的例子和我的調試後總結以下。


在MyWidget中寫一個靜態方法

 //describe是一個在配置文件中自由輸入文本,而後在widget的text上顯示,widget是爲了作到代碼重用,這裏只是一個簡單的更改文本,若是涉及到圖片更改,列表數據改動等,這些改動若是有配置界面的話基本上和onupdate所作的操做同樣。
 public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,int appWidgetId, String describe) {
   RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider);
   views.setTextViewText(R.id.tv, describe);
   appWidgetManager.updateAppWidget(appWidgetId, views);
}

在配置界面的退出方法中這樣寫

private void exits(){
    String describe = et.getText().toString();
    Context context = this;
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    //appWidgetId在進入配置界面的時候已經獲取了
    MyWidget.updateAppWidget(context,appWidgetManager,appWidgetId , describe );
    
    //配置完成退出界面
    Intent intent = new Intent();
    resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    setResult(RESULT_OK, intent );
    finish();
}

當時參考文檔作時,文檔中並無提到調用updateAppWidget方法後,退出界面須要從新獲取view,並改變view的顯示數據。因此我只寫了appWidgetManager.updateAppWidget(appWidgetId, views)方法。

相關文章
相關標籤/搜索