Android開發之Service服務詳解

服務,作爲Android四大組件之一,必然是重點。我們今天就來講解一下有關服務的生命週期、兩種開啓方式以及相關用法。

服務有兩種開啓方式,一種是正常開啓, 一種是以綁定的方式開啓,當然,這兩種方式可以組成混合開啓。


一、服務的正常開啓

正常開啓服務的方法非常簡單,我們先看如何定義一個服務

1、編寫一個類,繼承Service類。

   我們先不管代碼中的binder類。那個後續講解用。
public class TestService extends Service {

	@Override
	public IBinder onBind(Intent arg0) {
		System.out.println("onBind");
		return new Mybinder();
	}

	@Override
	public void onCreate() {
		System.out.println("create");
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		System.out.println("onDestroy");
		super.onDestroy();
	}

	@Override
	@Deprecated
	public void onStart(Intent intent, int startId) {
		System.out.println("start");
		super.onStart(intent, startId);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		System.out.println("onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public boolean onUnbind(Intent intent) {
		System.out.println("onUnbind");
		return super.onUnbind(intent);
	}

	class Mybinder extends Binder implements IService {

		public void method() {

			System.out.println("serviceMethod");
		}

	}

}

2、清單文件中註冊服務

  <service android:name="com.example.servicedemo.TestService" >
        </service>

3、正常開啓服務

intent = new Intent(getBaseContext(), TestService.class);
		startService(intent);

4、正常關閉服務

	stopService(intent);

這裏我們值得注意的是,一般服務的意圖對象會做成全局變量,便於在退出的時候銷燬服務。這是服務正常使用的步驟。正常使用的時候,服務的生命週期是這樣的:
開啓: onCreate-->onStartCommand-->onStart
結束: onDestory
正常情況下,服務只開啓一次,既只執行一次onCreate方法,如果已經開啓服務,再次執行startService方法時候,會跳過onCreate,直接執行onStartCommand方法以及之後的方法。其中onStart方法已經廢棄

二、服務的綁定開啓

      有時候,我們需要調用服務裏的方法,這個時候,我們就需要採取綁定的方式,開啓服務了。關於綁定開啓服務的原理,這個涉及的android的binder機制,這個我們在下一篇專題中在講解。這裏直接跳過。
    採用綁定的方式開啓服務,我們需要準備幾個東西。
   1、實現一個繼承binder的類
   2、activity裏面實現一個實現ServiceConnection接口的類。

1、binder類的實現

    綁定服務,會調用onBind的方法,然後返回一個IBinder的代理。所以我們需要實現一個繼承Binder的類。然後在裏面寫一個方法,就可以調用服務裏的方法了。其中IService是一個接口類,便於後續操作遠程調用服務方法就這樣一起寫了。
 
class Mybinder extends Binder implements IService {

		public void method() {

			System.out.println("serviceMethod");
		}

	}

  在onBind方法裏返回這個binder
	@Override
	public IBinder onBind(Intent arg0) {
		System.out.println("onBind");
		return new Mybinder();
	}

        2、拿到代理binder

因爲Binder實現了IService接口,所以我們拿到的也是一個實現過IService的類。
 
	class Mycon implements ServiceConnection {

		@Override
		public void onServiceConnected(ComponentName arg0, IBinder binder) {
			Iservice = (IService) binder;
		}

		@Override
		public void onServiceDisconnected(ComponentName arg0) {

		}

	}

          3、服務的綁定與調用服務方法和解綁

   
intent = new Intent(getBaseContext(), TestService.class);
		conn = new Mycon();
		bindService(intent, conn, BIND_AUTO_CREATE);
當這樣綁定服務後,服務的生命週期執行是這樣的:onCreate-->onBind,不會執行onStartCommand方法,拿到代理類後,我們可以執行服務裏的方法了。
	findViewById(R.id.test).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				//startService(intent);
				Iservice.method();
			}
		});
        這樣,就調用了服務裏的方法。
         採用綁定的方式開啓服務有一個風險,就是如果採用綁定的方法開啓服務,那麼當你最小化程序的時候,會報錯。程序會提醒你要解綁服務才能這樣。這個時候我們就需要在一些actvity的生命週期裏面解綁服務
 
unbindService(conn);
         執行這行代碼,就可以解綁服務了。執行的生命週期函是:onUnBind-->onDestory


       三、服務的混合開啓

之前,我們說,採用綁定的方式開啓服務,就會造成最小化的時候程序報錯,那麼有什麼辦法解決呢?這個時候,我們就需要採用混合開啓的方法開啓服務了。
所謂的混合開啓,就是在正常開啓服務之後,在採用綁定的方法綁定服務。我們來看代碼
intent = new Intent(getBaseContext(), TestService.class);
		startService(intent);
		conn = new Mycon();
		bindService(intent, conn, BIND_AUTO_CREATE);

這樣就達到了混合開啓服務的效果。他所執行的生命週期的函數爲:onCreate-->onStartCommand-->onStart-->onBind
        那麼退出的時候,我們需要先解綁,在停止服務
				unbindService(conn);
				stopService(intent);
				conn=null;
				intent=null;

這個時候執行的生命週期函數爲:onUnbind-->onDestory



四、調用遠程服務的方法

 有時候,我們需要調用別的應用裏面的服務的方法,這個其實就是android的IPC機制原理的實現。我們今天就先講講實現步驟的方法代碼。
 

1、將接口文件重命名爲.aidl文件

  
package com.example.servicedemo;

interface IService {
	
	 void method();

}

我們將之前的IService接口文件的後綴名改爲.aidl後,需要將裏面的public等修飾字段去掉。
 

  2、在新的應用中,新建一個與之前存放.aidl文件包名一樣的包。

     新建好之後,將.aidl文件複製到包裏

   3、修改之前服務類裏的binder實現方法

      
	class Mybinder extends IService.Stub {

		public void method() {

			System.out.println("serviceDemomethod");
		}

	}
      將之前的接口文件修改之後,我們直接繼承接口文件自動生成的.Stub類即可

     4、定義服務的隱試意圖開啓方式,並採用隱式意圖開啓服務

     因爲不能拿到別的應用裏的服務的類名,所以我們需要採用隱式意圖去開啓服務並綁定。
    
        <service android:name="com.example.servicedemo.TestService" >
            <intent-filter>
                <action android:name="com.example.servicedemo.TestService.action" />
            </intent-filter>
        </service>
在綁定服務之前,需要重寫一下代理接口實現類,這裏不再採用強制轉換了。
       
	class Mycon implements ServiceConnection {

		@Override
		public void onServiceConnected(ComponentName arg0, IBinder binder) {
			Iservice = IService.Stub.asInterface(binder);
		}

		@Override
		public void onServiceDisconnected(ComponentName arg0) {

		}

	}

       然後綁定服務,就可以調用遠程服務的方法了
      
<span style="white-space:pre">		</span>Intent intent = new Intent();
		intent.setAction("com.example.servicedemo.TestService.action");
		bindService(intent, new Mycon(), BIND_AUTO_CREATE);
		findViewById(R.id.test).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				try {
					Iservice.method();
				} catch (RemoteException e) {
					e.printStackTrace();
				}

			}
		});


在服務使用的過程中,需要注意的是,結束服務的時候,一定要記得釋放掉服務裏的所有資源,尤其是服務裏有開啓子線程並無線循環的。
好了,服務的基本使用方法到此講解結束,希望此文能幫助到大家。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章