Android IPC进程间通信(四)AIDL

AIDL-Android接口定义语言

一·
1.相比于Messenger AIDL可跨进程调用方法。
2.支持数据类型:
(1) Java 的原生基本类型(int, long, char, boolean, double等)
(2)String 和CharSequence
(3) ArrayList 和 HashMap ,里面的元素必须是AIDL支持的数据类型; 以上三种类型都不需要导入(import)
(4) AIDL 自动生成的接口 需要导入(import)
(5) 实现android.os.Parcelable 接口的类. 需要导入(import)
3.除了Java 的原生基本类型其他类型参数都需标明方向:in 输入 , out 输出, inout 出入输出。
4.建议吧所有一AIDL相关文件放在同一个文件夹下,方便复制到客户端,而且服务端可客户端AIDL包结构需保持一致,否则 无法反序列化成功
5.优点:功能强大,支持一对多并发通信,支持即时通信。
缺点:稍复杂,需做好线程同步。
使用场景:一对多且有RPC-远程方法调用 需求。
二,RemoteCallbackList系统用于管理跨进程listener,支持管理任意的AIDL

public class RemoteCallbackList<E extends IInterfaxc>

内部提供一个Map来管理这些AIDL,key为IBinder,value为Callback

ArrayMap<IBinder,Callback> mCallbacks = new ArrayMap<>();

当客户端注册listener时,Callback将listener的信息以IBinder为key存入mCallbacks,删除时也是找到此key对应的listener进行删除,因为跨进程生成的是相同的两个对象
三,创建AIDL文件,此代码复制粘贴即可顺利运行
1.创建Book类,IPC进程间通信(三)中已讲解,此处再创建一个aidl接口IOnNewBookArriveListener.aidl用于订阅书籍,同样会生成它自己的java类

package com.songfeng.aidlautocreate;
// Declare any non-default types here with import statements
//自定义类都需要显示的引入进来
import com.songfeng.aidlautocreate.Book;
//提供一个监听新书到达的接口
interface IOnNewBookArriveListener {
    void onNewBookArrived(in Book book);
}

2.在IBookManger.aidl接口中增加注册和解注册方法,用于被远程调用,以实现某种功能

// IBookManager.aidl
package com.songfeng.aidlautocreate;

// Declare any non-default types here with import statements
import com.songfeng.aidlautocreate.Book;
import com.songfeng.aidlautocreate.IOnNewBookArriveListener;

interface IBookManager {

    List<Book> getBookList();
    void addBook(in Book book);
    void registerLister(IOnNewBookArriveListener listener);
    void unRegisterLister(IOnNewBookArriveListener listener);
}

3.创建BookManagerService用于管理AIDL文件,在其中实现Binder,并返回给客户端,以便在客户端调用Binder中的方法。

public class BookManagerService extends Service {

    private static final String TAG = "BookManagerService";
    private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList();
    //注册和解注册多进程中的监听方法
    private RemoteCallbackList mListenerList = new RemoteCallbackList();

    @Override
    public void onCreate() {
        super.onCreate();
        new Thread(new arrivedBookRunnable()).start();
    }
    //自动生成的java类,创建Binder,重写其方法,实现逻辑
    private IBookManager.Stub mBinder = new IBookManager.Stub() {
        @Override
        public List<Book> getBookList() throws RemoteException {
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            if (!mBookList.contains(book)){
                mBookList.add(book);
            }
        }

        @Override
        public void registerLister(IOnNewBookArriveListener listener) throws RemoteException {
                mListenerList.register(listener);
        }

        @Override
        public void unRegisterLister(IOnNewBookArriveListener listener) throws RemoteException {
            mListenerList.unregister(listener);
        }
    };
	//在这进行一个权限验证,只有客户端注册了此自定义权限才返回Binder给客户端
    @Override
    public IBinder onBind(Intent intent) {
       int check = checkCallingOrSelfPermission("com.songfeng.aidlautocreate.permission.BookManagerService");
       if (check == PackageManager.PERMISSION_DENIED){
            return null;
       }
        return mBinder;
    }

    /**
     * 开启线程每5秒添加一本新书并通知每一个注册了注册了监听方法的客户端
     */
    private class arrivedBookRunnable implements Runnable{
        @Override
        public void run() {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int bookId = mBookList.size() + 1;
            Book newBook = new Book(bookId,"Android : " + bookId);
            //新书到达,启动通知
            oOnNewBookArrived(newBook);
        }
    }

    /**
     * 通知每一个注册可监听方法IOnNewBookArriveListener的客户端,并回调到客户端的onNewBookArrived()
     * @param newBook
     */
    private void oOnNewBookArrived(Book newBook){
        int N = mListenerList.beginBroadcast();
        for (int i = 0; i < N; i++) {
            IOnNewBookArriveListener listener =(IOnNewBookArriveListener) mListenerList.getBroadcastItem(i);
            try {
                listener.onNewBookArrived(newBook);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        mListenerList.finishBroadcast();
    }
}

4.在客户端的连接方法中获取Binder,即可调用Binder中方法

public class MainActivity extends AppCompatActivity {


    private static final String TAG = "MainActivity";

    private static final int MSG_BOOK_ARRIVED = 1;
    //自定义的AID文件,里面是一个接口
    private IBookManager mIBookManager;
    private List<Book> mBookList;
    private MyHandler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandler = new MyHandler();
        Intent intent = new Intent(MainActivity.this, BookManagerService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private class MyHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_BOOK_ARRIVED:
                    Book book = (Book) msg.obj;
                    Toast.makeText(MainActivity.this, "新书 ID:"
                            + book.getBookId() + ", 书名 :" + book.getBookName()
                            + "已到达。", Toast.LENGTH_SHORT).show();
                default:
                    break;
            }
        }
    }

    /**
     * 监听图书到达,当服务调用新书到达的方法时就会回调到此方法
     */
    private IOnNewBookArriveListener mBookArriveListener = new IOnNewBookArriveListener.Stub() {
        @Override
        public void onNewBookArrived(Book book) throws RemoteException {
            mHandler.obtainMessage(MSG_BOOK_ARRIVED, book).sendToTarget();
        }
    };

    /**
     * 从服务中取出IBinder创建IBookManager
     * public static com.songfeng.aidlautocreate.IBookManager asInterface(android.os.IBinder obj)
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            IBookManager bookManager = IBookManager.Stub.asInterface(iBinder);
            try {
                Toast.makeText(MainActivity.this, "链接服务器成功", Toast.LENGTH_SHORT).show();
                mIBookManager = bookManager;
                mBookList = bookManager.getBookList();
                Log.d(TAG, "BookList.size :" + mBookList.size());
                //注册监听
                bookManager.registerLister(mBookArriveListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Toast.makeText(MainActivity.this, "服务器已断开,重连中...", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(MainActivity.this, BookManagerService.class);
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mIBookManager != null && mIBookManager.asBinder().isBinderAlive()) {
            try {
                mIBookManager.unRegisterLister(mBookArriveListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            unbindService(mConnection);
        }
    }
}

5.AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
. .  .  .   .
        <service
            android:name=".BookManagerService"
            android:enabled="true"
            android:exported="true"
            android:process=":remote">
        </service>
</manifest>

猜你喜欢

转载自blog.csdn.net/qq_39507260/article/details/83662817