第六十二讲:Android之AIDL(二)

本文介绍如何在Android应用中使用AIDL实现进程间传递自定义类型参数,包括实现 Parcelable 接口的方法及示例代码。

只会幻想而不行动的人,永远也体会不到收获果实时的喜悦。


本讲内容:Android之进程间传递自定义类型参数

上一讲我们讲解了简单的AIDL进程间通信的操作,客户端向服务端发送一个String类型的参数,服务端也返回一个String类型的结果,本讲我们讲解向服务端传递复杂的数据类型。


一、AIDL对Java类型的支持:

AIDL默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),如果要传递自定义的类型该如何实现呢?


二、传递自定义的类型:

要传递自定义类型,首先要让自定义类型支持parcelable协议,实现步骤如下:


第一步:自定义类型必须实现Parcelable接口,并且实现Parcelable接口的public void writeToParcel(Parcel dest, int flags)方法 。
第二步:自定义类型中必须含有一个名称为CREATOR的静态成员,该成员对象要求实现Parcelable.Creator接口及其方法。
第三步:创建一个aidl文件声明你的自定义类型。

三、Parcelable接口的作用:

实现了Parcelable接口的实例可以将自身的状态信息(状态信息通常指的是各成员变量的值)写入Parcel,也可以从Parcel中恢复其状态。 Parcel用来完成数据的序列化传递。 


四、下面我们通过一个例子讲解:

客户端和服务端的源码结构如下:

         

(一)建立一个服务端的工程的步骤:

第一步:创建自定义类型,并实现Parcelable接口,使其支持parcelable协议。如:在com.person.aidl创建Person.java:

package com.person.aidl;

import android.os.Parcel;
import android.os.Parcelable;

public class Person implements Parcelable {
	private String name;
	private int sex;

	// 必须提供一个名为CREATOR的static final属性 该属性需要实现android.os.Parcelable.Creator<T>接口
	public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
		@Override
		public Person createFromParcel(Parcel source) {
			return new Person(source);
		}

		@Override
		public Person[] newArray(int size) {
			return new Person[size];
		}
	};

	public Person() {
	}

	private Person(Parcel source) {
		readFromParcel(source);
	}

	@Override
	public int describeContents() {
		return 0;
	}

	// 注意写入变量和读取变量的顺序应该一致 不然得不到正确的结果
	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeString(name);
		dest.writeInt(sex);
	}

	// 注意读取变量和写入变量的顺序应该一致 不然得不到正确的结果
	public void readFromParcel(Parcel source) {
		name = source.readString();
		sex = source.readInt();
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getSex() {
		return sex;
	}

	public void setSex(int sex) {
		this.sex = sex;
	}
}


第二步: 在自定义类型所在包下创建一个aidl文件对自定义类型进行声明,文件的名称与自定义类型同名。代码如下:

package com.person.aidl;
parcelable Person;

第三步: 在接口aidl文件中使用自定义类型,需要使用import显式导入,创建IGreetService.aidl文件,代码如下:
package com.person.aidl;  
import com.person.aidl.Person;  
  
interface IGreetService {  
    String greet(in Person person);  
}  

第四步: 建立一个服务类(Service的子类)代码如下:

public class AIDLService extends Service {
	private static final String TAG = "MyService";

	IGreetService.Stub stub = new IGreetService.Stub() {
		@Override
		public String greet(Person person) throws RemoteException {
			Log.i(TAG, "greet(Person person) called");

			String greeting = "hello, " + person.getName();
			switch (person.getSex()) {
			case 0:
				greeting = greeting + ", you're handsome.";
				break;
			case 1:
				greeting = greeting + ", you're beautiful.";
				break;
			}
			return greeting;
		}
	};

	@Override
	public IBinder onBind(Intent intent) {
		Log.i(TAG, "onBind() called");
		return stub;
	}

	@Override
	public boolean onUnbind(Intent intent) {
		Log.i(TAG, "onUnbind() called");
		return true;
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.i(TAG, "onDestroy() called");
	}
}
在AndroidManifest.xml中配置

<service android:name=".AIDLService" >
            <intent-filter>
                <action android:name="android.intent.action.AIDLService" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
</service>

(二)建立一个客户端的工程的步骤:

第一步:把com.person.aidl包的文件拷到相应的目录中和服务端一样,使服务端和客户端在通信协议上达到了统一。


第二步:主要工作在MainActivity中完成。代码如下:

public class MainActivity extends Activity implements OnClickListener {
	private static final String TAG = "MyService";
	private Button bindBtn;
	private Button greetBtn;
	private Button unbindBtn;
	private IGreetService greetService; 
	private ServiceConnection conn = new ServiceConnection() {
		@Override
		public void onServiceDisconnected(ComponentName name) {
			Log.i(TAG, "onServiceDisconnected() called");
		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			Log.i(TAG, "onServiceConnected() called");
			greetService = IGreetService.Stub.asInterface(service); 
		}
	};

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

		bindBtn = (Button) findViewById(R.id.bindService);
		greetBtn = (Button) findViewById(R.id.greet);
		unbindBtn = (Button) findViewById(R.id.unbindService);
		bindBtn.setOnClickListener(this);
		greetBtn.setOnClickListener(this);
		unbindBtn.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.bindService:
			Intent intent = new Intent("android.intent.action.AIDLService");
			bindService(intent, conn, Context.BIND_AUTO_CREATE);
			bindBtn.setEnabled(false);
			greetBtn.setEnabled(true);
			unbindBtn.setEnabled(true);
			break;
			
		case R.id.greet:
			try {
				 Person person = new Person();  
                 person.setName("dan");  
                 person.setSex(0);  
                 String retVal = greetService.greet(person);  
                 Toast.makeText(MainActivity.this, retVal, Toast.LENGTH_SHORT).show();
			} catch (RemoteException e) {
				Toast.makeText(MainActivity.this, "error", Toast.LENGTH_SHORT).show();
			}
			break;
			
		case R.id.unbindService:
			 unbindService(conn);  
             bindBtn.setEnabled(true);  
             greetBtn.setEnabled(false);  
             unbindBtn.setEnabled(false); 
			break;
		}
	}
}

下面是运行结果:(要先启动服务器)


点击bindService


点击greet


点击unbindService



本讲就到这里,Take your time and enjoy it


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值