Android Service學習篇三:Service啓動方式之bindService

客戶端經過調用bindService方法可以綁定服務,而後Android系統會調用服務的onBind回調方法,這個方法會返回一個跟服務端交互的IBinder對象。這個綁定是異步的,bindService方法當即返回,而且不給客戶端返回IBinder對象。要接受IBinder對象,客戶端必須建立一個ServiceConnection類的實例,而且把這個實例傳遞給bindService方法。java

注意:只有Activity、Service和內容提供器(content provider)可以綁定服務,廣播接收器是不能綁定服務的。android

經過綁定服務來實現功能有如下幾個步驟:
app

  1. 實現一個ServiceConnection接口,並重寫裏面的onServiceConnected和onServiceDisconnected兩個方法,其中,前者是在服務已經綁定成功後回調的方法,後者是在服務發生異常終止時調用的方法。異步

  2. 在客戶端,經過bindService方法來異步地綁定一個服務對象,若是綁定成功,則會回調ServiceConnection接口方法中的onServiceConnected方法,並獲得一個IBinder對象。ide

  3. 服務端經過建立一個*.aidl文件來定義一個能夠被客戶端調用的業務接口,同時,服務端還須要提供一個業務接口的實現類,並實現*.aidl中定義的全部方法,一般讓這個實現類去繼承Stub類。this

    注意:建立aidl文件時有幾個注意點:spa

    (1)定義的方法前面不能有修飾符,相似於接口的寫法。code

    (2)支持的類型有:8大基本數據類型,CharSequence,String,List<String>,Map,以及自定義類型。orm

    自定義類型須要作到如下幾點:xml

    1. 實現Parcelable接口。

    2. 定義一個aidl文件來聲明該類型。

    3. 若是要在其餘的aidl文件中使用,則必需要使用import來引用。

  4. 經過Service組件來暴露業務接口。

  5. 經過Service的onBind方法來返回被綁定的業務對象。

  6. 客戶端若是綁定成功,就能夠像調用本身的方法同樣去調用遠程的業務對象方法。

爲了便於理解,能夠看一看下面的這個項目,項目名爲ServiceINS。

先來看看項目的構成:

MainActivity:

package com.example.serviceins;

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

public class MainActivity extends Activity {
	private ICat cat;
	private boolean isBound = false;// 用於判斷是否綁定

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	// 綁定服務的鏈接回調接口
	private ServiceConnection conn = new ServiceConnection() {

		// 已經綁定完成時調用
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// 綁定成功後回調的方法
			cat = ICat.Stub.asInterface(service);
			isBound = true;
			Toast.makeText(MainActivity.this, "綁定成功", Toast.LENGTH_SHORT)
					.show();
		}

		// 服務發生異常終止時調用的方法
		@Override
		public void onServiceDisconnected(ComponentName name) {
			isBound = false;
		}
	};

	// 綁定服務
	public void boundClick(View view) {
		Intent intent = new Intent(this, MyBoundService.class);
		// 這個綁定的步驟是異步的,綁定成功後會回調onServiceConnected方法
		bindService(intent, conn, Context.BIND_AUTO_CREATE);
	}

	// 解除綁定
	public void unBoundClick(View view) {
		if (isBound) {
			unbindService(conn);
			Toast.makeText(MainActivity.this, "解除綁定成功", Toast.LENGTH_SHORT)
					.show();
		}
	}

	// 經過IPC調用業務方法
	public void callClick(View view) {
		if (cat == null) {
			return;
		}
		try {
			cat.setName("黑貓警長");
			Toast.makeText(this,
					cat.desc() + "\n" + cat.getPerson().toString(),
					Toast.LENGTH_LONG).show();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="boundClick"
        android:text="綁定一個服務" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="unBoundClick"
        android:text="解除綁定服務" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="callClick"
        android:text="經過IPC調用業務方法" />

</LinearLayout>

ICat.aidl:

package com.example.serviceins;

import com.example.serviceins.Person;

interface ICat {
	
    void setName(String name);
	
    String desc();
}

ICatImpl:

package com.example.serviceins;

import android.os.RemoteException;

import com.example.serviceins.ICat.Stub;

/*
 * 業務接口的具體實現類
 */
public class CatImpl extends Stub {
	private String name;

	@Override
	public void setName(String name) throws RemoteException {
		this.name = name;
	}

	@Override
	public String desc() throws RemoteException {
		return "hello! my name is " + name + "," + "I am a police.";
	}
}

MyBoundService:

package com.example.serviceins;

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

public class MyBoundService extends Service {
	public MyBoundService() {
	}

	@Override
	public void onCreate() {
            super.onCreate();
	}

	@Override
	public IBinder onBind(Intent intent) {
	    return new CatImpl();
	}

	@Override
	public boolean onUnbind(Intent intent) {
	    return super.onUnbind(intent);
	}

	@Override
	public void onDestroy() {
	    super.onDestroy();
	}
}
相關文章
相關標籤/搜索