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

Android四大組件之服務Service的用法

編輯:關於Android編程

一、 進程概念介紹

四大組件都是運行在主線程
Service是在一段不定的時間運行在後台,不和用戶交互應用組件。每個Service必須在manifest中 通過來聲明。可以通過contect.startservice和contect.bindserverice來啟動。
Service和其他的應用組件一樣,運行在進程的主線程中。這就是說如果service需要很多耗時或者阻塞的操作,需要在其子線程中實現。

二、服務的使用

 定義一個新的服務,要用一個類去繼承Service這個類,Service類中有一個抽象方法onBind()。

一般處理定義一個服務去處理一些事情需要重新覆寫三個方法
①onCreate()
②onStartCommand(Intent intent , int flags ,int startId)
③onDestroy()

   onCreate()方法會在服務創建的時候調用
   onStartCommand()方法會在每次服務啟動的時候調用
   onDestroy()方法會在服務銷毀的時候調用

onCreate()和 onStartCommand()方法的區別:
答:oncreate()方法是在服務第一次創建的時候調用,而 onStartCommand()方法則在每次啟動服務的時候都會調用。

注意:每一個服務都需要在AndroidManifest.xml文件中注冊
[圖片]<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMyBpZD0="三啟動服務和停止服務">三、啟動服務和停止服務

定義一個自定義服務類,然後在主函數中通過按鈕點擊事件進行服務的啟動和停止
  通過startService()方法啟動服務

通過stopService()方法停止服務
代碼如下:
[圖片]

注意:startService()和stopService()方法都是定義在Context類中的,所以在活動中可以直接調用這兩個方法,完全是由活動來決定服務何時停止的。如果想讓服務自己停止,則只需要在服務類MyService中的任何一個位置調用stopSelf()方法就可以讓這個服務停下來

Android中的服務 也是在後台運行 可以理解成是在後台運行並且是沒有界面的Activity

五種服務的級別:

(1)Foreground process 前台進程 用戶正在交互 可以理解成相 當於 Activity執行onResume方法
(2)Visible process 可視進程 用戶沒有在交互 但用戶還一直能看得見頁面 相當於Activity執行了onPause方法
(3)Service Process 服務進程 通過startService()開啟了一個服務
(4)Background process 後台進程 當前用戶看不見頁面 相當於Activity執行了onStop方法
(5)Empty process 空進程


