Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android四大組件之Service

Android四大組件之Service

編輯:關於Android編程

Service基本用法

新建一個MyService繼承自Service,並重寫父類的onCreate()、onStartCommand()和onDestroy()方法,如下所示:

public class MyService extends Service {  
   
    public static final String TAG = "MyService";  
   
    @Override  
    public void onCreate() {  
         super.onCreate();  
        Log.d(TAG, "onCreate() executed");  
     }  
   
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
         Log.d(TAG, "onStartCommand() executed");  
         return super.onStartCommand(intent, flags, startId);  
    }  
       
     @Override  
     public void onDestroy() {  
        super.onDestroy();  
        Log.d(TAG, "onDestroy() executed");  
     }  
   
     @Override  
     public IBinder onBind(Intent intent) {  
         return null;  
    }  
} 

然後打開或新建MainActivity作為程序的主Activity,在裡面加入啟動Service和停止Service的邏輯,代碼如下所示:

public class MainActivity extends Activity implements OnClickListener {  
  
    private Button startService;  
  
    private Button stopService;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        startService = (Button) findViewById(R.id.start_service);  
        stopService = (Button) findViewById(R.id.stop_service);  
        startService.setOnClickListener(this);  
        stopService.setOnClickListener(this);  
    }  
  
    @Override  
    public void onClick(View v) {  
        switch (v.getId()) {  
        case R.id.start_service:  
            Intent startIntent = new Intent(this, MyService.class);  
            startService(startIntent);  
            break;  
        case R.id.stop_service:  
            Intent stopIntent = new Intent(this, MyService.class);  
            stopService(stopIntent);  
            break;  
        default:  
            break;  
        }  
    }  
  
}  

可以看到,在Start Service按鈕的點擊事件裡,我們構建出了一個Intent對象,並調用startService()方法來啟動MyService。然後在Stop Serivce按鈕的點擊事件裡,我們同樣構建出了一個Intent對象,並調用stopService()方法來停止MyService。

onCreate()方法只會在Service第一次被創建的時候調用,如果當前Service已經被創建過了,不管怎樣調用startService()方法,onCreate()方法都不會再執行。因此你可以再多點擊幾次Start Service按鈕試一次,每次都只會有onStartCommand()方法執行。

另外需要注意,項目中的每一個Service都必須在AndroidManifest.xml中注冊才行,所以還需要編輯AndroidManifest.xml文件,代碼如下所示:

  
          
    ……  
  
          
        

Service和Activity通信

上面的MyService中的代碼,你會發現一直有一個onBind()方法我們都沒有使用到,這個方法其實就是用於和Activity建立關聯的。

public class MyService extends Service {  
  
    public static final String TAG = "MyService";  
  
    private MyBinder mBinder = new MyBinder();  
  
    @Override  
    public void onCreate() {  
        super.onCreate();  
        Log.d(TAG, "onCreate() executed");  
    }  
  
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        Log.d(TAG, "onStartCommand() executed");  
        return super.onStartCommand(intent, flags, startId);  
    }  
  
    @Override  
    public void onDestroy() {  
        super.onDestroy();  
        Log.d(TAG, "onDestroy() executed");  
    }  
  
    @Override  
    public IBinder onBind(Intent intent) {  
        return mBinder;  
    }  
  
    class MyBinder extends Binder {  
  
        public void startDownload() {  
            Log.d("TAG", "startDownload() executed");  
            // 執行具體的下載任務  
        }  
  
    }  
  
}  
public class MainActivity extends Activity implements OnClickListener {  
  
    private Button startService;  
  
    private Button stopService;  
  
    private Button bindService;  
  
    private Button unbindService;  
  
    private MyService.MyBinder myBinder;  
  
