Android之Service

我叫阿狸貓發表於2014-02-11
Service
       1.什麼是Service
              Service也是Android四大元件之一, 可以在後臺長期執行, 沒有介面.
       2.定義Service
              定義類繼承Service, 在清單檔案中宣告<service>節點. 如果需要使用隱式意圖啟動, 可以配置<intent-filter>和<action>
       3.啟動停止Service
              呼叫startService()方法傳入一個Intent物件可以啟動Service, 呼叫onCreate()和onStart()方法, onCreate()只有第一次呼叫時執行
              呼叫stopService()方法傳入一個Intent可以停止Service, 呼叫onDestroy()方法
       4.繫結Service
              呼叫bindService()方法繫結一個服務, 這裡會呼叫Service中的onBind()方法
              bindService()方法需要傳入一個ServiceConnection, 當onBind()返回一個IBinder的時候, 會呼叫ServiceConnection類中的onServiceConnected()
              在Service中為了能讓繫結其的客戶端呼叫到service中的業務方法, 所以onBind()返回出去的IBinder就需要能呼叫業務方法
              我們可以自定義一個類繼承Binder, 並且在類中定義一些方法, 呼叫Service中的方法. 這樣onBind()方法返回出去的物件就能呼叫Service中的方法了
              繫結處的onServiceConnected(ComponentName name, IBinder service)方法會得到一個IBinder引數, 這個IBinder是onBind()返回物件的父類, 不能直接呼叫子類方法
              為了解決這個問題, 我們使用了aidl技術
              在Service中定義一個介面, 改為aidl檔案, 這時會在R檔案中生成一個java檔案,自定義的類繼承自動生成的Stub類(最終是繼承Stub,而不是Binder)

              繫結處的onServiceConnected()方法使用Stub.asInterface(service)方法將IBinder轉為介面型別, 即可呼叫業務方法




遠端呼叫Service步驟:

1.將定義的介面檔案字尾名改為aidl,分別放在兩個應用的相同包下

2.在service應用中自定義類繼承Stub,並在類中寫呼叫業務的方法。

3.在客戶端中

 private ServiceConnection conn = new ServiceConnection() {
	public void onServiceDisconnected(ComponentName name) {
	}
	public void onServiceConnected(ComponentName name, IBinder service) {
		System.out.println("繫結成功,得到IBinder");
		InvokeInterface ii = Stub.asInterface(service);//呼叫此方法獲取實現自定義介面的自定義類
		System.out.println("ii---->"+ii);
	}
};



Service

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import com.xxc.service.InvokeInterface.Stub;

public class RemoteService extends Service {
	
	//自定義類繼承Stub,在類中定義需要被遠端呼叫的業務方法
	private class MyBinder extends Stub {
		public String sayHello(String name) {
			return RemoteService.this.sayHello(name);
		}
	}
	
	public String sayHello(String name){
		return "Hello "+name;
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		System.out.println("Remote onCreate");
	}
	
	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		System.out.println("Remote onStart");
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		System.out.println("Remote onBind");
		return new MyBinder();//繫結service的時候返回自定義類
	}
	
	@Override
	public boolean onUnbind(Intent intent) {
		System.out.println("Remote onUnbind");
		return super.onUnbind(intent);
	}

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

Service清單檔案

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxc.remoteservice"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        
        <!-- 註冊Service -->
        <service android:name=".RemoteService">
            <intent-filter>
                <action android:name="com.xxc.service.RemoteService"></action>
            </intent-filter>
        </service>
    </application>
</manifest>


遠端呼叫Service的客戶端

import com.xxc.service.InvokeInterface;
import com.xxc.service.InvokeInterface.Stub;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;

public class MainActivity extends Activity {
	private InvokeInterface ii;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    private ServiceConnection conn = new ServiceConnection() {
		public void onServiceDisconnected(ComponentName name) {
		}
		public void onServiceConnected(ComponentName name, IBinder service) {
			System.out.println("繫結成功,得到IBinder");
			ii = Stub.asInterface(service);
			System.out.println("ii---->"+ii);
		}
	};
    
    public void onClick(View view) throws RemoteException{
    	//遠端呼叫Service
    	Intent intent = new Intent("com.xxc.service.RemoteService"); 
    	switch (view.getId()) {
		case R.id.startBT:
			startService(intent);//啟動服務
			break;
		case R.id.bindBT:
			bindService(intent, conn, BIND_AUTO_CREATE);//繫結服務  第三個參數列示,如果此時沒啟動服務就先啟動服務
			break;
		case R.id.invokeBT:
			System.out.println("ii在呼叫---->"+ii);
			System.out.println(ii.sayHello("pkq"));//呼叫服務的業務方法
			break;
		case R.id.unbindBT:
			unbindService(conn);//解綁服務
			break;
		case R.id.stopBT:
			stopService(intent);//停止服務
			break;
		}
    }
}


Service和客戶端兩個應用中都要有的aidl檔案(把修飾符全部去掉)

package com.xxc.service;

interface InvokeInterface {
	String sayHello(String name);
}




相關文章