安卓IPC之AIDL的简单模型测试

1.android android PIC 进程间通信

PIC 进程间通信主要有这几种
1.bundle :
简单易用 但是只能传输Bundle支持的对象 常用于四大组件间进程间通信
2.文件共享:
简单易用 但不适合在高并发的情况下 并且读取文件需要时间 不能即时通信 常用于并发程度不高 并且实时性要求不高的情况
3.AIDL :
功能强大 支持一对多并发通信 支持即时通信 但是使用起来比其他的复杂 需要处理好多线程的同步问题 常用于一对多通信 且有RPC 需求的场合(服务端和客户端通信)
4.Messenger :
功能一般 支持一对多串行通信 支持实时通信 但是不能很好处理高并发情况 只能传输Bundle支持的类型 常用于低并发的无RPC需求一对多的场合
5.ContentProvider :
在数据源访问方面功能强大 支持一对多并发操作 可扩展call方法 可以理解为约束版的AIDL 提供CRUD操作和自定义函数 常用于一对多的数据共享场合
6.Socket :
功能强大 可以通过网络传输字节流 支持一对多并发操作 但是实现起来比较麻烦 不支持直接的RPC 常用于网络数据交换

2.AIDL知识

AIDL需要了解的知识,这一篇就够了。

Android:学习AIDL,这一篇文章就够了(上)_lypeer的博客-CSDN博客_aidl

3.服务端搭建

1.新建空项目

安卓IPC之AIDL的简单模型测试_第1张图片

 我这里取名为aidl4。

2.创建类,并implements Parcelable 

创建一个类,正常的书写其成员变量,建立getter和setter并添加一个无参构造

创建如下类:

public class Book{
    public String getName() {
        return name;
    }

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

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    private String name;

    private int price;

    public Book() {}

}

按下Alt+Insert,选择Palcelable,可以帮你生成以下代码。

package com.example.aidl4;

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

public class Book implements Parcelable {
    public String getName() {
        return name;
    }

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

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    private String name;

    private int price;

    public Book() {}

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

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

    public void readFromParcel(Parcel source) {
        this.name = source.readString();
        this.price = source.readInt();
    }

    protected Book(Parcel in) {
        this.name = in.readString();
        this.price = in.readInt();
    }