    private ServiceConnection connection = new ServiceConnection() {  
  
        @Override  
        public void onServiceDisconnected(ComponentName name) {  
        }  
  
        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) {  
            myBinder = (MyService.MyBinder) service;  
            myBinder.startDownload();  
        }  
    };  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        startService = (Button) findViewById(R.id.start_service);  
        stopService = (Button) findViewById(R.id.stop_service);  
        bindService = (Button) findViewById(R.id.bind_service);  
        unbindService = (Button) findViewById(R.id.unbind_service);  
        startService.setOnClickListener(this);  
        stopService.setOnClickListener(this);  
        bindService.setOnClickListener(this);  
        unbindService.setOnClickListener(this);  
    }  
  
    @Override  
    public void onClick(View v) {  
        switch (v.getId()) {  
        case R.id.start_service:  
            Intent startIntent = new Intent(this, MyService.class);  
            startService(startIntent);  
            break;  
        case R.id.stop_service:  
            Intent stopIntent = new Intent(this, MyService.class);  
            stopService(stopIntent);  
            break;  
        case R.id.bind_service:  
            Intent bindIntent = new Intent(this, MyService.class);  
            bindService(bindIntent, connection, BIND_AUTO_CREATE);  
            break;  
        case R.id.unbind_service:  
            unbindService(connection);  
            break;  
        default:  
            break;  
        }  
    }  
  
}  

可以看到,這裡我們首先創建了一個ServiceConnection的匿名類,在裡面重寫了onServiceConnected()方法和onServiceDisconnected()方法,這兩個方法分別會在Activity與Service建立關聯和解除關聯的時候調用。在onServiceConnected()方法中,我們又通過向下轉型得到了MyBinder的實例,有了這個實例,Activity和Service之間的關系就變得非常緊密了。現在我們可以在Activity中根據具體的場景來調用MyBinder中的任何public方法,即實現了Activity指揮Service干什麼Service就去干什麼的功能。

當然,現在Activity和Service其實還沒關聯起來了呢,這個功能是在Bind Service按鈕的點擊事件裡完成的。可以看到,這裡我們仍然是構建出了一個Intent對象,然後調用bindService()方法將Activity和Service進行綁定。bindService()方法接收三個參數,第一個參數就是剛剛構建出的Intent對象第二個參數是前面創建出的ServiceConnection的實例第三個參數是一個標志位,這裡傳入BIND_AUTO_CREATE表示在Activity和Service建立關聯後自動創建Service,這會使得MyService中的onCreate()方法得到執行,但onStartCommand()方法不會執行。

然後如何我們想解除Activity和Service之間的關聯怎麼辦呢?調用一下unbindService()方法就可以了,這也是Unbind Service按鈕的點擊事件裡實現的邏輯。

如何銷毀Service

點擊Start Service按鈕啟動Service,再點擊Stop Service按鈕停止Service,這樣MyService就被銷毀了.

點擊的Bind Service按鈕呢?由於在綁定Service的時候指定的標志位是BIND_AUTO_CREATE,說明點擊Bind Service按鈕的時候Service也會被創建,這時應該怎麼銷毀Service呢?其實也很簡單,點擊一下Unbind Service按鈕,將Activity和Service的關聯解除就可以了。

如果我們既點擊了Start Service按鈕,又點擊了Bind Service按鈕會怎麼樣呢?這個時候你會發現,不管你是單獨點擊Stop Service按鈕還是Unbind Service按鈕,Service都不會被銷毀,必要將兩個按鈕都點擊一下,Service才會被銷毀。也就是說,點擊Stop Service按鈕只會讓Service停止,點擊Unbind Service按鈕只會讓Service和Activity解除關聯,一個Service必須要在既沒有和任何Activity關聯又處理停止狀態的時候才會被銷毀。

服務的分類:

\

 

解釋:

①AIDL(Android Interface Definition Language)是Android接口定義語言的意思,它可以用於讓某個Service與多個應用程序組件之間進行跨進程通信,從而可以實現多個應用程序共享同一個Service的功能。

②為什麼將MyServiSce轉換成遠程Service後就不會導致程序ANR了呢?這是由於,使用了遠程Service後,MyService已經在另外一個進程當中運行了,所以只會阻塞該進程中的主線程,並不會影響到當前的應用程序。

③那麼如何才能讓Activity與一個遠程Service建立關聯呢?這就要使用AIDL來進行跨進程通信了(IPC)。

具體AIDL跨進程通信見《Android 進程間通信》

\

 

Service 和 IntentService的區別:

 

參考:http://blog.csdn.net/p106786860/article/details/17885115

IntentService的使用

IntentService是Service的子類,比普通的Service增加了額外的功能。IntentService是繼承Service的,那麼它包含了Service的全部特性,當然也包含service的生命周期和啟動方式,IntentService集開啟線程和自動停止於一身,IntentService還是博得了不少程序員的喜愛。

IntentService用法:

這裡首先是要提供一個無參的構造函數,並且必須在其內部調用父類的有參構造函數。然後要在子類中去實現 onHandleIntent()這個抽象方法,在這個方法中可以去處理一些具體的 邏輯,而且不用擔心 ANR(Application Not Responding)的問題,因為這個方法已經是在子線程中運行的了。這裡為了證 實一下,我們在 onHandleIntent()方法中打印了當前線程的 id。另外根據 IntentService的特性, 這個服務在運行結束後應該是會自動停止的,所以我們又重寫了 onDestroy()方法,在這裡也打印了一行日志,以證實服務是不是停止掉了。

\

 

Service和線程的關系:

Service是運行在主線程裡的,也就是說如果你在Service裡編寫了非常耗時的代碼,程序必定會出現ANR的。

你可能會驚呼,這不是坑爹麼!?那我要Service又有何用呢?其實大家不要把後台和子線程聯系在一起就行了,這是兩個完全不同的概念。Android的後台就是指,它的運行是完全不依賴UI的。即使Activity被銷毀,或者程序被關閉,只要進程還在,Service就可以繼續運行。比如說一些應用程序,始終需要與服務器之間始終保持著心跳連接,就可以使用Service來實現。你可能又會問,前面不是剛剛驗證過Service是運行在主線程裡的麼?在這裡一直執行著心跳連接,難道就不會阻塞主線程的運行嗎?當然會,但是我們可以在Service中再創建一個子線程,然後在這裡去處理耗時邏輯就沒問題了。

既然在Service裡也要創建一個子線程,那為什麼不直接在Activity裡創建呢?這是因為Activity很難對Thread進行控制,當Activity被銷毀之後,就沒有任何其它的辦法可以再重新獲取到之前創建的子線程的實例。而且在一個Activity中創建的子線程,另一個Activity無法對其進行操作。但是Service就不同了,所有的Activity都可以與Service進行關聯,然後可以很方便地操作其中的方法,即使Activity被銷毀了,之後只要重新與Service建立關聯,就又能夠獲取到原有的Service中Binder的實例。因此,使用Service來處理後台任務,Activity就可以放心地finish,完全不需要擔心無法對後台任務進行控制的情況。

生命周期

\

 

一旦在項目的任何位置調用了 Context的 startService()方法,相應的服務就會啟動起來,並回調 onStartCommand()方法。如果這個服務之前還沒有創建過,onCreate()方法會先於onStartCommand()方法執行。服務啟動了之後會一直保持運行狀態,直到 stopService()或stopSelf()方法被調用。注意雖然每調用一次startService()方法,onStartCommand()就會執行一次,但實際上每個服務都只會存在一個實例。所以不管你調用了多少次 startService()方法, 只需調用一次 stopService()或 stopSelf()方法,服務就會停止下來了。

另外,還可以調用 Context的bindService()來獲取一個服務的持久連接,這時就會回調服務中的 onBind()方法。類似地,如果這個服務之前還沒有創建過,onCreate()方法會先於 onBind()方法執行。之後,調用方可以獲取到 onBind()方法裡返回的 IBinde對象的實例,這樣就能自由地和服務進行通信了。只要調用方和服務之間的連接沒有斷開,服務就會一直保持運行狀態。 當調用了 startService()方法後,又去調用 stopService()方法,這時服務中的 onDestroy() 方法就會執行,表示服務已經銷毀了。類似地,當調用了 bindService()方法後,又去調用 unbindService()方法,onDestroy()方法也會執行,這兩種情況都很好理解。

但是需要注意,我們是完全有可能對一個服務既調用了 startService()方法,又調用了 bindService()方法的, 這種情況下該如何才能讓服務銷毀掉呢?根據 Android系統的機制,一個服務只要被啟動或者被綁定了之後,就會一直處於運行狀態,必須要讓以上兩種條件同時不滿足,服務才能被銷毀。所以,這種情況下要同時調用 stopService()和 unbindService()方法,onDestroy()方法才會執行。

\

 

系統Service

 

1. 概要:

Android系統服務提供系統最基本的,最核心的功能,如設備控制,位置信息,通知等。這些服務有的在Framework層,有的在Libraries層。

2. 分類:

