跨进程通讯之AIDL-----不同应用程序之间跨进程

AIDL,通俗来说就是两个Android应用要进行通信,且不能通过网络云服务器的方式进行数据交互,只能调用本地函数库的机制来实现,这时Android系统提供AIDL的机制来实现Android的跨进程通讯(用户进程之间是相对封闭的,无法直接访问数据)。

我们先不管任何原理,把demo跑出来再说其他的:
准备材料:一个Service、一个Client、连接S—C的桥梁(AIDL文件)
第一步: 连接S—C的桥梁(AIDL文件),这个aidl文件是客户端和服务器端都需要的,在服务端或者客户端的项目中生成都可以,如果传递基本数据类型就直接使用,如果是引用数据类型,先声明这个实体类,项目包结构如下在这里插入图片描述
①Person类中主要是实现Parcelable接口,代码如下

package com.testaidl.model;

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

/**
 * Created by Administrator on 2018\10\31 0031.
 */

public class Person implements Parcelable {
    private String name;

    protected Person(Parcel in) {
        name = in.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];
        }
    };

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


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

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

    @Override
    public String toString() {
        return "Person{" +
                "mName='" + this.getName() + '\'' +
                '}';
    }
}

②然后再项目的main结构下创建aidl文件夹,创建Person的aidl后缀文件,必须要和上面Person的包名(结构)相同,在这里插入图片描述这个Person类很简单就是声明一下parcelable 接口,
③IMyAidl这个接口的方法是提供给C-S调用的,

// IMyAidl.aidl
package com.testaidl;

// 这个引用类型必须是全类名的才能使用
import com.testaidl.model.Person;

interface IMyAidl {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    void addPerson(in Person person);
    List<Person> getPersonList();
}

这样子,AIDL这个中间件就做好了,把它分别放到代表:客户端和服务器项目中(例如我们在客户端的项目中生成AIDL文件,然后copy给服务器,但是要注意包名必须完全一致,C-S两端都要一致的,有点童鞋会说我想将客户端或者服务端放到之前的项目中,这时包名是定好的,不方便修改怎么办,在与当前包名同级的地方创建Person类,这样就保证了C-S两端包名都是一致的)

第二部:创建服务端,在新的项目中copyAIDL文件(放到项目中main结构的aidl文件夹中),一定要注意包名相同!!!,然后在完全相同的包结构下复制Person这个实体类,编译一下程序,服务端其实就是Android四大组件中的Service,

package com.my_project.test_aidl;

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

import com.testaidl.IMyAidl;
import com.testaidl.model.Person;

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

/**
 * Created by Administrator on 2018\10\31 0031.
 * 服务端 service
 */

public class MyAidlService extends Service {
    private final String TAG = this.getClass().getSimpleName();
    public ArrayList<Person> mPersons;
    /**
     * 创建生成的本地 Binder 对象,实现 AIDL 制定的方法
     */
    private IBinder mIBinder = new IMyAidl.Stub() {
        @Override
        public void addPerson(Person person) throws RemoteException {
            Log.e("11111111111",person.toString());
            mPersons.add(person);
        }

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

        }

        @Override
        public List<Person> getPersonList() throws RemoteException {
            return mPersons;
        }
    };

    /**
     * 客户端与服务端绑定时的回调,返回 mIBinder 后客户端就可以通过它远程调用服务端的方法,即实现了通讯
     *
     * @param intent
     * @return
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        mPersons = new ArrayList<>();
        Log.e(TAG, "MyAidlService onBind");
        return mIBinder;
    }

}

然后咱们再清单文件中声明service的时候要设置其action(这个名字可以随意取的):在这里插入图片描述
第三步:创建客户端项目:同样的方式copyAIDL文件和Person实体类,这个是和服务端一样的,然后编译生成Stub,做好准备工作以后,在客户端上绑定这个服务,bingService(…)

package com.testaidl;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.testaidl.model.Person;

import java.util.List;
import java.util.Random;

/**
 * 客户端client  代码
 * */
public class MainActivity extends AppCompatActivity {

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

        Intent intent1 = new Intent();
        intent1.setPackage("com.my_project");
        intent1.setAction("com.test_aidl.aidl");
        bindService(intent1, mConnection, BIND_AUTO_CREATE);


        final Button btn_test = findViewById(R.id.btn_test);
        final TextView tv_test = findViewById(R.id.tv_test);
        btn_test.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Random random = new Random();
                Person person = new Person("shixin" + random.nextInt(10));
                try {
                    mAidl.addPerson(person);
                    List<Person> personList = mAidl.getPersonList();
                    tv_test.setText(personList.toString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private IMyAidl mAidl;
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //连接后拿到 Binder,转换成 AIDL,在不同进程会返回个代理
            mAidl = IMyAidl.Stub.asInterface(service);
        }

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

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

这样客户端生成好了,可以通过客户端发消息给服务端,亲测服务端可以收到消息
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章