Android studio上面学习Aidl实现复杂数据类型的传递

时间:2024-04-01 13:34:25

上一篇学习使用了 基本数据类型的传递,但是在实际开发中肯定是不够用的

这一篇主要学习使用Aidl来实现自定义对象的传递



服务端要简单一些,先写一下服务端(例子是参考的网上的)

需要传递的实体类(不能用Serializable)


Android studio上面学习Aidl实现复杂数据类型的传递



package com.chang.test.remote;

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

/**
 * Created by changquan on 2016/2/26.
 */
public class StudentBean implements Parcelable{

    private String name;
    private int age;
    private long number;

    public StudentBean(String name, int age, long number)
    {
        this.name = name;
        this.age = age;
        this.number = number;
    }

    public StudentBean(Parcel source)
    {
        //注意:这里的name  age  number 的读取顺序和下面writeToParcel()方法里面的顺序要一致,否则出错
        this.name = source.readString();
        this.age = source.readInt();
        this.number = source.readLong();
    }

    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 long getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", number=" + number +
                '}';
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags)
    {
        dest.writeString(name);
        dest.writeInt(age);
        dest.writeLong(number);
    }

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

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



}


然后是两个aidl文件(一个是供使用的接口,一个是为bean指定路径)

Android studio上面学习Aidl实现复杂数据类型的传递



StudentBean.aidl(这里去创建aidl文件的时候,因为同名所以可以先创建一个文件,然后改后缀名就好)


package com.chang.test.remote;
parcelable StudentBean;


Iserver.aidl

// IServer.aidl
package com.chang.test.remote;
import com.chang.test.remote.StudentBean;

// Declare any non-default types here with import statements

interface IServer {
   
             // 一般数据类型
             void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
             double aDouble, String aString);

             String callRemote();
             
             
             // 复杂数据类型
             // 这里的in 是指客户端传值 ,out是服务端返回值,inout是代表双向传值,必须要写一个
             List<StudentBean> addStudent(in StudentBean studentBean); 
}

这里可能会报错,找不到bean,那就是文件放的位置不对,可以通过下面的方法来解决(在该模块的gradle里面添加)

sourceSets {
    main {
        Manifest.srcFile 'src/main/AndroidManifest.xml'
        java.srcDirs = ['src/main/java', 'src/main/aidl']
        resources.srcDirs = ['src/main/java', 'src/main/aidl']
        aidl.srcDirs = ['src/main/aidl']
        res.srcDirs = ['src/main/res']
        assets.srcDirs = ['src/main/assets']
    }
}

也有可能直接编译失败 报如下的错

Error:Execution failed for task ':remote:compileDebugAidl'.

这个可能是aidl文件的包名有误,也有可能是项目的编译版本和编译工具的版本不一致,右键项目 open Moudle Setting -> app -> 修改Compile Sdk Version 和Build Tools Version 版本一致


接下来就是所有接口的实现类

RemoteServerde 实现


package server;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

import com.chang.test.remote.IServer;
import com.chang.test.remote.StudentBean;

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

/**
 * Created by changquan on 2017/8/22.
 */

public class RemoteServer extends Service{

    private ArrayList<StudentBean> students;

    @Override
    public IBinder onBind(Intent intent) {
        students = new ArrayList<>();
        return mBinder;
    }

    private IBinder mBinder = new IServer.Stub() {

        // 基本类型
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public String callRemote() throws RemoteException {
            return "100000";
        }

        
        // 复杂类型
        @Override
        public List<StudentBean> addStudent(StudentBean student) throws RemoteException {
            students.add(student);
            return students;
        }
    };
}


// 所有服务端的实现就已经完成了

// 接下来就要实现 客户端了

Android studio上面学习Aidl实现复杂数据类型的传递


简单的看一下客户端的目录

aidl文件夹就是拷贝的服务端的

StudentBean 也是拷贝的服务端的,但是要保证包名一致和服务端

MianActivity里面绑定远程服务(具体的实现如下)

package com.chang.test.chang;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.chang.test.remote.IServer;
import com.chang.test.remote.StudentBean;

import java.util.ArrayList;


public class MainActivity extends Activity {

    private TextView bind;
    private Intent intent;
    private IServer iServer;
    private MyConn myConn = new MyConn();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bind = (TextView) findViewById(R.id.bind);

        bind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 绑定服务
                intent = new Intent();
                intent.setAction("android.intent.action.com.chang.test.remoteserver");
                intent.setPackage("com.chang.test.remote");
                bindService(intent,myConn,BIND_AUTO_CREATE);
            }
        });
    }


    class MyConn implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iServer = IServer.Stub.asInterface(service);
            try {

                // 基本数据的类型
                String s = iServer.callRemote();
                Log.e("hhhhhhhhhh",s);

                // 复杂类型
                ArrayList<StudentBean> students = (ArrayList<StudentBean>) iServer.addStudent(new StudentBean("changchang",20,120));
                Log.e("hhhhhhhhhh",students.toString());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Toast.makeText(MainActivity.this,"失败!",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(myConn);
    }
}

上面的action在上一遍中有写到,就是远程server的一个事件


这样就完成了整个studio 中aidl的全部实现


效果

Android studio上面学习Aidl实现复杂数据类型的传递