天天看點

【Android】Android Service 服務

一、 Service簡介

Service是android 系統中的四大元件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的級别差不多,但不能自己運作隻能背景運作,并且可以和其他元件進行互動。service可以在很多場合的應用中使用,比如播放多媒體的時候使用者啟動了其他Activity這個時候程式要在背景繼續播放,比如檢測SD卡上檔案的變化,再或者在背景記錄你地理資訊位置的改變等等,總之服務總是藏在背景的。

Service的啟動有兩種方式:context.startService() 和 context.bindService()

二、 Service啟動流程

context.startService() 啟動流程:

context.startService()  -> onCreate()  -> onStart()  -> Service running  -> context.stopService()  -> onDestroy()  -> Service stop 

如果Service還沒有運作,則android先調用onCreate(),然後調用onStart();

如果Service已經運作,則隻調用onStart(),是以一個Service的onStart方法可能會重複調用多次。 

如果stopService的時候會直接onDestroy,如果是調用者自己直接退出而沒有調用stopService的話,Service會一直在背景運作,該Service的調用者再啟動起來後可以通過stopService關閉Service。

是以調用startService的生命周期為: onCreate  -->  onStart  (可多次調用) -->  onDestroy

context.bindService()啟動流程:

context.bindService()  -> onCreate()  -> onBind()  -> Service running  -> onUnbind()  -> onDestroy()  -> Service stop

onBind()将傳回給用戶端一個IBind接口執行個體,IBind允許用戶端回調服務的方法,比如得到Service的執行個體、運作狀态或其他操作。這個時候把調用者(Context,例如Activity)會和Service綁定在一起,Context退出了,Srevice就會調用onUnbind->onDestroy相應退出。 

是以調用bindService的生命周期為:onCreate --> onBind(隻一次,不可多次綁定) --> onUnbind --> onDestory。

在Service每一次的開啟關閉過程中,隻有onStart可被多次調用(通過多次startService調用),其他onCreate,onBind,onUnbind,onDestory在一個生命周期中隻能被調用一次。

【Android】Android Service 服務
【Android】Android Service 服務

三、 Service生命周期 

Service的生命周期并不像Activity那麼複雜,它隻繼承了onCreate()、onStart()、onDestroy()三個方法

當我們第一次啟動Service時,先後調用了onCreate()、onStart()這兩個方法;當停止Service時,則執行onDestroy()方法。

這裡需要注意的是,如果Service已經啟動了,當我們再次啟動Service時,不會在執行onCreate()方法,而是直接執行onStart()方法。

它可以通過Service.stopSelf()方法或者Service.stopSelfResult()方法來停止自己,隻要調用一次stopService()方法便可以停止服務,無論調用了多少次的啟動服務方法。

四、 Service示例

下面我做了一個簡單的音樂播放的應用,分别使用startService和bindService來啟動本地的服務。

Activity

public class PlayMusicService extends Activity implements OnClickListener {  
  
    private Button playBtn;  
    private Button stopBtn;  
    private Button pauseBtn;  
    private Button exitBtn;  
    private Button closeBtn;  
  
    private Intent intent;  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.music_service);  
  
        playBtn = (Button) findViewById(R.id.play);  
        stopBtn = (Button) findViewById(R.id.stop);  
        pauseBtn = (Button) findViewById(R.id.pause);  
        exitBtn = (Button) findViewById(R.id.exit);  
        closeBtn = (Button) findViewById(R.id.close);  
          
        playBtn.setOnClickListener(this);  
        stopBtn.setOnClickListener(this);  
        pauseBtn.setOnClickListener(this);  
        exitBtn.setOnClickListener(this);  
        closeBtn.setOnClickListener(this);  
  
    }  
  
    @Override  
    public void onClick(View v) {  
        int op = -1;  
        intent = new Intent("com.homer.service.musicService");  
  
        switch (v.getId()) {  
        case R.id.play:                             // play music  
            op = 1;  
            break;  
        case R.id.stop:                             // stop music  
            op = 2;  
            break;  
        case R.id.pause:                            // pause music  
            op = 3;  
            break;  
        case R.id.close:                            // close activity  
            this.finish();  
            break;  
        case R.id.exit:                             // stopService  
            op = 4;  
            stopService(intent);  
            this.finish();  
            break;  
        }  
  
        Bundle bundle = new Bundle();  
        bundle.putInt("op", op);  
        intent.putExtras(bundle);  
          
        startService(intent);                           // startService  
    }  
      
    @Override  
    public void onDestroy(){  
        super.onDestroy();  
  
        if(intent != null){  
            stopService(intent);  
        }  
    }  
}             

