android创建aidl并实现跨进程通信

82 阅读2分钟

用途说明:

比如一些耗资源的操作,如下载等,我们可以单独开一个进程去下载,然后只需要获取到他的下载状态就好。

第一步:创建数据类

package com.example.test.service;

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

public class Person implements Parcelable {
    int age;
    String name;

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

    protected Person(Parcel parcel) {
        this.age = parcel.readInt();
        this.name = parcel.readString();
    }

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

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


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

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

第二步:创建aidl文件

IPersonManager.aidl

package com.example.test.service;

import com.example.test.service.PersonListener;
import com.example.test.service.Person;

interface IPersonManager {
    void sendPerson(in Person person);
    void register(PersonListener per);
    void unRegister(PersonListener per);
}

Person.aidl

package com.example.test.service;

parcelable Person;

PersonListener.aidl

package com.example.test.service;

import com.example.test.service.Person;

interface PersonListener {
    void onReceive(in Person person);
}

创建好后需要make一下,然后开始编写service文件。

aidl文件的作用是提供一个数据传输的功能,具体的业务逻辑还是得在service中。

第三步:创建PersonService

package com.example.test.service;

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

public class PersonService extends Service {

    private RemoteCallbackList<PersonListener> personListenerRemoteCallbackList = new RemoteCallbackList<>();

    public PersonService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d("pjw","onbind");
        return new binder();
    }

    public class binder extends IPersonManager.Stub {

        @Override
        public void sendPerson(Person person) throws RemoteException {
            //通知Callback循环开始,返回N为实现mReceiveListener回调的个数
            final int N = personListenerRemoteCallbackList.beginBroadcast();
            person.name = "lilei";
            for (int i = 0; i < N; i++){
                PersonListener listener = personListenerRemoteCallbackList.getBroadcastItem(i);
                if (listener != null){
                    try {
                        listener.onReceive(person);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
            //通知通知Callback循环结束
            personListenerRemoteCallbackList.finishBroadcast();
        }

        @Override
        public void register(PersonListener per) throws RemoteException {
            personListenerRemoteCallbackList.register(per);
        }

        @Override
        public void unRegister(PersonListener per) throws RemoteException {
            personListenerRemoteCallbackList.unregister(per);
        }
    }
}

第四步:将service弄到另外的进程去

<service
            android:name=".service.PersonService"
            android:enabled="true"
            android:process=":remote"
            android:exported="true">
        </service>

第五步:在activity中启动service并获取回调的数据

package com.example.test;

import androidx.appcompat.app.AppCompatActivity;

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.widget.TextView;

import com.example.test.UIUtils.CharUtils;
import com.example.test.service.IPersonManager;
import com.example.test.service.Person;
import com.example.test.service.PersonListener;
import com.example.test.service.PersonService;

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

public class MainActivity extends AppCompatActivity {

    private TextView textView;
    ServiceConnection mConnection;
    PersonService.binder binder = null;
    private List<Person> mMsgs = new ArrayList<>();
    private IPersonManager mIMsgManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.tvtip);
        textView.setText(CharUtils.formatBoldChar("aaa","qwe"));
        init();
        //这就是开始aidl传数据的地方
        findViewById(R.id.btnAidl).setOnClickListener(view -> {
            try {
                mIMsgManager.sendPerson(new Person(10,"xiaoming"));
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        });
    }

    private void init(){
        mConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                mIMsgManager = IPersonManager.Stub.asInterface(iBinder);

                try {
                    mIMsgManager.asBinder().linkToDeath(mDeathRecipient, 0);
                    mIMsgManager.register(personListener);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName componentName) {

            }
        };

        Intent intent = new Intent();
        ComponentName componentName = new ComponentName("com.example.test","com.example.test.service.PersonService");
        intent.setComponent(componentName);
        bindService(intent, mConnection, BIND_AUTO_CREATE);//开启服务
    }

    private final PersonListener personListener = new PersonListener.Stub() {

        @Override
        public void onReceive(Person msg) throws RemoteException {
            Log.d("pjw",msg.toString());
        }
    };

    private final IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        //当承载IBinder的进程消失时接收回调的接口
        @Override
        public void binderDied() {
            if (null == mIMsgManager) {
                return;
            }
            mIMsgManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
            mIMsgManager = null;
        }
    };

    @Override
    protected void onDestroy() {
        //解除注册
        if (null != mIMsgManager && mIMsgManager.asBinder().isBinderAlive()) {
            try {
                mIMsgManager.unRegister(personListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        //解除绑定服务
        unbindService(mConnection);
        super.onDestroy();
    }

}

最后看一下项目的目录结构。

同一个包名不同进程的aidl就算完成啦。