1.IPC及AIDL产生原因:
AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
在Android中,每个应用(Application)执行在它自己的进程中,无法直接调用到其他应用的资源,这也符合“沙箱”的理念。所谓沙箱原理,一般来说用在移动电话业务中,简单地说旨在部分地或全部地隔离应用程序。因此,在Android中,当一个应用被执行时,一些操作是被限制的,比如访问内存,访问传感器,等等。这样做可以最大化地保护系统,免得应用程序“为所欲为”。那我们有时需要在应用间交互,怎么办呢?于是,Android需要实现IPC协议。然而,这个协议还是有点复杂,主要因为需要实现数据管理系统(在进程或线程间传递数据)。为了暂时减缓这个“会呼吸的痛”,Android为我们实现了自己的IPC,也就是AIDL;
AIDL是IPC的一个轻量级实现,用了对于Java开发者来说很熟悉的语法。Android也提供了一个工具,可以自动创建Stub(类构架,类骨架)
有开发过蓝牙或者WIFI应用的朋友肯定都知道,要去操作它必须先获得一个管理类,比如WIFI的管理类是WifiManager,通过getSystemService(Context.WIFI_SERVICE)就可以得到wifi的管理权限,这个提供了很多的方法可以让用户去操作它,比如打开wifi可以调用setWifiEnabled(true)方法。那这个Manager到底做了什么工作呢?是怎样实现打开wifi的呢?其实这个Manager只是一个管理类,真正干活的另有其人,是一个叫WifiService的系统服务。在Android系统中有很多的Manager,wifi的管理类叫WifiManager,蓝牙的管理类叫BluetoothManager,但是,只要有xxxManager.java,就会有Ixxx.aidl,并且有xxxService.java。这个aidl类就是实现Manager和Service通信的桥梁。
2.安卓里面要怎么来实现这个AIDL通信呢?
a. 常规的情况下, A 应用去激活B 应用中的组件的时候, 这实际上就是一种IPC通信的体现, 这个时候发送是Intent 就是
在做ipc通信 , intent 也是去实现 paraceable 接口的, ipc 通信时 传递的非8 种基本数据类型都需要去实现 这个接口
b. 进程 间 通信, 除了使用 intent 之外, 还可以使用 远程服务 调用
c. 谷歌已经对应用中提供了 aidl的技术供应用之间进行通信
3.AIDL怎么去传输数据?
安卓中有两个接口,一个是Serializable,另一个就是Parcelable,传递的时候,其实就是将一堆数据打包,然后传输,然后再分解出来。如果某个类实现了这个接口,那么它的对象实例可以写入到
Parcel
中,并且能够从中恢复,并且这个类必须要有一个
static
的
field
,并且名称要为
CREATOR
,这个
field
是某个实现了
Parcelable.Creator
接口的类的对象实例。
下面写一个实例:
创建model:
public class PersonMsg implements Parcelable
{
private String name = null;
private int age = 0;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public int describeContents()
{
return 0;
}
public void writeToParcel(Parcel out, int flags)
{
out.writeString(name);
out.writeInt(age);
}
public static final Parcelable.Creator CREATOR =
new Parcelable.Creator()
{
public PersonMsg createFromParcel(Parcel in)
{
PersonMsg msg = new PersonMsg();
msg.name = in.readString();
msg.age = in.readInt();
return msg;
}
public PersonMsg[] newArray(int size)
{
return new PersonMsg[size];
}
};
}
将这个model封装到intend中:
public class ActivityFrom extends Activity
{
private EditText nameEditText = null;
private EditText ageEditText = null;
private Button startButton = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nameEditText = (EditText)findViewById(R.id.name_content);
ageEditText = (EditText)findViewById(R.id.age_content);
startButton = (Button)findViewById(R.id.start);
startButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
String name = nameEditText.getEditableText().toString();
int age = Integer.valueOf(ageEditText.getEditableText().toString());
Log.d("name is: ", name);
Log.d("age is: ", age + "");
PersonMsg msg = new PersonMsg();
msg.setName(name);
msg.setAge(age);
Intent intent = new Intent();
intent.setClass(ActivityFrom.this, ActivityTo.class);
intent.putExtra("personmsg", msg);
startActivity(intent);
}
});
}
}
从intent中取出数据:
public class ActivityTo extends Activity
{
private EditText nameEditText = null;
private EditText ageEditText = null;
private Button startButton = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nameEditText = (EditText)findViewById(R.id.name_content);
ageEditText = (EditText)findViewById(R.id.age_content);
startButton = (Button)findViewById(R.id.start);
startButton.setVisibility(View.INVISIBLE);
Intent intent = getIntent();
PersonMsg msg = (PersonMsg)intent.getParcelableExtra("personmsg");
String name = msg.getName();
int age = msg.getAge();
nameEditText.setText(name);
ageEditText.setText(age + "");
}
}
4.最后上一个AIDL的小demo
在远程的服务端:
service类中(注意继承IAlipayService这个类,同时在onbind这个方法中返回代理的对象):
public class AlipayService extends Service {
private class AlipayAgent extends IAlipayService.Stub{
@Override
public int callPayInService(String account, float money)
throws RemoteException {
int result = pay(account, money);
return result;
}
}
@Override
public IBinder onBind(Intent intent) {
return new AlipayAgent();
}
@Override
public void onCreate() {
System.out.println("alipay 服务 创建 了 ");
super.onCreate();
}
@Override
public void onDestroy() {
System.out.println("alipay 服务 销毁 了 ");
super.onDestroy();
}
public int pay(String account, float money){
System.out.println("alipay 支付 OK 了");
return 1;
}
}
服务接口(注意不需要修饰符):
interface IAlipayService {
int callPayInService(String account, float money);
}
最后就是在mainfast文件中进行注册service:
<service android:name="com.test.alipay.AlipayService">
<intent-filter>
<action android:name="com.test.alipay"/>
</intent-filter>
</service>
这样一个服务端的service就完成了,在写调用端的时候,注意要把服务端的 .aidl文件拷贝到本地,然后再在本地新建接口对象来调用其方法:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void bindService(View v){
//绑定 alipay的 服务
Intent intent = new Intent();
intent.setAction("com.test.alipay");
bindService(intent, new MyConnection(), BIND_AUTO_CREATE);
}
private IAlipayService agent;
private class MyConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
agent = IAlipayService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
public void call(View v){
try {
int result = agent.callPayInService("test", 50f);
System.out.println(result);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}