您的位置:首页 > 大数据 > 人工智能

Aidl在项目中的使用

2016-05-04 10:47 501 查看
Aidl

Aidl是一个进程间通信的一个语言,通过他我们可以在不同应用之间通讯,不管有多少应用都可以,但是前提是必须要使用同一份定义好的aidl文件,这个文件包含的有aidl类型的文件,已经继承了Parcelable的要在aidl中传输的类。

现在网上很多例子中对于Aidl的讲解其实是很详细的,但是可能在开发中还是会有不同的问题,我算是总结吧。

关于aidl的流程:

(1)  服务端创建aidl文件,aidl文件创建的时候可以是在任意包下创建,但是一般很多人都会专门为他创建一个包,



   (2)  书写aidl文件,他的写法是这样的:

第一行是这个文件当前所在的包名, 然后下边可以导入他要用到的类的,然后就是这个接口类的定义“

package com.braincol.aidl.service;
import com.braincol.aidl.service.Beauty;
import com.braincol.aidl.service.OnChangeListener;
interface RemoteBeauty {
void setListener(in OnChangeListener listener);
void notify(in String s,in OnChangeListener listener);

}
(3) 然后就会在gen文件夹下生成相应的aidl文件(ecplise中),然后自己写一个service,里边通过IBinder来返回aidl对象

package com.braincol.aidl.service;

import java.util.ArrayList;
import java.util.List;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
/**
*提供服务的service
*/
public class RemoteService extends Service {
private final static String TAG = "RemoteService";
private List<OnChangeListener> list = new ArrayList<OnChangeListener>();
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "执行了OnBind");
return new MyBinder();
}

private class MyBinder extends RemoteBeauty.Stub{

@Override
public void notify(String s, OnChangeListener listener)
throws RemoteException {
Log.e("TAG", "NOTIFY");
Log.e("TAG", list.size()+"");
if (list.size() >0) {
for (int i = 0; i < list.size(); i++) {
list.get(i).getINotifyCallBack().onStringChange(s);;
}
}
}
@Override
public void setListener(OnChangeListener listener)
throws RemoteException {
list.add(listener);
}}
}


(4) 然后在清单文件中把这个service进行注册,然后指定Action。在客户端要通过这个Action来进行绑定,服务端就写完了。

  (5) 上边的服务端写完以后,然后就是客户端了,客户端相对更简单,只要把服务端的aidl包直接拷贝一份放到客户端就好,但是记得要删除service文件,然后你就会看到客户端gen文件下边也生成了aidl文件

(6) 客户端进行绑定就可以进行通信了

package com.example.test2;

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.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.braincol.aidl.service.INotifyCallback;
import com.braincol.aidl.service.OnChangeListener;
import com.braincol.aidl.service.RemoteBeauty;

public class MainActivity extends Activity {

private Button button;
private RemoteBeauty remoteBeauty;
private INotifyCallback iNotifyCallback = new INotifyCallback() {

@Override
public IBinder asBinder() {
return new INotifyCallback.Stub() {

@Override
public void onStringChange(String str) throws RemoteException {
button.setText(str);
}
};
}

@Override
public void onStringChange(String str) throws RemoteException {

}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.btn_);
button.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.braincol.aidl.remote");
bindService(intent, new ServiceConnection() {

@Override
public void onServiceDisconnected(ComponentName name) {

}

@Override
public void onServiceConnected(ComponentName name,
IBinder service) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "连接", 1000).show();
remoteBeauty = RemoteBeauty.Stub.asInterface(service);
try {
remoteBeauty.setListener(new OnChangeListener(iNotifyCallback));
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, Context.BIND_AUTO_CREATE);
}
});

Button button_1 = (Button)findViewById(R.id.btn_1);
button_1.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
try {
remoteBeauty.notify("我要改變你", null);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}

}


上边基本上市一个简单的aidl的写法,那么如果我们要在Aidl中传递跟使用实体类对象呢,

那么就要创建相应的aidl文件,还有跟它同名的实现了Parcelable借口的类,应为传递的时候必须是序列化才能进行传递,还有一点要注意的就是,跟它同名的实现了Parcelable接口的类不能是抽象类。

下边看一个实体类的实现步骤:

(1)首先创建Aidl文件,然后编写aidl文件 ,里边的代码是这样的:

<span style="white-space:pre">	</span>package com.braincol.aidl.service;
<span style="white-space:pre">	</span>parcelable Person;


(2)同名实体类的书写

package com.braincol.aidl.service;

import android.os.Parcel;
import android.os.Parcelable;
/**
*Parcelable是android提供的一个比serializable效率更高的序列号接口这里必须要继承Parcelable!
* 在实体类我们要做两件重要的事情:
* 第一:实现Parcelable接口
* 第二:定义一个Parcelable.Creator类型的CREATOR对象
* 第三:要提供一个Person.aidl文件,其中内容为parcelable Beauty,定义了之后,在其他aidl文件中引用Beauty时便不会提示出错了。
*/
public class Person implements Parcelable {

String name ;
int age ;
String sex ;

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 String getSex() {
return sex;
}

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

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

/**
* 将对象序列号
* dest 就是对象即将写入的目的对象
* flags 有关对象序列号的方式的标识
* 这里要注意,写入的顺序要和在createFromParcel方法中读出的顺序完全相同。例如这里先写入的为name,
* 那么在createFromParcel就要先读name
*/
@Override
public void writeToParcel(Parcel dest, int flags) {

dest.writeString(name);
dest.writeInt(age);
dest.writeString(sex);
}
/**
* 在想要进行序列号传递的实体类内部一定要声明该常量。常量名只能是CREATOR,类型也必须是
* Parcelable.Creator<T>
*/
public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() {

/**
* 创建一个要序列号的实体类的数组,数组中存储的都设置为null
*/
@Override
public Person[] newArray(int size) {
return new Person[size];
}

/***
* 根据序列号的Parcel对象,反序列号为原本的实体对象
* 读出顺序要和writeToParcel的写入顺序相同
*/
@Override
public Person createFromParcel(Parcel source) {
String name = source.readString();
int age = source.readInt();
String sex = source.readString();
Person person = new Person();
person.setName(name);
person.setAge(age);
person.setSex(sex);

return person;
}
};

}


这样的话一个实体类就ok了。

但是有的时候我们可能还会用到别的东西,比如可能要写一个监听器,还有回调的callBack的话他该如何写呢?

写法其实类似:

package com.braincol.aidl.service;

parcelable OnChangeListener;

package com.braincol.aidl.service;

import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;
// 不嫩使用抽象类
public  class OnChangeListener implements Parcelable{
private   INotifyCallback callback;

public OnChangeListener (INotifyCallback callback){
this.callback = callback;
}
public void setINotifyCallback(INotifyCallback iNotifyCallback){
this.callback = iNotifyCallback;
}
public  INotifyCallback getINotifyCallBack(){
return  callback;
}
// 添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口
public static final Parcelable.Creator<OnChangeListener> CREATOR = new Creator<OnChangeListener>() {

@Override
public OnChangeListener[] newArray(int size) {
// TODO Auto-generated method stub
return new OnChangeListener[size];
}

@Override
public OnChangeListener createFromParcel(Parcel source) {
OnChangeListener listener = new OnChangeListener(INotifyCallback.Stub.asInterface(source.readStrongBinder()));
return listener;
}
};

@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStrongBinder(callback.asBinder());
}
}

这样就ok了。

总结:

aidl可以实现Android手机上边应用间的相互访问,可以以实现不类似其中一个app有改动的时候通知其他所有的app的功能(类似广播功能),还可以通过远程aidl实现html上边跟客户端的交互,其中就需要用到类似监听器。

下边把我写的Demo附上:Demo,Demo是可以实现类似广播的功能,但是前提是你的app要都打开才行,如果能熟练这个Demo的话基本上Aidl没有任何问题了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Aidl