正如前面的應用服務一樣,根據實現方式 ,我們可以把系統服務分為java系統服務本地系統服務。存在於Framework層的,我們稱之為java系統服務,這些服務都處於框架層,是用java語言編寫的;存在於Libraries層的,我們稱之為本地系統服務,這些服務都處於更低的Libraries層,是用C++語言編寫的,運行在各自獨立的進程中。

例如:

(1)在Android Framework框架層服務有:

Activity Manager, Content Providers, NotificationManager, PackageManager, TelephonyManager, Location Manager..., 這些組件都是以單例模式在SystemServer進程中進行初始化的。

1.EntropyService

熵服務,周期性的加載和保存隨機信息。主要是linux開機後,/dev/random的狀態可能是可預知的,這樣一些需要隨機信息的應用程序就可能會有問題。這個無需提供應用程序接口。

2.PowerManagerService –> PowerManager

Android的電源管理也是很重要的一部分。比如在待機的時候關掉不用的設備,待機時屏幕和鍵盤背光的關閉,用戶操作的時候該打開多少設備等等。

3.ActivityManagerService->ActivityManager

這個是整個Android framework框架中最為核心的一個服務,管理整個框架中任務、進程管理, Intent解析等的核心實現。雖然名為Activity的Manager Service,但它管轄的范圍,不只是Activity,還有其他三大組件,和它們所在的進程。也就是說用戶應用程序的生命管理,都是由他負責的。

4.TelephonyRegistry->TelephonyManager

電話注冊、管理服務模塊,可以獲取電話的鏈接狀態、信號強度等等。<可以刪掉,但要看的大概明白>

5.PackageManagerService -> PackageManager

包括對軟件包的解包,驗證,安裝以及升級等等,對於我們現在不能安裝.so文件的問題,應該先從這塊著手分析原因。

6.AccountManagerService -> AccountManager

A system service that providesaccount, password, and authtoken management for all

accounts on the device。

7.ContentService -> ContentResolver

內容服務,主要是數據庫等提供解決方法的服務。

8.BatteryService

監控電池充電及狀態的服務,當狀態改變時,會廣播Intent

9.HardwareService

一般是ring和vibrate的服務程序

10.SensorService -> SensorManager

管理Sensor設備的服務,負責注冊client設備及當client需要使用sensor時激活Sensor

11.WindowManagerService -> WindowManager -> PhoneWindowManager

和ActivityManagerService高度粘合

窗口管理,這裡最核心的就是輸入事件的分發和管理。

12.AlarmManagerService -> AlarmManager

鬧鐘服務程序

13.BluetoothService -> BluetoothDevice

藍牙的後台管理和服務程序

14.StatusBarService -> StatusBarManager

負責statusBar上圖標的更新、動畫等等的服務,服務不大。

15.ClipboardService -> ClipboardManager

和其他系統的clipBoard服務類似,提供復制黏貼功過。

16.InputMethodManagerService -> InputMethodManager

輸入法的管理服務程序,包括何時使能輸入法,切換輸入法等等。

17.NetStatService

手機網絡服務

18.ConnectivityService -> ConnectivityManager

網絡連接狀態服務,可供其他應用查詢,當網絡狀態變化時,也可廣播改變。

19.AccessibilityManagerService-> AccessibilityManager

這塊可能要仔細看一下,主要是一些View獲得點擊、焦點、文字改變等事件的分發管理,對整個系統的調試、問題定位等,也需要最這個服務仔細過目一下。

20.NotificationManagerService -> NotificationManager

負責管理和通知後台事件的發生等,這個和statusbar膠黏在一起,一般會在statusbar上添加響應圖標。用戶可以通過這知道系統後台發生了什麼事情。

21.MountService

磁盤加載服務程序,一般要和一個linux daemon程序如vold/mountd等合作起作用,主要負責監聽並廣播device的mount/unmount/bad removal等等事件。

22.DeviceStorageMonitorService

監控磁盤空間的服務,當磁盤空間不足10%的時候會給用戶警告

23.LocationManagerService -> LocationManager

要加入GPS服務等,這部分要細看,現在應用中的navigation沒響應,可以從此處著手看一下

24.SearchManagerService -> SearchManager

The search manager service handles the search UI, and maintains a registry of searchable activities.

25.Checkin Service(FallbackCheckinService)

貌似checkin service是google提供的包,沒有源代碼,源碼只有fallbackCheckinService