Service

public class MusicService extends Service {  
    private static final String TAG = "MyService";  
      
    private MediaPlayer mediaPlayer;  
  
    @Override  
    public IBinder onBind(Intent arg0) {  
        return null;  
    }  
  
    @Override  
    public void onCreate() {  
        Log.v(TAG, "onCreate");  
        Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show();  
  
        if (mediaPlayer == null) {  
            mediaPlayer = MediaPlayer.create(this, R.raw.tmp);  
            mediaPlayer.setLooping(false);  
        }  
    }  
  
    @Override  
    public void onDestroy() {  
        Log.v(TAG, "onDestroy");  
        Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT);  
        if (mediaPlayer != null) {  
            mediaPlayer.stop();  
            mediaPlayer.release();  
        }  
    }  
  
    @Override  
    public void onStart(Intent intent, int startId) {  
        Log.v(TAG, "onStart");  
        if (intent != null) {  
            Bundle bundle = intent.getExtras();  
            if (bundle != null) {  
                int op = bundle.getInt("op");  
                switch (op) {  
                case 1:  
                    play();  
                    break;  
                case 2:  
                    stop();  
                    break;  
                case 3:  
                    pause();  
                    break;  
                }  
            }  
        }  
    }  
  
    public void play() {  
        if (!mediaPlayer.isPlaying()) {  
            mediaPlayer.start();  
        }  
    }  
  
    public void pause() {  
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
            mediaPlayer.pause();  
        }  
    }  
  
    public void stop() {  
        if (mediaPlayer != null) {  
            mediaPlayer.stop();  
            try {  
                mediaPlayer.prepare();  // 在調用stop後如果需要再次通過start進行播放,需要之前調用prepare函數  
            } catch (IOException ex) {  
                ex.printStackTrace();  
            }  
        }  
    }  
}             

AndroidManifest.xml

注冊activity

<activity  
    android:name=".service.PlayMusicService"  
    android:label="@string/app_name" />             

注冊service

<service  
    android:name=".service.MusicService"  
    android:enabled="true" >  
    <intent-filter>  
        <action android:name="com.homer.service.musicService" />  
    </intent-filter>  
</service>             

五、 代碼解析

1、Activity中,PlayMusicService中通過重寫OnClickListener 接口onClick()方法實作對播放音樂的控制,把音樂各種操作用數字通過Intent傳遞給service

然後通過構造一個Intent , intent = new Intent("com.homer.service.musicService"); 

其中,com.homer.service.musicService是 AndroidManifest.xml 對service的定義,即上面“注冊service”

2、Activity中,音樂播放的控制,利用Bundle綁定數字op後,通過 startService(intent); 服務後發送出去

Bundle bundle = new Bundle();

bundle.putInt("op", op);

intent.putExtras(bundle);

startService(intent);

3、 Service中,會處理Activity啟動的 startService(intent);服務,依次調用service的啟動過程:onCreate --> onStart(可多次調用) --> onDestroy

onCreate(),  建立mediaPlayer

onStart(),      通過擷取Bundle bundle = intent.getExtras();,提取int op = bundle.getInt("op");,然後執行響應的音樂播放操作

onDestroy(),停止并釋放mediaPlayer音樂資源,如果當執行context.stopService()時調用此方法

4、Activity中,onClick()函數中close與exit是執行含義是不同的:

close : 隻是執行了this.finish(); 關閉了本Activity窗體,service并沒有被關掉,音樂依然會繼續在背景播放