    //方便打印数据
    @Override
    public String toString() {
        return "name : " + name + " , price : " + price;
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        @Override
        public Book createFromParcel(Parcel source) {
            return new Book(source);
        }

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

这里要手动添加 toString()。

注意,如果你没有安装Palcelable插件,可以直接在线安装。方法是:

打开File -> Settings -> Pugins -> Browse Repositories 如下,输入 android parcelable code generator :

3.书写AIDL文件

src目录右击选择new->AIDL,制作两份AIDL文件。

// Book.aidl
//第一类AIDL文件
//这个文件的作用是引入了一个序列化对象 Book 供其他的AIDL文件使用
//注意:Book.aidl与Book.java的包名应当是一样的
package com.example.aidl4;

//注意parcelable是小写
parcelable Book;
// BookManager.aidl
//第二类AIDL文件
//作用是定义方法接口
package com.example.aidl4;

//导入所需要使用的非默认支持数据类型的包
import com.example.aidl4.Book;

interface BookManager {

    //所有的返回值前都不需要加任何东西,不管是什么数据类型
    List getBooks();

    //传参时除了Java基本类型以及String,CharSequence之外的类型
    //都需要在前面加上定向tag,具体加什么量需而定
    void addBook(in Book book);
}

4.修改 build.gradle 文件

修改 build.gradle 文件:在 android{} 中间加上下面的内容:

sourceSets {
    main {
        java.srcDirs = ['src/main/java', 'src/main/aidl']
    }
}

点击build->rebuild project ,检查无报错

5.编写服务端代码 AIDLService.java

package com.example.aidl4;

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

import androidx.annotation.Nullable;

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

/**
 * 服务端的AIDLService.java
 * 

* Created by lypeer on 2016/7/17. */ public class AIDLService extends Service { public final String TAG = this.getClass().getSimpleName(); //包含Book对象的list private List mBooks = new ArrayList<>(); //由AIDL文件生成的BookManager private final BookManager.Stub mBookManager = new BookManager.Stub() { @Override public List getBooks() throws RemoteException { synchronized (this) { Log.e(TAG, "invoking getBooks() method , now the list is : " + mBooks.toString()); if (mBooks != null) { return mBooks; } return new ArrayList<>(); } } @Override public void addBook(Book book) throws RemoteException { synchronized (this) { if (mBooks == null) { mBooks = new ArrayList<>(); } if (book == null) { Log.e(TAG, "Book is null in In"); book = new Book(); } //尝试修改book的参数,主要是为了观察其到客户端的反馈 book.setPrice(2333); if (!mBooks.contains(book)) { mBooks.add(book); } //打印mBooks列表,观察客户端传过来的值 Log.e(TAG, "invoking addBooks() method , now the list is : " + mBooks.toString()); } } }; @Override public void onCreate() { super.onCreate(); Book book = new Book(); book.setName("Android开发艺术探索"); book.setPrice(20220607); mBooks.add(book); } @Nullable @Override public IBinder onBind(Intent intent) { Log.e(getClass().getSimpleName(), String.format("on bind,intent = %s", intent.toString())); return mBookManager; } }

6.Manefest 文件里面注册Service 

修改从内容。




    
        
            
                
                
            

        
            
                

                
            
        
    

7.检查确认服务端整体结构

检查确认服务端整体结构是否如下图:

安卓IPC之AIDL的简单模型测试_第2张图片

4.客户端搭建

1.新建空项目,命名aidl5

安卓IPC之AIDL的简单模型测试_第3张图片

2.拷贝aidl文件

安卓IPC之AIDL的简单模型测试_第4张图片

 注意,是原封不动的拷贝aidl目录所有内容。

3.编写客户端代码

修改MainActivity

package com.example.aidl5;

import androidx.appcompat.app.AppCompatActivity;

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.util.Log;
import android.view.View;
import android.widget.Toast;

import com.example.aidl4.Book;
import com.example.aidl4.BookManager;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    //由AIDL文件生成的Java类
    private BookManager mBookManager = null;

    //标志当前与服务端连接状况的布尔值,false为未连接,true为连接中
    private boolean mBound = false;

    //包含Book对象的list
    private List mBooks;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_aidl);
        setContentView(R.layout.activity_main);
        if (!mBound) {
            attemptToBindService();
            Log.w("harry","当前与服务端处于未连接状态,正在尝试重连,请稍后再试");
            Toast.makeText(this, "harry 当前与服务端处于未连接状态,正在尝试重连,请稍后再试", Toast.LENGTH_SHORT).show();
            return;
        }
        if (mBookManager == null) return;

        Book book = new Book();
        book.setName("APP研发录In");
        book.setPrice(30);
        try {
            mBookManager.addBook(book);
            Log.e(getLocalClassName(), book.toString());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
     * 按钮的点击事件,点击之后调用服务端的addBookIn方法
     *
     * @param view
     */
    public void addBook(View view) {
        //如果与服务端的连接处于未连接状态,则尝试连接
        if (!mBound) {
            attemptToBindService();
            Log.i("harry","no当前与服务端处于未连接状态,正在尝试重连,请稍后再试");
            Toast.makeText(this, "当前与服务端处于未连接状态,正在尝试重连,请稍后再试", Toast.LENGTH_SHORT).show();
            return;
        }
        if (mBookManager == null) return;

        Book book = new Book();
        book.setName("APP研发录In");
        book.setPrice(30);
        try {
            mBookManager.addBook(book);
            Log.e(getLocalClassName(), book.toString());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    /**
     * 尝试与服务端建立连接
     */
    private void attemptToBindService() {
        Log.i("harry","enter attemptToBindService");
        Intent intent = new Intent();
        intent.setAction("com.example.aidl4.ALDLService");
        intent.setPackage("com.example.aidl4");
        Log.i("harry","in attemptToBindService,"+ intent);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (!mBound) {
            attemptToBindService();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            unbindService(mServiceConnection);
            mBound = false;
        }
    }

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("harry","enter onServiceConnection");
            Log.e(getLocalClassName(), "service connected");
            mBookManager = BookManager.Stub.asInterface(service);
            Log.i("harry","got mBookManager");
            mBound = true;

            if (mBookManager != null) {
                Log.i("harry","mBookManager is not null");
                try {
                    mBooks = mBookManager.getBooks();
                    Log.i("harry","after getBooks");
                    Log.e(getLocalClassName(), mBooks.toString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("harry","enter onServiceDisConnection");
            Log.e(getLocalClassName(), "service disconnected");
            mBound = false;
        }
    };
}

5.测试

在安卓设备上安装两个app,先启动aidl4服务端,再启动aidl5客户端。观察日志:

aidl5客户端:

安卓IPC之AIDL的简单模型测试_第5张图片

 aidl4服务端

 测试成功。

6.总结

实践出真知,看懂了不如调通了。

你可能感兴趣的:(code,design,test,android,网络,AIDL,IPC)