使用AIDL实现进程间的通信

本文实现的功能:
下图是客户端的截图
在这里插入图片描述
第一个button用于client程序绑定servcer程序的服务
edit用于用户输入学生的ID
第二个Button用于调用servcer程序的getStudent方法,获取学生的数据。学生的数据在server程序中,我们实现的是从client程序访问Server程序的数据,这就是用AIDL实现进程的通信,
第三个button用于取消绑定

下面是程序的实现步骤:

1、在服务端定义一个Student.class,并使其继承自Parcelable

//**1、**implements Parcelable,使这个类序列化,其中的数据才能在两个进程间传递
public class Student extends LitePalSupport implements Parcelable{
    @Column(unique = true)
    private int studentId;
    private String name;
    private double grade;

    protected Student(Parcel in) {
//**4、**解包,读取其中的数据,读取顺序需要和写入的顺序一样
        studentId = in.readInt();
        name = in.readString();
        grade = in.readDouble();
    }
//**3、**创建 Creator<Student>类,并重写其中的方法
    public static final Creator<Student> CREATOR = new Creator<Student>() {
        //解包,读取包中的数据
        @Override
        public Student createFromParcel(Parcel in) {
            return new Student(in);
        }
        @Override
        public Student[] newArray(int size) {
            return new Student[size];
        }
    };
    public Student() {
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + studentId +
                ", name='" + name + '\'' +
                ", grade=" + grade +
                '}';
    }
    public void setStudentId(int id) {
        this.studentId = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setGrade(double grade) {
        this.grade = grade;
    }
    public int getStudentId() {
        return studentId;
    }
    public String getName() {
        return name;
    }
    public double getGrade() {
        return grade;
    }
    //**2、**将当前数据打包,注意,之后的读数据的顺序需要和写数据一样
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(studentId);
        dest.writeString(name);
        dest.writeDouble(grade);
    }
}

2、创建ISteudent.aidl,需要和Student在一个包中,直接new一个AIDL,会生成一个aidl包,ISteudent.aidl的包名和Student一样

package com.michal.getstudentservicer;
//1、需要手动import Student
import com.michal.getstudentservicer.Student;
//2、interface的public去掉
interface IStudentService {

    Student getStudent(int id);
}

3、在ISteudent.aidl所在的包下,新建一个Student.aidl,new file>Student.aidl,与Student是一样的名称内容如下

package com.michal.getstudentservicer;
parcelable Student;

4、新建一个服务器端的服务,需要实现getStudent的方法

//**1、**继承Service
public class GetStudentServer extends Service {
    public GetStudentServer() {
    }
//5、客户端绑定服务端的服务之后会调用到这个方法,并返回StudentService对象给客户端,
//客户端得到这个对象之后就可以调用getStudent方法,此方法会调用刚才重新的getStudent方法,并将获取的Student对象返回给客户端
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.e("michal","onBind");
        return new StudentService();
    }
//2、新建一个StudentService类,继承IstudentService.Stub
    class StudentService extends IStudentService.Stub{
//**3、**重写getStudent方法,这是这个方法的真正实现,客户端调用的就是这个方法
        @Override
        public Student getStudent(int id) throws RemoteException {
            //4、查询数据库中对应id的Student的数据,并返回给客户端
						List<Student> student = LitePal.where("id=?",String.valueOf(id)).find(Student.class);
            if (student.size()>0)
                return student.get(0);
            else {
                return null;
            }
        }
    }
}

5、服务端搞定,现在开始写客户端,客户端算是另一个程序(进程)

将服务端创建的Student,ISteudent.aidl,Student.aidl复制到客户端,注意两者的包名必须一样,我选择在客户端创建同样的包名,然后将三个文件的内容复制过去

6、在客户端创建getStudentActivity,并创建点击事件,包括绑定远程服务,调用远程服务的getStudent方法,取消绑定

public class GetStudentActivity extends AppCompatActivity {

    private IStudentService studentService;
    private EditText editText;
    private ServiceConnection serviceConnection;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_get_student);
        editText = findViewById(R.id.student_id);
    }
public void onBindRemoteService(View view) {}
public void invokeRemoteService(View view) {}
public void unBindRemoteService(View view) {}
}