service的兩種模式(startService()/bindService()不是完全分離的

● 本地服務 Local Service 用於應用程序內部。
它可以啟動並運行,直至有人停止了它或它自己停止。在這種方式下,它以調用Context.startService()啟動,而以調用Context.stopService()結束。它可以調用Service.stopSelf() 或 Service.stopSelfResult()來自己停止。不論調用了多少次startService()方法,你只需要調用一次stopService()來停止服務。
用於實現應用程序自己的一些耗時任務,比如查詢升級信息,並不占用應用程序比如Activity所屬線程,而是單開線程後台執行,這樣用戶體驗比較好。
● 遠程服務 Remote Service 用於android系統內部的應用程序之間。
它可以通過自己定義並暴露出來的接口進行程序操作。客戶端建立一個到服務對象的連接,並通過那個連接來調用服務。連接以調用Context.bindService()方法建立,以調用 Context.unbindService()關閉。多個客戶端可以綁定至同一個服務。如果服務此時還沒有加載,bindService()會先加載它。

可被其他應用程序復用,比如天氣預報服務,其他應用程序不需要再寫這樣的服務,調用已有的即可。

生命周期

服務不能自己運行,需要通過調用Context.startService()或Context.bindService()方法啟動服務。這兩個方法都可以啟動Service,但是它們的使用場合有所不同。
1. 使用startService()方法啟用服務,調用者與服務之間沒有關連,即使調用者退出了,服務仍然運行。
如果打算采用Context.startService()方法啟動服務,在服務未被創建時,系統會先調用服務的onCreate()方法,接著調用onStart()方法。
如果調用startService()方法前服務已經被創建,多次調用startService()方法並不會導致多次創建服務,但會導致多次調用onStart()方法。
采用startService()方法啟動的服務
只能調用Context.stopService()方法結束服務,服務結束時會調用onDestroy()方法。

2. 使用bindService()方法啟用服務,調用者與服務綁定在了一起,調用者一旦退出,服務也就終止,大有“不求同時生,必須同時死”的特點。
onBind()只有采用Context.bindService()方法啟動服務時才會回調該方法。該方法在調用者與服務綁定時被調用,當調用者與服務已經綁定
多次調用Context.bindService()方法並不會導致該方法被多次調用。
采用Context.bindService()方法啟動服務時只能調用onUnbind()方法解除調用者與服務解除,服務結束時會調用onDestroy()方法。

看看官方給出的比較流程示意圖:
這裡寫圖片描述

官方文檔告訴我們,一個service可以同時start並且bind,在這樣的情況,系統會一直保持service的運行狀態如果service已經start了或者BIND_AUTO_CREATE標志被設置。如果沒有一個條件滿足,那麼系統將會調用onDestory方法來終止service.所有的清理工作(終止線程,反注冊接收器)都在onDestory中完成。

擁有service的進程具有較高的優先級
官方文檔告訴我們,Android系統會盡量保持擁有service的進程運行,只要在該service已經被啟動(start)或者客戶端連接(bindService)到它。當內存不足時,需要保持,擁有service的進程具有較高的優先級。

1. 如果service正在調用onCreate,onStartCommand或者onDestory方法,那麼用於當前service的進程則變為前台進程以避免被killed。

2. 如果當前service已經被啟動(start),擁有它的進程則比那些用戶可見的進程優先級低一些,但是比那些不可見的進程更重要,這就意味著service一般不會被killed.

3. 如果客戶端已經連接到service (bindService),那麼擁有Service的進程則擁有最高的優先級,可以認為service是可見的。

4. 如果service可以使用startForeground(int, Notification)方法來將service設置為前台狀態,那麼系統就認為是對用戶可見的,並不會在內存不足時killed。

如果有其他的應用組件作為Service,Activity等運行在相同的進程中,那麼將會增加該進程的重要性。


二、start方式開啟服務和bindService方式開啟服務的特點

服務是在後台運行 可以理解成是沒有界面的activity
定義四大組件的方式都是一樣的
定義一個類繼承Service
1.特點:
(1)服務通過startservice方式開啟 第一次點擊按鈕開啟服務 會執行服務的onCreate 和 onStart方法
(2)如果第二次開始再點擊按鈕開啟服務 服務只會執行onStrat方法
(3)服務被開啟後 會在設置頁面裡面的 running裡面找得到這個服務
*(4)startservice 方式開啟服務 服務就會在後台長期運行 直到用戶手工停止 或者調用StopService方法 服務才會被銷毀

bindService()理解:

自定義的Service服務類裡面的onBind()方法是在activity中執行了bindService()綁定服務的操作後執行的。
bindService()方法中藥傳入三個參數:
第一個參數是Intent對象;

第二個參數是建立連接的對象,即ServiceConnection的對象,當執行了bindService()後,服務和activity之間的聯系便建立起來了,此時會回調Service中的onBind()方法,該方法返回一個IBinder對象,這個對象我們可以在該類中自定義一個MyBinder類繼承Bind抽象類,在裡面實現服務的方法,當onBind()執行後,活動中的ServiceConnection類的onServiceConnection()方法會執行,在該方法裡有傳過來的一個參數IBinder service,將這個參數拿出來,通過這個對象去調用服務中的方法,相當於中間人;

//服務中自定義的中間人對象類
public  class MyBinder extends Binder{
    public void startDownload(){
xxxxxxxxxx;
    };
}

......

//連接服務的對象
 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();  
        }  
    };  

第三個參數是一個標志位,這裡傳入BIND_AUTO_CREATE表示在Activity和Service建立關聯後自動創建Service,這會使得MyService中的onCreate()方法得到執行,但onStartCommand()方法不會執行。

[圖片]

2.bindService 方式開啟服務的特點

(1)當點擊按鈕第一次開啟服務 會執行服務的onCreate方法 和 onBind()方法
(2) 當第二次點擊按鈕在調用bindservice 服務沒有響應
**(3) 當activity銷毀的時候服務也銷毀 不求同時生但求同時死
(4)通過bind方式開啟服務 服務不能再設置頁面裡面找到 相當於是一個隱形的服務

(5)bindservice不能多次解綁 多次解綁會報錯

3 使用服務注冊特殊的廣播接收者

(1)創建我們要注冊的廣播接收者

  public class ScreenReceiver extends BroadcastReceiver {
    @Override
        public void onReceive(Context context, Intent intent) {
            //獲取廣播事件的類型
        String action = intent.getAction();

            if ("android.intent.action.SCREEN_OFF".equals(action)) {

            System.out.println("說明屏幕鎖屏了");
        }else if("android.intent.action.SCREEN_ON".equals(action)){

                System.out.println("說明屏幕解鎖了");
            }
    }
    }

(2)創建一個服務 用來注冊廣播接收者 代碼如下

 public class ScreenService extends Service {

    private ScreenReceiver receiver;
    @Override
        public IBinder onBind(Intent intent) {
            return null;
    }

        //當服務第一次啟動的時候調用
        @Override
        public void onCreate() {

            //在這個方法裡面注冊廣播接收者
        //[1]獲取ScreenReceiver實例
            receiver = new ScreenReceiver();

            //[2]創建IntentFilter對象
        IntentFilter filter = new IntentFilter();
        //[3]添加注冊的事件
            filter.addAction("android.intent.action.SCREEN_OFF");
            filter.addAction("android.intent.action.SCREEN_ON");
            //[4]通過代碼的方式注冊
        registerReceiver(receiver, filter);

            super.onCreate();
    }

    //當服務銷毀的時候調用
    @Override
    public void onDestroy() {

        //當actvivity銷毀的時候  取消注冊廣播接收者 
        unregisterReceiver(receiver);


        super.onDestroy();
        }
    }`

(3)一定要記得配置service

5 為什麼要引入bindService
目的為了調用服務裡面的方法


創建前台Service
Service幾乎都是在後台運行的,一直以來它都是默默地做著辛苦的工作。但是Service的系統優先級還是比較低的,當系統出現內存不足情況時,就有可能會回收掉正在後台運行的Service。如果你希望Service可以一直保持運行狀態,而不會由於系統內存不足的原因導致被回收,就可以考慮使用前台Service。前台Service和普通Service最大的區別就在於,它會一直有一個正在運行的圖標在系統的狀態欄顯示,下拉狀態欄後可以看到更加詳細的信息,非常類似於通知的效果。當然有時候你也可能不僅僅是為了防止Service被回收才使用前台Service,有些項目由於特殊的需求會要求必須使用前台Service,比如說墨跡天氣,它的Service在後台更新天氣數據的同時,還會在系統狀態欄一直顯示當前天氣的信息


public class MyService extends Service {  

    public static final String TAG = "MyService";  

    private MyBinder mBinder = new MyBinder();  

    @Override  
    public void onCreate() {  
        super.onCreate();  
        Notification notification = new Notification(R.drawable.ic_launcher,  
                "有通知到來", System.currentTimeMillis());  
        Intent notificationIntent = new Intent(this, MainActivity.class);  
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,  
                notificationIntent, 0);  
        notification.setLatestEventInfo(this, "Title", "Message",  
                pendingIntent);  
        startForeground(1, notification);  
        Log.d(TAG, "onCreate() executed");  
    }  

    .........  

} 

這裡只是修改了MyService中onCreate()方法的代碼。可以看到,首先創建了一個Notification對象,然後調用了它的setLatestEventInfo()方法來為通知初始化布局和數據,並在這裡設置了點擊通知後就打開MainActivity。然後調用startForeground()方法就可以讓MyService變成一個前台Service,並會將通知的圖片顯示出來。


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