26.WallpaperManagerService -> WallpaperManager
管理桌面背景的服務,深度定制化桌面系統,需要看懂並擴展<同時要兼容>這部分

27.AudioService -> AudioManager

AudioFlinger的上層管理封裝,主要是音量、音效、聲道及鈴聲等的管理

28.HeadsetObserver

耳機插拔事件的監控小循環

29.DockObserver

如果系統有個座子,當手機裝上或拔出這個座子的話,就得靠他來管理了

30.BackupManagerService -> BackupManager

備份服務

31.AppWidgetService -> AppWidgetManager

Android可以讓用戶寫的程序以widget的方式放在桌面上,這就是這套管理和服務的接口

32.StatusBarPolicy

管理哪個圖標該在status bar上顯示的策略。

(2)在Libraries層的系統服務有:
SurfaceFlinger

這是framebuffer合成的服務,將各個應用程序及應用程序中的邏輯窗口圖像數據(surface)合成到一個物理窗口中顯示(framebuffer)的服務程序

mediaServer服務進程:

MediaServer服務基本上都是native的services,mediaServer進程也是在init.rc中啟動的,它不是一個daemon進程,這點容易搞混。他也是和systemserver進程類似的系統服務進程,提供應用進程的RPC調用的真正服務代碼所運行的位置。其服務都是和媒體錄播放有關,主要有三個服務:

AudioFlinger

聲音的錄播放服務,包括混音等

MediaPlayerService

提供媒體播放服務,opencore是這塊的核心模塊,對java端的接口在mediaplayer.java

CameraService

提供camera的錄制、preview等功能的服務

AudioPolicyService

主要功能有檢查輸入輸出設備的連接狀態及系統的音頻策略的切換等。

3.系統服務的使用:

相信大家對getSystemService()並不陌生,無論是java系統服務,還是本地系統服務,直接調用getSystemService()就能獲取指定的服務,這一點與應用服務(前面幾節已經講過)不同(應用服務是通過startService()來啟動的。)。之所以能直接使用getSystemService(),是因為在Android初始化過程中,已經在init進程中啟動了這些服務。

SensorManager SM = (SensorManager)getSystemService(context.SENSOR_SERVICE);

4.系統服務的實現:

無論是java系統服務,還是本地系統服務,要實現它,就要按照Android平台的要求,實現相應的函數和接口,這需要在源碼的基本上進行修改。

如何保證Service不被殺死

1.onDestroy方法裡重啟service

service +broadcast 方式,就是當service走ondestory的時候,發送一個自定義的廣播,當收到廣播的時候,重新啟動service;

 

 

 

//這個就是自定義的action

 

 

在onDestroy時:

@Override

publicvoidonDestroy(){

stopForeground(true);

Intentintent=newIntent("com.dbjtech.waiqin.destroy");

sendBroadcast(intent);

super.onDestroy();

}

在BootReceiver裡

 

public class BootReceiver extends BroadcastReceiver {  
   
     @Override  
     public void onReceive(Context context, Intent intent) {  
         if (intent.getAction().equals("com.dbjtech.waiqin.destroy")) {  
            //TODO  
            //在這裡寫重新啟動service的相關操作  
            startUploadService(context);  
        }  
   }  
 }

 

也可以直接在onDestroy()裡startService

@Override  
public void onDestroy() {  
     Intent sevice = new Intent(this, MainService.class);  
     this.startService(sevice);  
     super.onDestroy();  
}  

【結論】當使用類似口口管家等第三方應用或是在setting裡-應用-強制停止時,APP進程可能就直接被干掉了,onDestroy方法都進不來,所以還是無法保證~.~

2.監聽系統廣播判斷Service狀態

通過系統的一些廣播,比如:手機重啟、界面喚醒、應用狀態改變等等監聽並捕獲到,然後判斷我們的Service是否還存活,別忘記加權限啊。

  
      
          
          
          
          
      
  

BroadcastReceiver中:

@Override  
public void onReceive(Context context, Intent intent) {  
    if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {  
        System.out.println("手機開機了....");  
        startUploadService(context);  
    }  
    if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {  
        startUploadService(context);  
    }  
} 

【結論】這也能算是一種措施,不過感覺監聽多了會導致Service很混亂,帶來諸多不便

3.AlarmManager 定時廣播重新開啟服務

這點不具體展開,具體見第一行代碼,天氣應用實例

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved