您的位置:首页 > 移动开发 > Android开发

Android ipc数据传输方式之一 AIDL

2018-02-03 15:47 525 查看
AIDL 的全名是 Android
Interface definition language,就是一种在安卓的接口定义语言,而它的作用就是主要用于不同进程之间的通信

一 如何在AndroidStudio中创建AIDL?

首先要创建一个AIDL文件 AndroidStudio 穿件方式如下图:



第一次这样创建完成后就会出现一个aidl的文件夹

然后我们创建一个aidl文件 写完之后我们makeproject一下(最好先不要写实体类进去 等到下面实体类aidl步骤完成之后再回来写实体的相关导包
声明 方法等) 因为aidl默认传递的是String 加 基本数据类型

// IMyAidlInterface.aidl
package com.example.lyl.aidldemo;
import com.example.lyl.aidldemo.UserBean;//一定要导入实体类的包!
// Declare any non-default types here with import statements

interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
//    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
//            double aDouble, String aString);

int add (int a , int b);
void sendUrl(String url);
//传递其他数据类型的时候前面要加上in 代表这个数据要往服务里传
void sendUser (in UserBean userBean);
}

我们定义一个加法和字符串传输方法,还有一个传递实体类的方法  

注意:

sendUser方法中 实体类前面的in是定向tag,定向Tag表示在跨进程通信中数据的流向,用于标注方法的参数值,分为
in、out、inout 三种。其中 in 表示数据只能由客户端流向服务端, out 表示数据只能由服务端流向客户端,而 inout 则表示数据可在服务端与客户端之间双向流通。此外,如果AIDL方法接口的参数值类型是:基本数据类型、String、CharSequence或者其他AIDL文件定义的方法接口,那么这些参数值的定向 Tag 默认是且只能是 in,所以除了这些类型外,其他参数值都需要明确标注使用哪种定向Tag。

如果我们要传递实体类该怎么办呢?

我们先创建一个实体类并将它包裹化

public class UserBean implements Parcelable {
private int id;
private S
4000
tring password;

public UserBean() {
}

protected UserBean(Parcel in) {
id = in.readInt();
password = in.readString();
}

public static final Creator<UserBean> CREATOR = new Creator<UserBean>() {
@Override
public UserBean createFromParcel(Parcel in) {
return new UserBean(in);
}

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

@Override
public String toString() {
return "UserBean{" +
"id=" + id +
", password='" + password + '\'' +
'}';
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

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

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(password);
}
}


在定义一个aidl 这个aidl的名字需要和实体类的名字一样

// UserBean1.aidl
package com.example.lyl.aidldemo;

parcelable UserBean;
这个实体类的aidl中 需要把类进行包裹化声明 完成以上步骤就可以数据传递了

二 如何利用aidl在activity进程和service进程中进行数据传递

然后要创建一个新的进程 创建一个Service 并在manifest 清单文件中进行声明:

<service android:name=".AidlServer" android:process=":aidl"/>
pricess属性是让这个组件运行在不同于APP进程的另一个新进程 并给这个进程起一个名字

然后创建这个服务并绑定

public class AidlServer extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new ServiceBinder();
}

public class ServiceBinder extends IMyAidlInterface.Stub{

@Override
public int add(int a, int b) throws RemoteException {
int i2 = Process.myPid();//获取该进程的ID。
Log.d("MainActivity", "Service进程id:" + i2);
int i3 = Process.myTid();//获取该线程的ID。
Log.d("MainActivity", "Service线程id:" + i3);
return a+b;
}

@Override
public void sendUrl(String url) throws RemoteException {
int i2 = Process.myPid();//获取该进程的ID。
Log.d("MainActivity", "Service进程id:" + i2);
int i3 = Process.myTid();//获取该线程的ID。
Log.d("MainActivity", "Service线程id:" + i3);
Log.d("ServiceBinder", url);
}

@Override
public void sendUser(UserBean userBean) throws RemoteException {
int i2 = Process.myPid();//获取该进程的ID。
Log.d("MainActivity", "Service进程id:" + i2);
int i3 = Process.myTid();//获取该线程的ID。
Log.d("MainActivity", "Service线程id:" + i3);
Log.d("ServiceBinder", "userBean:" + userBean);
}

}
}


我们可以看到 我们单进程中使用service时 一般都继承一个binder类 但是为了要在Service中实现我们再Aidl中声明的方法,

所以我们需要继承IMyAidlInterface.Stub
这个类

这样我们在服务中就可以接收到Activity进程中的网址 我们就可以在一个新的进程中做下载操作

最后我们只需要在Acitivity中用bindservice 绑定服务 就可以了

Activity的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.lyl.aidldemo.MainActivity">

<Button
android:id="@+id/btn_bind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绑定服务" />

<Button
android:id="@+id/btn_control"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="控制服务" />

<Button
android:id="@+id/btn_change"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="传值" />

</LinearLayout>


Activity中的代码

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private Button btn_bind;
private Button btn_control;
private Button btn_change;
private IMyAidlInterface iMyAidlInterface;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};

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

private void initView() {
btn_bind = (Button) findViewById(R.id.btn_bind);
btn_control = (Button) findViewById(R.id.btn_control);
btn_change = (Button) findViewById(R.id.btn_change);

btn_bind.setOnClickListener(this);
btn_control.setOnClickListener(this);
btn_change.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_bind:
Intent intentAidl = new Intent(MainActivity.this,AidlServer.class);
bindService(intentAidl,serviceConnection,BIND_AUTO_CREATE);
break;
case R.id.btn_control:
int i = Process.myPid();//获取该进程的ID。
Log.d("MainActivity", "Activity进程id:" + i);
int i1 = Process.myTid();//获取该线程的ID。
Log.d("MainActivity", "Activity线程id:" + i1);
try {
iMyAidlInterface.sendUrl("https://www.baidu.com");
UserBean userBean = new UserBean();
userBean.setId(1);
userBean.setPassword("123");
iMyAidlInterface.sendUser(userBean);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case R.id.btn_change:
int i2 = Process.myPid();//获取该进程的ID。
Log.d("MainActivity", "Activity进程id:" + i2);
int i3 = Process.myTid();//获取该线程的ID。
Log.d("MainActivity", "Activity线程id:" + i3);
try {
int add = iMyAidlInterface.add(5, 8);
Log.d("MainActivity", "add:" + add);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: