Android基础知识之AIDL基本使用(实现两个进程间的通信)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/c_he_n/article/details/84562287

AIDL(Android Interface Definition Language)是Android系统自定义的接口描述语言。可以用来实现进程间的通讯。

如何生成AIDL

通过file->new->aidl,来生成像对应的.aidl对应的文件,本文要实现两个不同的app通信。要想实现两个app的通信,那么就要实现app同样的接口。要完全一样,什么意思呢?里面的代码要完全一样。

  • 客户端:ITestAIDL.aidl文件
// ITestAIDL.aidl
package iflytek.com.clientcode;//服务端和客户端也要一样

// Declare any non-default types here with import statements

interface ITestAIDL {
 void addBook(in String book);
 List<String> getBookList();
}
  • 服务端:ITestAIDL.aidl文件
// ITestAIDL.aidl
package iflytek.com.clientcode; //服务端和客户端也要一样

// Declare any non-default types here with import statements

interface ITestAIDL {
 void addBook(in String book);
 List<String> getBookList();
}

两者的代码也要完全一摸一样,包括package ,若是package不一样,会报错,可以通过新建包名的方式来实现package一样。如下图:左边时服务端,右边客户端
在这里插入图片描述
若两端的代码不一致,会出现下面的错误:

Binder invocation to an incorrect interface 

AIDL 支持下列数据类型:

  • Java 编程语言中的所有原语类型(如 int、long、char、boolean 等等)
  • String
  • CharSequence
  • List
  • List 中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 可选择将 List 用作“通用”类(例如,List)。另一端实际接收的具体类始终是 ArrayList,但生成的方法使用的是 List 接口。
  • Map
    Map 中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 不支持通用 Map(如 Map<String,Integer> 形式的 Map)。 另一端实际接收的具体类始终是 HashMap,但生成的方法使用的是 Map 接口。

这些数据类型可能无法满足我们的要求,我们需要出书更复杂的数据,如何定义这些数据呢?需要两步:
1.在对应的package路径下model,这个model就是我服务端和客户端要传输的数据,并继承Parcelable,如下:

package iflytek.com.clientcode;

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

public class Book implements Parcelable {
    private String name;

    public String getName() {
        return name;
    }

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

    public Book(String name) {

        this.name = name;
    }

    protected Book(Parcel in) {
    }


    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
    }
}

2.这是需要重新定义一个aidl,名字为IBookAIDL.aidl,删除里面的数据,处理package那行,如下图

// IBookAIDL.aidl
package iflytek.com.clientcode;

// Declare any non-default types here with import statements

parcelable Book;

实现

客服端代码

public class MainActivity extends AppCompatActivity {
    private ITestAIDL iTestAIDL;
    private boolean connected;
    private List<String> bookList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bindService();
        setContentView(R.layout.activity_main);
        TextView textView = findViewById(R.id.hello_world);
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    iTestAIDL.addBook("书籍");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iTestAIDL = ITestAIDL.Stub.asInterface(service);
            connected = true;
            Toast.makeText(getApplicationContext(), "绑定成功!+true", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            connected = false;
            Toast.makeText(getApplicationContext(), "绑定成功!+false" + name, Toast.LENGTH_SHORT).show();
            Log.i("haochen", name + "被杀死");
            bindService();
        }
    };

服务端代码:

public class MyService extends Service {
    private List<String> books;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        books = new ArrayList<>();
        return iBinder;
    }

    private IBinder iBinder = new ITestAIDL.Stub() {
        @Override
        public void addBook(String book) throws RemoteException {
            books.add(book);
            Log.i("haochen", "msg" + book);
        }

        @Override
        public List<String> getBookList() throws RemoteException {

            Toast.makeText(getApplicationContext(), "server get", Toast.LENGTH_SHORT).show();
            return books;
        }
    };

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}

值得注意是再生成服务端和客户端的aidl文件时,代码要完全一样,包的路径也要完全一样,否则会包上面的错误。
githubDemo代码

猜你喜欢

转载自blog.csdn.net/c_he_n/article/details/84562287