本章繼續講述在android界面設計中相關的知識點。介紹內容包括BroadcastReceiver(廣播),Service(服務),Widget(小部件),WebView(網頁加載控件)。
1.BroadcastReceiver
(1)廣播簡介
在Android中,Broadcast是一種廣泛運用的在應用程序之間傳輸信息的機制。而BroadcastReceiver是對發送出來的 Broadcast進行過濾接受並響應的一類組件。
廣播接收者( BroadcastReceiver )用於接收廣播 Intent ,廣播 Intent 的發送是通過調用 Context.sendBroadcast() 、 Context.sendOrderedBroadcast() 來實現的。通常一個廣播 Intent 可以被訂閱了此 Intent 的多個廣播接收者所接收。
(2)廣播機制
首先在需要發送信息的地方,把要發送的信息和用於過濾的信息(如Action、Category)裝入一個Intent對象,然后通過調用 sendOrderBroadcast()或sendStickyBroadcast()方法,把 Intent對象以廣播方式發送出去。
當Intent發送以后,所有已經注冊的BroadcastReceiver會檢查注冊時的IntentFilter是否與發送的Intent 相匹配,若匹配則就會調用BroadcastReceiver的onReceive()方法。所以當我們定義一個BroadcastReceiver的時候,都需要實現onReceive()方法。
(3)廣播注冊
- 靜態注冊:在AndroidManifest.xml中用標簽生命注冊,並在標簽內用標簽設置過濾器。例如:
<receiver android:name="myRecevice"> //繼承BroadcastReceiver,重寫onReceiver方法
<intent-filter>
<action android:name="com.dragon.net"></action> //使用過濾器,接收指定action廣播
</intent-filter>
</receiver>
- 動態注冊:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(String); //為BroadcastReceiver指定action,使之用於接收同action的廣播
registerReceiver(BroadcastReceiver,intentFilter);
一般:在onStart中注冊,onStop中取消unregisterReceiver
指定廣播目標Action:Intent intent = new Intent(actionString);
並且可通過Intent攜帶消息 :intent.putExtra("msg", "hi,我通過廣播發送消息了");
2.Service
(1)服務簡介
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
翻譯過來就是:Service(服務)是一個沒有用戶界面的在后台運行執行耗時操作的應用組件。其他應用組件能夠啟動Service,並且當用戶切換到另外 的應用場景,Service將持續在后台運行。另外,一個組件能夠綁定到一個service與之交互(IPC機制),例如,一個service可能會處理 網絡操作,播放音樂,操作文件I/O或者與內容提供者(content provider)交互,所有這些活動都是在后台進行。
Service有兩種狀態,“啟動的”和“綁定”。Service生命周期流程如下圖所示:
(2)啟動方式
- startService 啟動的服務:主要用於啟動一個服務執行后台任務,不進行通信。停止服務使用stopService;
- bindService 啟動的服務:該方法啟動的服務可以進行通信。停止服務使用unbindService;
- startService 同時也 bindService 啟動的服務:停止服務應同時使用stepService與unbindService
綁定狀態的service,通過調用bindService()來啟動,一個綁定的service提供一個允許組件與service交互的接 口,可以發送請求、獲取返回結果,還可以通過誇進程通信來交互(IPC)。綁定的service只有當應用組件綁定后才能運行,多個組件可以綁定一個 service,當調用unbind()方法時,這個service就會被銷毀了。
(3)使用方法
注冊Service,啟動Service,在AndroidManifest.xml中注冊,注冊代碼如下:
<service android:name="com.example.trywidgetsimplest.MusicManageService" ></service>
啟動服務:
Intent startIntent = new Intent(MainActivity.this,MusicManageService.class);
startService(startIntent);
停止服務:
Intent startIntent = new Intent(MainActivity.this,MusicManageService.class);
stopService(startIntent);
綁定服務:
綁定服務,便於數據交互或者訪問其中的一些方法:
public boolean bindService(Intent intent, ServiceConnection conn, int flags) ;
public void unbindService(ServiceConnection conn);
intent是跳轉到service的intent,如 Intent intent = new Intent();intent.setClass(this,MyService.class);
conn則是一個代表與service連接狀態的類,當我們連接service成功或失敗時,會主動觸發其內部的onServiceConnected或onServiceDisconnected方法。訪問service中的數據,可以在onServiceConnected()方法中進行實現。
(4)注意事項
- 在調用 bindService 綁定到Service的時候,應當保證在某處調用 unbindService 解除綁定(盡管 Activity 被 finish 的時候綁定會自動解除,並且Service會自動停止);
- 使用 startService 啟動服務之后,一定要使用 stopService停止服務,不管你是否使用bindService;
- 使用 startService 與 bindService 要注意到,Service 的終止,需要unbindService與stopService同時調用,才能終止 Service,不管 startService 與 bindService 的調用順序,如果先調用 unbindService 此時服務不會自動終止,再調用 stopService 之后服務才會停止,如果先調用 stopService 此時服務也不會終止,而再調用 unbindService 或者之前調用 bindService 的 Context 不存在了(如Activity 被 finish 的時候)之后服務才會自動停止;
- 當在旋轉手機屏幕的時候,當手機屏幕在“橫”“豎”變換時,此時如果你的 Activity 如果會自動旋轉的話,旋轉其實是 Activity 的重新創建,因此旋轉之前的使用 bindService 建立的連接便會斷開(Context 不存在了),對應服務的生命周期與上述相同。
3.Widget
(1)Widget簡介
App Widget是應用程序窗口小部件(Widget)是微型的應用程序視圖,它可以被嵌入到其它應用程序中(比如桌面)並接收周期性的更新。你可以通過一個App Widget Provider來發布一個Widget。
(2)Widget應用
appwidget-provider標簽:
這個玩意是用來定義桌面widget的大小,初始狀態等等信息的,它的位置應該放在res/xml文件夾下,具體的xml參數如下:
- android:minWidth : 最小寬度
- android:minHeight : 最小高度
- android:updatePeriodMillis : 更新widget的時間間隔(ms),"86400000"為1個小時
- android:previewImage : 預覽圖片
- android:initialLayout : 加載到桌面時對應的布局文件
- android:resizeMode : widget可以被拉伸的方向。horizontal表示可以水平拉伸,vertical表示可以豎直拉伸
- android:widgetCategory : widget可以被顯示的位置。home_screen表示可以將widget添加到桌面,keyguard表示widget可以被添加到鎖屏界面
- android:initialKeyguardLayout : 加載到鎖屏界面時對應的布局文件
示例XML:
<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:configure="com.example.android.ExampleAppWidgetConfigure"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen|keyguard"
android:initialKeyguardLayout="@layout/example_keyguard">
</appwidget-provider>
示例說明:
- minWidth 和minHeight
它們指定了App Widget布局需要的最小區域。缺省的App Widgets所在窗口的桌面位置基於有確定高度和寬度的單元網格中。如果App Widget的最小長度或寬度和這些網格單元的尺寸不匹配,那么這個App Widget將上舍入(上舍入即取比該值大的最接近的整數)到最接近的單元尺寸。注意:app widget的最小尺寸,不建議比 “4x4” 個單元格要大。關於app widget的尺寸,后面在詳細說明。
- minResizeWidth 和 minResizeHeight
它們屬性指定了 widget 的最小絕對尺寸。也就是說,如果 widget 小於該尺寸,便會因為變得模糊、看不清或不可用。 使用這兩個屬性,可以允許用戶重新調整 widget 的大小,使 widget 的大小可以小於 minWidth 和 minHeight。注意:當 minResizeWidth 的值比 minWidth 大時,minResizeWidth 無效;當 resizeMode 的取值不包括 horizontal 時,minResizeWidth 無效。當 minResizeHeight 的值比 minHeight 大時,minResizeHeight 無效;當 resizeMode 的取值不包括 vertical 時,minResizeHeight 無效。
- updatePeriodMillis
它定義了 widget 的更新頻率。實際的更新時機不一定是精確的按照這個時間發生的。建議更新盡量不要太頻繁,最好是低於1小時一次。 或者可以在配置 Activity 里面供用戶對更新頻率進行配置。 實際上,當updatePeriodMillis的值小於30分鍾時,系統會自動將更新頻率設為30分鍾!關於這部分,后面會詳細介紹。
注意: 當更新時機到達時,如果設備正在休眠,那么設備將會被喚醒以執行更新。如果更新頻率不超過1小時一次,那么對電池壽命應該不會造成多大的影響。 如果你需要比較頻繁的更新,或者你不希望在設備休眠的時候執行更新,那么可以使用基於 alarm 的更新來替代 widget 自身的刷新機制。將 alarm 類型設置為 ELAPSED_REALTIME 或 RTC,將不會喚醒休眠的設備,同時請將 updatePeriodMillis 設為 0。
- initialLayout
指向 widget 的布局資源文件
- configure
可選屬性,定義了 widget 的配置 Activity。如果定義了該項,那么當 widget 創建時,會自動啟動該 Activity。
- previewImage
指定預覽圖,該預覽圖在用戶選擇 widget 時出現,如果沒有提供,則會顯示應用的圖標。該字段對應在 AndroidManifest.xml 中 receiver 的 android:previewImage 字段。由 Android 3.0 引入。
- autoAdvanceViewId
指定一個子view ID,表明該子 view 會自動更新。在 Android 3.0 中引入。
- resizeMode
指定了 widget 的調整尺寸的規則。可取的值有: "horizontal", "vertical", "none"。"horizontal"意味着widget可以水平拉伸,“vertical”意味着widget可以豎值拉伸,“none”意味着 widget不能拉伸;默認值是"none"。Android 3.1 引入。
- widgetCategory
指定了 widget 能顯示的地方:能否顯示在 home Screen 或 lock screen 或 兩者都可以。它的取值包括:"home_screen" 和 "keyguard"。Android 4.2 引入。
- initialKeyguardLayout
指向 widget 位於 lockscreen 中的布局資源文件。Android 4.2 引入。
AppWidgetProvider類:
通過appwidget-provider標簽就可以得到初始化的布局,視圖等,但widget要實時更新時,要響應用戶操作時,就需要額外的類來輔助處理了,這個類就是AppWidgetProvider。由於AppWidgetProvider要接收到當前widget的狀態(是否被添加,是否被刪除等),所以要接收通知,必然是派生自BroadcastReceiver。
AppWidgetProvider中的廣播處理函數如下:(根據不同的使用情況,重寫不同的函數)
- onUpdate():
在3種情況下會調用OnUpdate()。onUpdate()是在main線程中進行,因此如果處理需要花費時間多於10秒,處理應在service中完成。(第二篇會講為什么還要有service)
- 在時間間隔到時調用,時間間隔在widget定義的android:updatePeriodMillis中設置;
- 用戶拖拽到主頁,widget實例生成。無論有沒有設置Configure activity,我們在Android4.4的測試中,當用戶拖拽圖片至主頁時,widget實例生成,會觸發onUpdate(),然后再顯示 activity(如果有)。這點和資料說的不一樣,資料認為如果設置了Configure acitivity,就不會在一開始調用onUpdate(),而實驗顯示當實例生成(包括創建和重啟時恢復),都會先調用onUpate()。在本例, 由於此時在preference尚未有相關數據,創建實例時不能有效進行數據設置。
- 機器重啟,實例在主頁上顯示,會再次調用onUpdate()
- onDeleted(Context, int[]):
當 widget 被刪除時被觸發。
- onEnabled(Context):
當第1個 widget 的實例被創建時觸發。也就是說,如果用戶對同一個 widget 增加了兩次(兩個實例),那么onEnabled()只會在第一次增加widget時觸發。
- onDisabled(Context):
當最后1個 widget 的實例被刪除時觸發。
- onReceive(Context, Intent):
在接收到廣播時,調用。
(3)Widget布局
在 AppWidgetProviderInfo中已經介紹了,minWidth 和minHeight 用來指定了App Widget布局需要的最小區域。缺省的App Widgets所在窗口的桌面位置基於有確定高度和寬度的單元網格中。如果App Widget的最小長度或寬度和這些網格單元的尺寸不匹配,那么這個App Widget將上舍入(上舍入即取比該值大的最接近的整數——譯者注)到最接近的單元尺寸。
例如,很多手機提供4x4網格,平板電腦能提供8x7網格。當widget被添加到時,在滿足minWidth和minHeight約束的前提下,它將被占領的最小數目的細胞。
粗略計算minWidth和minHeight,可以參考下面表格:
| 單元格個數 (行 / 列) |
對應的設置大小 (dp) ( minWidth / minHeight) |
|---|---|
| 1 | 40dp |
| 2 | 110dp |
| 3 | 180dp |
| 4 | 250dp |
| … | … |
| n | 70 × n − 30 |
詳細計算minWidth和minHeight,要計算各個區域的大小。以下圖為例:

計算結果:
minWidth = 144dp + (2 × 8dp) + (2 × 56dp) = 272dp
minHeight = 48dp + (2 × 4dp) = 56dp
(4)Widget支持的布局和控件
Widget並不支持所有的布局和控件,而僅僅只是支持Android布局和控件的一個子集。
- App Widget支持的布局
FrameLayout
LinearLayout
RelativeLayout
GridLayout
-
App Widget支持的控件
AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView
ViewFlipper
ListView
GridView
StackView
AdapterViewFlipper
除此之外的所有控件(包括自定義控件)都無法顯示,無法顯示時,添加出來的widget會顯示“加載布局出錯”
4.WebView
5.參考引用
Widget文檔參考:
http://blog.csdn.net/harvic880925/article/details/41445407
http://blog.csdn.net/sasoritattoo/article/details/17616597
Service文檔參考:
http://www.cnblogs.com/yejiurui/p/3429451.html
