編輯:關於Android編程
剛開始使用Service的時候,常常會有一個誤區:認為這個Service運行於應用中一個單獨的線程。其實Service組件和其他組件一樣,都是運行於這個應用的主線程當中的,它們都運行於同一個單一的線程。
可以把Service簡單的理解成一個沒有界面顯示的Activity(這個比喻其實並不准確,因為Service可以直接調用WindowManager實現界面展示,不過這裡暫時就這樣理解吧)。
如果需要Service進行一個需要持續的、耗時的任務,還是需要給它開啟一個工作線程。
既然Service進行耗時工作也要開啟的單獨的線程,那麼為什麼不讓Activity代替Service的工作呢?例如從網絡下載一個文件,可以讓應用對應的Activity開啟一個下載線程單獨進行下載工作。即使用戶在下載的時候想使用其他應用也沒有關系,點擊HOME按鈕就可以了。下載文件的那個Activity會自動隱藏起來,根本不會影響到其他應用的使用。
這看上去也是可以的,不過千萬不能忽略了安卓系統的回收機制。假如系統資源需要回收,操作系統有可能把隱藏起來的Activity給回收了,所以將一個需要長期運行的任務與隨時可能被清除的Activity關聯在一起是很危險的。所以安卓系統引入了Service組件來處理這種情況。Service組件的重要性在系統當中僅次於“正在與用戶交互的Actvity”,是最不可能被系統自動回收的組件。以此來保證長期運行的任務能夠始終運行著。
很多時候,啟動一個Service就是要它完成一個復雜而耗時的任務,完成之後,這個Service就可以退出了。
例如文件下載。Activity界面啟動負責下載的Service,Service安靜的下載,下載完成了,就可以自己退出。下載的過程中,Activity可以繼續顯示下載的進度,也可以不用關心當前的狀態而完全退出。
Android SDK為開發者准備好了這樣一個現成的Service-IntentService。
IntentService是Service的子類,就是為了上面的那種使用場景而設計的。Android SDK對Service類進行了進一步的封裝和擴展,方便開發者直接使用,而不需要重新造輪子了。
使用IntentService,
繼承IntentService,實現它的onHandlerIntent()函數。onHandlerIntent()是在工作線程中被調用的,所以可以在它當中添加耗時的任務處理,
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//添加耗時的任務處理
//如果intent攜帶參數,可以從intent中獲取參數
......
}
}
在AndroidManifest.xml文件中,聲明這個Service;
使用它的時候,直接啟動Service就可以了。
Intent intent=new Intent(this,MyIntentService.class);
//如果需要傳遞參數,可以將參數放到intent當中
startService(intent);
使用IntentService有幾個需要注意的地方,
Intent發布,如果需要使用參數,參數可以通過Intent傳遞; 一旦任務執行完成,Service就退出了; 可以處理多個Intent請求,但是會按照請求的先來後到挨個處理,一個接一個完成後,如果沒有任務了,Service就退出;
和所有別的應用組件一樣,Service需要在AndroidManifest.xml文件中聲明。
在應用的AndroidManifest.xml文件中,要給Service設置上android:exported屬性,
android:exported屬性設置成true:可被其他應用使用; android:exported屬性設置成false:只能被自己所在的應用使用;
在對其他應用開放Service的時候,也可以設置上訪問權限,只對部分應用開放使用的權限。
在AndroidManifest.xml文件中,對要設置權限的Service設置上android:permission屬性,該屬性值可以任意指定一個字符串。通常使用程序的包名作為其中的一部分,這樣可以避免和其他應用中的權限聲明沖突。例如"com.anddle.serviceaccess,
在AndroidManifest.xml文件中,與同級的位置,對外聲明前面使用的標簽,表示這個應用發布了一個叫做com.anddle.serviceaccess的權限,
其中android:name屬性的值,就是標簽中設置的android:permission的值。
假如應用B要使用應用A中帶權限的Service,需要在應用B的AndroidManifest.xml中加入權限的使用,
其中,標簽中設置的android:name的值,就是應用A中對外聲明的那個service的權限值。
用ADB工具啟動已知Service,
$ ./adb shell am startservice -n 包名/包名.activity名稱
這裡的包名就形如:com.android.xxx,例如
$ ./adb shell am start -n com.android.xxx/com.android.xxx.MyService
安卓系統當中也自帶了不少的Service,比如WindowManager BluetoothManager等等等等。
要使用它們也很簡單,比如,
//獲取WindowManager
WindowManager windowmanager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
windowmanager.xxx();
//獲取BluetoothManager
BluetoothManager bluetoothmanager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothmanager.xxx();
獲取到這些Service對外提供的接口以後,就可以使用這些接口了。
類似的Service還有很多很多,
深入淺析Android Fragment(下篇)
在上篇文章給大家介紹深入淺析Android Fragment(上篇),包括一些基本的用法和各種API,如果還想深入學習請繼續關注本篇文章。本篇將介紹上篇提到的:如何管理F
Android 動畫總結-屬性動畫
特點:改變的是對象的實際屬性 不僅可以應用於View, 有getter和setter方法的都可以在xml中定義放在res\animator中如:animator_alph
Android 自定義View 實現刮刮卡效果
主要思想:將一個view設計成多層:背景層,含中獎信息等;遮蓋層,用於刮獎,使用關聯一個Bitmap的Canvas在該Bitmap上,使用它的canvas.drawPat
Android自定義日歷Calender代碼實現
產品要做簽到功能,簽到功能要基於一個日歷來進行,所以就根據 要求自定義了一個日歷自定義控件相信做android都知道:(1)首先創建一個類,繼承一個容器類或者是一個控件&