7、实现onBindRemoteService方法

		public void onBindRemoteService(View view) {
//1、如果serviceConnection为空,则创建一个新对象
        if (serviceConnection==null){
            serviceConnection = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    LogUtils.e("onconnection");
//4、首次绑定之后会触发onServiceConnected,在此处获取IstudentService对象,在后面的incoke方法中用这个对象调用getStudent方法
										 studentService = IStudentService.Stub.asInterface(service);
                }
                @Override
                public void onServiceDisconnected(ComponentName name) {
                }
            };
//2、启动绑定服务,此处为隐式启动,需要在服务端设置一个intent-filter
            Intent intent = new Intent();
            intent.setAction("com.michal.getstudentservicer.GetStudentServer");
//3、设置远程服务端的包名,注意可能无法直接用new Intent(Action str),bindService()启动,因为不知道哪个版本开始不支持这种操作
						intent.setPackage("com.michal.getstudentservicer");
            bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE);
            LogUtils.e("绑定服务");
        }else {
            LogUtils.e("已绑定服务");
        }
    }

8、实现invokeRemoteService方法,调用服务端的getStudent方法,获取学生的数据

		public void invokeRemoteService(View view) {
        if (studentService!=null){
            try {
//1、获取editext输入的ID,并判断有没有输入,如果长度为0,则说明用户没输入ID,不会执行下面
                String meditText = editText.getText().toString();
                if (meditText.length()==0){
                    Toast.makeText(this,"请输入ID",Toast.LENGTH_SHORT).show();
                }else {
                    int id = Integer.parseInt(meditText);
                    if (id != 0){
//2、使用studentService对象调用getStudent方法,返回student对象
                        Student student = studentService.getStudentById(id);
                        if (student==null){
                            LogUtils.e("查询不到该ID");
                        }else {
                            LogUtils.e(student.toString());
                        }
                    }
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

程序源码地址:https://download.csdn.net/download/weixin_42456904/19305404

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AIDL(Android Interface Definition Language)是一种用于 Android 平台的接口定义语言,它可以帮助不同进程的组件进行通信。下面是使用 AIDL 进行进程通信的步骤: 1.定义 AIDL 接口 首先,在服务端和客户端之定义一个 AIDL 接口。在 AIDL 文件中,定义需要向客户端公开的方法和参数。 2.实现 AIDL 接口 在服务端中,实现定义的 AIDL 接口,并在 onCreate() 方法中将其注册到系统中。 3.绑定服务端 在客户端中,使用 bindService() 方法绑定服务端。 4.获取 AIDL 接口实例 在客户端中,实现 ServiceConnection 接口,当服务端连接成功时,会回调 onServiceConnected() 方法。在此方法中,可以获取到 AIDL 接口实例。 5.调用 AIDL 接口方法 在客户端中,通过获取到的 AIDL 接口实例,即可调用服务端暴露的方法。 下面是一个简单的示例代码: 服务端: ``` //定义 AIDL 接口 interface IMyAidlInterface { int add(int a, int b); } //实现 AIDL 接口 class MyAidlInterfaceImpl extends IMyAidlInterface.Stub { @Override public int add(int a, int b) throws RemoteException { return a + b; } } //在 onCreate() 方法中注册 AIDL 接口 @Override public void onCreate() { super.onCreate(); Intent intent = new Intent(this, MyAidlInterfaceService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); Log.i(TAG, "MyAidlInterfaceService is created."); } //定义 ServiceConnection 对象,以便在客户端连接时获取 AIDL 接口实例 private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); Log.i(TAG, "MyAidlInterfaceService is connected."); } @Override public void onServiceDisconnected(ComponentName name) { mIMyAidlInterface = null; Log.i(TAG, "MyAidlInterfaceService is disconnected."); } }; ``` 客户端: ``` //定义 ServiceConnection 对象 private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { //获取 AIDL 接口实例 mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); Log.i(TAG, "MyAidlInterfaceService is connected."); } @Override public void onServiceDisconnected(ComponentName name) { mIMyAidlInterface = null; Log.i(TAG, "MyAidlInterfaceService is disconnected."); } }; //使用 bindService() 方法绑定服务端 Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.myaidlservice", "com.example.myaidlservice.MyAidlInterfaceService")); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); //调用服务端暴露的方法 int result = mIMyAidlInterface.add(1, 2); ``` 希望这个简单的示例可以帮助你了解如何使用 AIDL 进行进程通信

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值