Android通信のIPC-AIDL

7975 ワード

一例を用いて説明すると、まずクライアントがサービス側を呼び出す方法で書籍を追加し、その後、サービス側は5秒ごとに自分で新しい書籍を追加し、クライアントに通知する.
サービス側
クライアントに露出したこのインタフェースをこのAIDLファイルに宣言するAIDLファイルを作成し、まずクライアントの接続要求を傍受するためのServiceを作成し、このAIDLを実現すればよい.1.AIDLファイルを作成し、必要なメソッドを宣言します.以下に4つのメソッドを宣言します.中にはBookという類が使われているので、ガイドバッグを覚えておく必要があります.タイムリーに1つのバッグの下でガイドする必要があります.
// IBookManager.aidl
package com.demo.nick.ipcstudy;

// Declare any non-default types here with import statements
import com.demo.nick.ipcstudy.Book;
import com.demo.nick.ipcstudy.IOnNewBookArrivedListener;
interface IBookManager {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
     List getBookList();
     void addBook(in Book book);
     void registerListener(IOnNewBookArrivedListener listener);
     void unregisterListener(IOnNewBookArrivedListener listener);
}

リスニングを作成します.
package com.demo.nick.ipcstudy;

// Declare any non-default types here with import statements
import com.demo.nick.ipcstudy.Book;
interface IOnNewBookArrivedListener {
  void onNewBookArrived(in Book book);
}

2.サービスの作成
public class BookManagerService extends Service {
    private static final String TAG = "BookManagerService";
    private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList<>();//    
    //         beginBroadcast finishBroadcast      
   private RemoteCallbackList mListenerList=new RemoteCallbackList<>();
    private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);//       
//    private CopyOnWriteArrayList mListenerList = new CopyOnWriteArrayList<>();
    //         AIDL  
    private Binder mBinder = new IBookManager.Stub() {
        @Override
        public List getBookList() throws RemoteException {
            return mBookList;
        }

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

        @Override
        public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException {
//            if (!mListenerList.contains(listener)) {
//                mListenerList.add(listener);
//            }else {
//                Log.e(TAG, "already exists: " );
//            }
            mListenerList.register(listener);
            int a=mListenerList.beginBroadcast();
            Log.e(TAG, "        "+a );
            mListenerList.finishBroadcast();
//            Log.e(TAG, "registerListener     : "+mListenerList.size());
        }

        @Override
        public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException {
//       if(mListenerList.contains(listener)){
//           mListenerList.remove(listener);
//           Log.e(TAG, "    : " );
//       }else {
//           Log.e(TAG, "      : " );
//       }
//            Log.e(TAG, "        "+mListenerList.size() );
//        }
            mListenerList.unregister(listener);
            int a=mListenerList.beginBroadcast();
            Log.e(TAG, "        "+a );
            mListenerList.finishBroadcast();
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        mBookList.add(new Book(1, "android"));
        mBookList.add(new Book(2, "ios"));
        new Thread(new ServiceWorker()).start();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public void onDestroy() {
        mIsServiceDestoryed.set(true);
        super.onDestroy();
    }

    private void  onNewBookArrived(Book book) throws RemoteException {
        mBookList.add(book);
        final int N=mListenerList.beginBroadcast();
        for (int i=0;i

クライアント
サービス側のサービスをバインドし、サービス側から返されるBinderオブジェクトをAIDLインタフェースが属するタイプに変換することで、AIDLでメソッドを呼び出すことができます.
public class BookManagerAty extends AppCompatActivity {
    private static final String TAG = "BookManagerAty";
    private static final int MESSAGE_NEW_BOOK_ARRIVED=1;
    private IBookManager mRemoteBookManager;
    private Handler mHandler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MESSAGE_NEW_BOOK_ARRIVED:
                    Log.e(TAG, "new BOOK: "+msg.obj );
                break;
            default:
                super.handleMessage(msg);
            }

        }
    };
    private ServiceConnection mConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            IBookManager bookManager=IBookManager.Stub.asInterface(service);
            try {
                mRemoteBookManager=bookManager;
                List list=bookManager.getBookList();
                Log.e(TAG, "onServiceConnected: "+list.getClass().getCanonicalName());
                Log.e(TAG, "onServiceConnected: "+list.toString() );
                Book book=new Book(3,"java");
                bookManager.addBook(book);
                List newList=bookManager.getBookList();
                Log.e(TAG, "onServiceConnected: "+newList.toString() );
                bookManager.registerListener(mOnNewBookArrivedLisener);//    
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mRemoteBookManager=null;
            Log.e(TAG, "onServiceDisconnected: " );
        }
    };
    private IOnNewBookArrivedListener mOnNewBookArrivedLisener=new IOnNewBookArrivedListener.Stub() {
        @Override
        public void onNewBookArrived(Book book) throws RemoteException {
            mHandler.obtainMessage(MESSAGE_NEW_BOOK_ARRIVED,book).sendToTarget();
        }

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

    @Override
    protected void onDestroy() {
        if (mRemoteBookManager!=null&&mRemoteBookManager.asBinder().isBinderAlive()){
            Log.e(TAG, "onDestroy: "+mOnNewBookArrivedLisener );
            try {
                mRemoteBookManager.unregisterListener(mOnNewBookArrivedLisener);//    
            } catch (RemoteException e) {
                e.printStackTrace();
            }

        }
        unbindService(mConnection);
        super.onDestroy();
    }
}


この時点でリモート・サービスは誰でも接続できるので、権限認証を行い、Mainfestファイルで権限をカスタマイズします.
   

サービスのonBindメソッドを変更し、
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //    ,      ,            .
        int check=checkCallingOrSelfPermission("com.demo.nick.ipcstudy.permission.TEST");
        if (check== PackageManager.PERMISSION_DENIED){
            //       ,            。
            return null;
        }
        return mBinder;
    }