使用AIDL跨进程通信

之前对IPC的研究有接触到AIDL,AIDL的作用实际上就是跨进程通信,因为进程间是各自维护着自己的一个内存,当前进程想要访问到其他进程的内存,就可以通过AIDL来实现。
假定现在进程1(服务端)中有一个学生信息的集合,现在要在进程2(客户端)通过学生ID获取到进程1中集合中某个学生的信息。下图为结构图:
这里写图片描述
首先,需要创建Student类:

//必须序列化,不然无法传输二进制对象
public class Student implements Parcelable{
    //id,姓名,年龄
    private int id;
    private String name;
    private int age;

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    protected Student(Parcel in) {
        id = in.readInt();
        name = in.readString();
        age = in.readInt();
    }

    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 int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

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

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeInt(id);
        parcel.writeString(name);
        parcel.writeInt(age);
    }
}

接着,需要创建aidl文件,Student.aidl和IStuInterface.aidl:

// Student.aidl
package com.aidl;

// Declare any non-default types here with import statements
parcelable Student;
// IStuInterface.aidl
package com.aidl;

// 即使同一包内,也要导入
import com.aidl.Student;

interface IStuInterface {
    //返回学生对象
    Student getStudent(int id);
}

点击build project,会自动生成一个java文件
这里写图片描述
这个文件便是跨进程的具体实现,具体原理可参考:http://blog.youkuaiyun.com/u010429311/article/details/52300794
这个文件里面有一个抽象的方法:

public com.aidl.Student getStudent(int id) throws android.os.RemoteException;

因此,需要创建一个service来具体实现IStuInterface中的方法,来为进程2提供服务。

public class QueryService extends Service {
    public static final String TAG = "Service";

    private ArrayList<Student> students;

    //具体实现,返回对应id的Student对象
    private IStuInterface.Stub stub = new IStuInterface.Stub() {
        @Override
        public Student getStudent(int id) throws RemoteException {
            for (Student s : students) {
                if (s.getId() == id) {
                    return s;
                }
            }
            return null;
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return stub;
    }

    //onCreate首先会被执行
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate");
        students = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            students.add(new Student(i, "student" + i, 20));
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG, "onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy");
    }
}

现在服务也做好了,就需要一个进程来使用这个服务,从而获取到Student对象:

public class StudentActivity extends AppCompatActivity {
    private EditText etId;
    private Button btnQuery;
    private TextView tvName, tvAge;
    private IStuInterface mService;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //将服务器端提供的IBinder对象转化为IStuInterface对象
            mService = IStuInterface.Stub.asInterface(iBinder);
        }

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

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

        Intent i = new Intent();
        i.setPackage(getPackageName());
        i.setAction("com.aidl.QueryService");
        bindService(i, connection, Context.BIND_AUTO_CREATE);

        etId = (EditText) findViewById(R.id.et_id);
        btnQuery = (Button) findViewById(R.id.btn_query);
        tvName = (TextView) findViewById(R.id.tv_name);
        tvAge = (TextView) findViewById(R.id.tv_age);

        btnQuery.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int id = Integer.parseInt(etId.getText().toString().trim());
                try {
                    Student student = mService.getStudent(id);
                    if (student != null) {
                        tvName.setText(student.getName());
                        tvAge.setText(student.getAge() + "");
                    } else {
                        tvName.setText("无记录");
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

完成上面的操作基本上实现了AIDL的简单应用,但由于需要跨进程,StudentActivity 就需要运行在另外一个进程上,这就需要在AndroidManifest上配置 :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.aidl">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!--通过android:process=":remote"来实现该Activity运行在新进程中-->
        <activity android:name=".StudentActivity"
            android:process=":remote"
            ></activity>
        <!--Service声明-->
        <service android:name=".QueryService"
            >
            <intent-filter>
                <action android:name="com.aidl.QueryService"/>
            </intent-filter>
        </service>
    </application>

</manifest>

当然,实现不同经常不局限于android:process=”:remote”,也可以创建另外一个应用程序,同样也可以实现AIDL功能。
结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值