Android ipc数据传输方式之一 AIDL

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 String 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;
        }
    }
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值