Android AIDL传递对象问题

本文详细介绍了如何在Android中使用AIDL进行对象的传递,并通过一个具体的例子演示了客户端和服务端的具体实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

最近在研究aidl传递对象的时候,自己在网上搜了下,发现了不少问题。由于网上的资料有的对应的Android版本比较老,有的可能不适应现在的Android Studio的版本,一直有这样那样的问题。这里把我遇到的问题以及解决办法说明下。

步骤

服务端

  • 首先我们先把新建一个aidl接口类IMyAidlInterface,在项目的app目录上右键new一个AIDL File,as会自动在main目录下创建一个aidl文件夹。
  • 接着再新建一个AIDL File,Person.aidl。然后可以先rebuild下工程。
  • 接着在java的目录下,也就是与MainActivity同目录下新建一个类Person.java并实现Parcelable接口。
  • 最后就是新建Service,命名为MyService

这里说一下,网上有些文章说是在aidl的目录下建Person.java,然后最后在gradle中把aidl目录配置为java源码目录。这个我试了,但是一直编译不过,找不到Person类。所以我就直接在默认的地方新建Person类,就没有问题了。

目录结构

这里写图片描述

代码
IMyAidlInterface.aidl
package com.limingjian.aidltest2;
import com.limingjian.aidltest2.Person;

interface IMyAidlInterface {
    int add(int a,int b);
    String inPerson(in Person p);
    String outPerson(out Person p);
    String inOutPerson(inout Person p);
}

这里注意要把我们的Person类的包手动导下。

Person.aidl
package com.limingjian.aidltest2;
parcelable Person;

这里的parcelable,开头是小写的p

Person.java
package com.limingjian.aidltest2;

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

public class Person implements Parcelable {
    private String name;
    private int age;
    public Person() {
    }
    protected Person(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }
    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }
        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
    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;
    }
    @Override
    public int describeContents() {
        return 0;
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }
    public void readFromParcel(Parcel dest) {
        name = dest.readString();
        age = dest.readInt();
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
MyService.java
package com.limingjian.aidltest2;

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

public class MyService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Log_LYL", "Onstart");
        return super.onStartCommand(intent, flags, startId);

    }
    @Override
    public IBinder onBind(Intent intent) {
        Log.e("MyService", "onBind");
        return stub;
    }
    IMyAidlInterface.Stub stub = new IMyAidlInterface.Stub() {
        @Override
        public int add(int a, int b) throws RemoteException {
            return a + b;
        }

        @Override
        public String inPerson(Person p) throws RemoteException {
            String old = "name:" + p.getName() + " age:" + p.getAge();
            Log.d("Log_LYL:inPerson_", old);
            p.setName("李四");
            p.setAge(13);
            return "name:" + p.getName() + " age:" + p.getAge();
        }

        @Override
        public String outPerson(Person p) throws RemoteException {
            String old = "name:" + p.getName() + " age:" + p.getAge();
            Log.d("Log_LYL:outPerson_", old);
            p.setName("周六");
            p.setAge(20);
            return "name:" + p.getName() + " age:" + p.getAge();
        }

        @Override
        public String inOutPerson(Person p) throws RemoteException {
            String old = "name:" + p.getName() + " age:" + p.getAge();
            Log.d("Log_LYL:inOutPerson_", old);
            p.setName("弓七");
            p.setAge(57);
            return "name:" + p.getName() + " age:" + p.getAge();
        }
    };
}

最后记得在AndroidManifest.xml文件里配置Service

<service android:name=".MyService"
                 android:enabled="true"
                 android:exported="true">
            <intent-filter>
                <action android:name="com.limingjian.aidl"/>
            </intent-filter>
        </service>

到这里,服务端就写好了。接下来是客户端。

客户端

我们新建个工程用来写客户端。

  • 先把服务端的aidl目录直接拷贝到客户端的main目录下,也就是与java目录同级。
  • 然后新建一个包,这里的包名要与服务端的Person.java所在的包名相同。然后把服务端的Person.java拷贝到这个包里。

到这里aidl方面的工作就完成了。

目录结构

这里写图片描述

代码
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:id="@+id/activity_main"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="客户端"
        android:textColor="@android:color/holo_red_dark"
        android:textSize="15sp" />

    <EditText
        android:id="@+id/et_num1"
        android:layout_width="200dp"
        android:layout_height="wrap_content" />

    <EditText
        android:id="@+id/et_num2"
        android:layout_width="200dp"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/bt_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:text="加运算" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="结果:" />

        <TextView
            android:id="@+id/tv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2" />
    </LinearLayout>
</LinearLayout>
MainActivty.java
package com.limingjian.clienttest;

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.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.limingjian.aidltest2.IMyAidlInterface;
import com.limingjian.aidltest2.Person;

public class MainActivity extends AppCompatActivity {

    private EditText et_num1, et_num2;
    private TextView tv;
    private IMyAidlInterface mService;
    private Button bt_add;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_num1 = (EditText) findViewById(R.id.et_num1);
        et_num2 = (EditText) findViewById(R.id.et_num2);
        bt_add = (Button) findViewById(R.id.bt_add);
        tv = (TextView) findViewById(R.id.tv);

        Intent intent = new Intent();
        intent.setAction("com.limingjian.aidl");

        //兼容Android 5.0以上
        intent.setPackage("com.limingjian.aidltest2");

        bindService(intent, mServiceC, Context.BIND_AUTO_CREATE);

        bt_add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                add();
            }
        });
    }

    public void add() {
        int a = Integer.valueOf(et_num1.getText().toString());
        int b = Integer.valueOf(et_num2.getText().toString());
        try {
            int res = mService.add(a, b);

            tv.setText(res+"");

            Person p1 = new Person();
            p1.setName("刘大");
            p1.setAge(3);
            Person p2 = new Person();
            p2.setName("赵二");
            p2.setAge(3);
            Person p3 = new Person();
            p3.setName("张三");
            p3.setAge(3);

            tv.setText(res + "\n" + mService.inPerson(p1) + "\n" + mService.outPerson(p2) + "\n" + mService.inOutPerson(p3)+"\n" + p1.toString() + "\n" + p2.toString() + "\n" + p3.toString());

        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    ServiceConnection mServiceC = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }
    };

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

从Android 5.0开始已经不能隐式启动Service了,所以要加上intent.setPackage("com.limingjian.aidltest2"),这里的包名就是服务端的MyService所在的包的名字。

最后我们把服务端和客户端都部署到手机上。运行结果图如下

运行结果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值