Appwidget控件的使用
http://www.cnblogs.com/qianlifeng/archive/2011/03/26/1996407.html
什么是AppWidget?AppWidget就是我們平常在桌面上見到的那種一個個的小窗口,利用這個小窗口可以給用戶提供一些方便快捷的操作。本篇打算從以下幾個點來介紹AppWidget:
????? 1.如何創建一個簡單的AppWidget
????? 2.如何使得AppWidget與客戶端程序交互
創建簡單的AppWidget?????? 在介紹之前給大家看一下程序運行的最后結果和項目結構圖,以便大家有個整體的印象。
運行結果圖:
項目結構圖:
?????
?第一步:
???????????首先在res文件夾下新建一個名字為xml的文件夾,然后在xml目錄下創建一個名為appwidget01的xml文件(如上圖所示)。這個appwidget01中的內容如下:
| 1 2 3 4 5 6 7 8 9 | <? xml? version="1.0" encoding="utf-8"?> < appwidget-provider ?? xmlns:android="http://schemas.android.com/apk/res/android" ?? android:minWidth = "294dp" ?? android:minHeight = "72dp" ?? android:updatePeriodMillis = "86400000" ?? android:initialLayout = "@layout/appwidgetlayout" ?? > </ appwidget-provider > |
這個xml是用來描述你所要創建的appWidget的一些描述信息的,比如高度、寬度、刷新間隔、布局文件等等。僅僅這個描述文件還不夠,我們看到的appWidget可都是有界面元素的呀,比如說文本,圖片,按鈕等等,這些東西的定義都需要放到layout文件夾下面。這個文件就是上面代碼中寫到的那個appwidgetlayout。
第二步:
????????? 在layout文件夾下面新建一個appwidgetlayout.xml文件,在這個文件中描述了appWidget的控件和布局等等信息,就和我們平常創建的一個activity的布局文件沒什么兩樣,因為只是簡單的演示,所以僅用一個文本和一個按鈕。xml的內容如下:
| <? xml? version="1.0" encoding="utf-8"?> < LinearLayout? xmlns:android="http://schemas.android.com/apk/res/android" ???? android:layout_width="fill_parent" android:layout_height="fill_parent"> ???? < TextView? android:id="@+id/txtapp" android:text="test" android:layout_width="wrap_content" ???????? android:layout_height="wrap_content" android:background="#ffffff"></ TextView > ???? < Button? android:id="@+id/btnSend" android:layout_width="wrap_content" ???? android:layout_height="wrap_content" android:text="Send"></ Button > </ LinearLayout > |
第三步:
??????????既然appWidget中存在按鈕等等控件,那么就肯定少不了處理這些控件事件的處理代碼啦。這些代碼被放在一個繼承于AppWidgetProvider的類中,在本例子中我新建了一個AppWidget的類,該類繼承于AppWidgetProvider,以后所有的AppWidget上面的控件事件都會在這個類中處理。看一下類的內容:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | public? class? AppWidget? extends? AppWidgetProvider { ???? private? final? String broadCastString =? "com.qlf.appWidgetUpdate" ; ????? ???? /** ????? * 刪除一個AppWidget時調用 ????? * */ ???? @Override ???? public? void? onDeleted(Context context,? int [] appWidgetIds) ???? { ???????? super .onDeleted(context, appWidgetIds); ???? } ???? /** ????? * 最后一個appWidget被刪除時調用 ????? * */ ???? @Override ???? public? void? onDisabled(Context context) ???? { ???????? super .onDisabled(context); ???? } ???? /** ????? * AppWidget的實例第一次被創建時調用 ????? * */ ???? @Override ???? public? void? onEnabled(Context context) ???? { ???????? super .onEnabled(context); ???? } ???? /** ????? * 接受廣播事件 ????? * */ ???? @Override ???? public? void? onReceive(Context context, Intent intent) ???? { ????????????? super .onReceive(context, intent); ???? } ???? /** ????? * 到達指定的更新時間或者當用戶向桌面添加AppWidget時被調用 ????? * */ ???? @Override ???? public? void? onUpdate(Context context, AppWidgetManager appWidgetManager, ???????????? int [] appWidgetIds) ???? { ?????????????????? ???? } ????? } |
各個方法的作用大家一看上面的注釋就明白了。我們暫時不需要實現里面的方法。
第四步:
??????? 在AndroidManifest.xml中定義一些創建AppWidget必要的東西,先看代碼:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <? xml? version="1.0" encoding="utf-8"?> < manifest? xmlns:android="http://schemas.android.com/apk/res/android" ???? package="com.qlf.widget" android:versionCode="1" android:versionName="1.0"> ???? < application? android:icon="@drawable/icon" android:label="@string/app_name"> ???????? < activity? android:name=".MainActivity" android:label="@string/app_name"> ???????????? < intent-filter > ???????????????? < action? android:name="android.intent.action.MAIN" /> ???????????????? < category? android:name="android.intent.category.LAUNCHER" /> ???????????? </ intent-filter > ???????? </ activity > ???????? < receiver? android:name="AppWidget"> ???????????? < intent-filter > ???????????????? < action? android:name="android.appwidget.action.APPWIDGET_UPDATE"></ action > ???????????? </ intent-filter > ???????????? < meta-data? android:name="android.appwidget.provider" ???????????????? android:resource="@xml/appwidget01" /> ???????? </ receiver > ???? </ application > ???? < uses-sdk? android:minSdkVersion="8" /> </ manifest > |
可以看到我們在配置文件里面定義了一個receiver,他的名字是上面創建處理控件代碼的那個類,下面那個intent-filter中的action是系統自帶的用于更新所有appwidget的廣播動作。然后meta-data標簽是一個描述我們創建appwidget的元數據,那個android:name="android.appwidget.provider"是固定的,android:resource="@xml/appwidget01"指定創建的appWidget的描述信息的位置。這樣程序就知道到哪里去初始化這些appWidget啦。?
??????? 經過上面四個步驟,我想您已經能夠成功在桌面上添加小工具了,效果就是我們最前面發出的樣子。
??????? 前面我們只是簡單的介紹了如何創建一個appWidget,但是目前這個appWidget還沒有任何的交互功能。下面我們介紹一下appWidget如何與程序進行交互。首先要介紹一個對象,這個對象在appwidget和程序的交互中很重要,他就是RemoteViews。因為appwidget運行的進程和我們創建的應用不在一個進程中,所以我們也就不能像平常引用控件那樣來獲得控件的實例。這個時候RemoteViews出場了,從字面上看他的意思是遠程的視圖,也就是說通過這個東西我們能夠獲得不在同一進程中的對象,這也就為我們編寫appwidget的處理事件提供了幫助。我們使用一下代碼來創建一個RemoteViews :
| 1 2 3 | RemoteViews remoteViews? =? new? RemoteViews(context.getPackageName(),R.layout.appwidgetlayout); remoteViews.setOnClickPendingIntent(R.id.btnSend, pendingIntent);?? //為小工具上的按鈕綁定事件 |
可以看到上面又出現了一個陌生的對象pendingIntent,這個又是用來干嘛的呢?我們知道在一般的程序中綁定按鈕的點擊事件是直接在實現了OnClickListener接口的類中中完成的。不過因為appwidget并不在我們應用的進程中,所以當然他也訪問不到我們在應用中設置的onclick代碼啦。而PendingIntent就是被用來解決這個問題的。PendingIntent可以看成是一個特殊的Intent,如果我們把Intent看成一封信,那么PendingIntent就是一封被信封包裹起來的信。這封信在remoteViews.setOnClickPendingIntent()中被“郵寄”到了appwidget, 當appwidget中的按鈕單擊時他知道將這封信打開,并執行里面的內容。這樣就避免了直接從appwidget中執行本地代碼。我們來看看PendingIntent是如何定義的:
| 1 2 3 4 5 6 | //創建一個Intent對象 Intent intent =? new? Intent(); intent.setAction(broadCastString); //這一步相當于寫信,說明這個信的作用到底是什么,在這里表示將發送一個廣播 PendingIntent pendingIntent = PendingIntent.getBroadcast(context,? 0 , intent,? 0 ); |
有了上面的介紹,我們在創建appwidget的交互應用時就簡單不少了。我們剩下要做的工作就是在appwidget在創建的時候調用上面說到的方法為appwidget中的控件綁定事件,也就是在AppWidget類下的onUpdate方法中完成這個過程。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /** * 到達指定的更新時間或者當用戶向桌面添加AppWidget時被調用 * */ @Override public? void? onUpdate(Context context, AppWidgetManager appWidgetManager, ???????? int [] appWidgetIds) { ???????? //創建一個Intent對象 ???????? Intent intent =? new? Intent(); ???????? intent.setAction(broadCastString); ???????? //設置pendingIntent的作用 ???????? PendingIntent pendingIntent = PendingIntent.getBroadcast(context,? 0 , intent,? 0 ); ???????? RemoteViews remoteViews? =? new? RemoteViews(context.getPackageName(),R.layout.appwidgetlayout); ???????? ???????? //綁定事件 ???????? remoteViews.setOnClickPendingIntent(R.id.btnSend, pendingIntent); ????????? ???????? //更新Appwidget ???????? appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); } |
通過上面的代碼我們就為button按鈕綁定了一個事件,這個事件的作用是發送一個廣播便于其他應用接收、更新信息。這是appwidget發送廣播,那么appwidget如何接受來自其他程序發送的廣播呢?這就是public void onReceive(Context context, Intent intent)的功能啦。這個方法會接收來自其他應用發出的廣播,我們只要在這個程序中過濾我們需要的廣播就能響應其他應用的操作來更新appwidget的信息了。要注意的是,因為appwidget運行的進程和我們創建的應用不在一個進程中的限制,所以更新的appwidget的時候也要通過遠程對象來操作,具體代碼如下:
??
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /** ??? * 接受廣播事件 ??? * */ ?? @Override ?? public? void? onReceive(Context context, Intent intent) ?? { ?????? if? (intent.getAction().equals(broadCastString)) ?????? {??????????????? ?????????? //只能通過遠程對象來設置appwidget中的控件狀態 ?????????? RemoteViews remoteViews? =? new? RemoteViews(context.getPackageName(),R.layout.appwidgetlayout); ????????? //通過遠程對象將按鈕的文字設置為”hihi” ?????????? remoteViews.setTextViewText(R.id.btnSend,? "hihi" );??? ???????????? ?????????? //獲得appwidget管理實例,用于管理appwidget以便進行更新操作 ?????????? AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); ??????????? ?????????? //相當于獲得所有本程序創建的appwidget ?????????? ComponentName componentName =? new? ComponentName(context,AppWidget. class ); ??????????? ?????????? //更新appwidget ?????????? appWidgetManager.updateAppWidget(componentName, remoteViews); ?????? } ?????? super .onReceive(context, intent); ?? } |
總結下就是appwidget上的操作都必須借助遠程對象來操作。最后看一下運行的圖片吧:
按之前:
按之后:
總結
以上是生活随笔為你收集整理的Appwidget控件的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: eBay、亚马逊、Lazada、Shop
- 下一篇: IP地址、子网掩码与划分方法