AIDL代碼舉例

AIDL代碼舉例

  • 補充IPC機制學習中AIDL使用的實例代碼。學習筆記正文
  • 實現的是客戶端與服務端之間的跨進程通信及RPC調用,還有服務端對客戶端的定時通知。

1.對象類及AIDL文件

  • Person.java

    public class Person implements Parcelable {
        public String pName;
        public int pAge;
    
        public Person(String pName, int pAge) {
            this.pName = pName;
            this.pAge = pAge;
        }
    
        protected Person(Parcel in) {
            pName = in.readString();
            pAge = in.readInt();
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(pName);
            dest.writeInt(pAge);
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        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];
            }
        };
    }
    
  • Person.aidl

    // Person.aidl
    package com.virtual.aidltest;
    
    //Person類在AIDL中的聲明
    parcelable Person;
    
  • IPersonManager.aidl

    // IPersonManager.aidl
    package com.virtual.aidltest;
    import com.virtual.aidltest.Person;
    import com.virtual.aidltest.IOnNewPersonArrivedListener;
    
    interface IPersonManager {
        List<Person> getPersonList();
        void addPerson(in Person person);
        void registerListener(IOnNewPersonArrivedListener listener);
        void unregisterListener(IOnNewPersonArrivedListener listener);
    }
    
  • IOnNewBookArrivedListener.aidl

    // IOnNewBookArrivedListener.aidl
    package com.virtual.aidltest;
    import com.virtual.aidltest.Person;
    
    interface IOnNewPersonArrivedListener {
        void onNewPersonArrived(in Person newPerson);
    }
    

2.服務端

  • PersonManagerService.java

    public class PersonManagerService extends Service {
        private static final String TAG = "PersonManagerService";
        /**
         * 併發情況下使用AtomicBoolean
         */
        private AtomicBoolean mIsServiceDestroyed = new AtomicBoolean(false);
        /**
         * 1.AIDL方法是在服務端的Binder線程池中執行的,多客戶端同時連接時,會存在多線程同時訪問的情況。
         * 2.CopyOnWriteArrayList支持併發讀/寫。
         * 3.我們要在AIDL方法中處理線程同步,可以使用CopyOnWriteArrayList進行自動線程同步。
         */
        private CopyOnWriteArrayList<Person> mPersonList = new CopyOnWriteArrayList<>();
        /**
         * RemoteCallbackList是系統專門提供用於刪除跨進程listener的接口。
         */
        private RemoteCallbackList<IOnNewPersonArrivedListener> mListenerList = new RemoteCallbackList<>();
    
        private Binder mBinder = new IPersonManager.Stub() {
    
            @Override
            public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
                int check = checkCallingOrSelfPermission("com.virtual.aidltest.ACCESS_PERSON_SERVICE");
                if (check == PackageManager.PERMISSION_DENIED) {
                    return false;
                }
                String packageName = null;
                String[] packages = getPackageManager().getPackagesForUid(getCallingUid());
                if (packages != null && packages.length > 0) {
                    packageName = packages[0];
                }
                if (!packageName.startsWith("com.virtual")) {
                    return false;
                }
                return super.onTransact(code, data, reply, flags);
            }
    
            @Override
            public List<Person> getPersonList() throws RemoteException {
                return mPersonList;
            }
    
            @Override
            public void addPerson(Person person) throws RemoteException {
                mPersonList.add(person);
            }
    
            @Override
            public void registerListener(IOnNewPersonArrivedListener listener) throws RemoteException {
                mListenerList.register(listener);
            }
    
            @Override
            public void unregisterListener(IOnNewPersonArrivedListener listener) throws RemoteException {
                mListenerList.unregister(listener);
            }
        };
    
    
        @Override
        public void onCreate() {
            super.onCreate();
            //先添加兩個人員對象
            mPersonList.add(new Person("Tim", 31));
            mPersonList.add(new Person("Jack", 11));
            /**
             * 每隔5s添加一個新用戶,並通知所有綁定的客戶端
             */
            new Thread(new ServiceWorker()).start();
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        @Override
        public void onDestroy() {
            mIsServiceDestroyed.set(true);
            super.onDestroy();
        }
    
        private class ServiceWorker implements Runnable {
            @Override
            public void run() {
                while (!mIsServiceDestroyed.get()) {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Person newPerson = new Person("Kim", 11);
                    try {
                        onNewPersonArrived(newPerson);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        private void onNewPersonArrived(Person person) throws RemoteException {
            mPersonList.add(person);
            final int N = mListenerList.beginBroadcast();
            Log.d(TAG, "onNewPersonArrived, notify listeners: " + N);
            for (int i = 0; i < N; i++) {
                IOnNewPersonArrivedListener listener = mListenerList.getBroadcastItem(i);
                Log.d(TAG, "onNewPersonArrived, notify listener: " + listener);
                listener.onNewPersonArrived(person);
            }
            //與beginBroadcast匹配對應
            mListenerList.finishBroadcast();
        }
    }
    

3.客戶端

  • PersonManagerActivity.java

    public class PersonManagerActivity extends AppCompatActivity {
    
        private static final String TAG = "PersonManagerActivity";
        private static final int MESSAGE_NEW_PERSON_ARRIVED = 1;
        private IPersonManager mRemotePersonManager;
    
        private Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MESSAGE_NEW_PERSON_ARRIVED:
                        Log.d(TAG, "receive new person: " + msg.obj);
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        };
    
        private ServiceConnection mConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                IPersonManager personManager = IPersonManager.Stub.asInterface(service);
                try {
                    //查找
                    mRemotePersonManager=personManager;
                    List<Person> lsit = personManager.getPersonList();
                    Log.d(TAG, "querry person list, list type: " + lsit.getClass());
                    Log.d(TAG, "querry person list: " + lsit.get(0).pName);
                    //添加
                    Person newPerson = new Person("Kit", 16);
                    personManager.addPerson(newPerson);
                    Log.d(TAG, "add new person! "+newPerson);
                    //再次查看
                    List<Person> newLsit = personManager.getPersonList();
                    Log.d(TAG, "querry person list 2nd, list type: " + lsit.getClass());
                    personManager.registerListener(mOnNewPersonArrivedListener);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mRemotePersonManager=null;
                Log.d(TAG, "binder died!");
            }
        };
    
        private IOnNewPersonArrivedListener mOnNewPersonArrivedListener = new IOnNewPersonArrivedListener.Stub() {
            @Override
            public void onNewPersonArrived(Person newPerson) throws RemoteException {
                mHandler.obtainMessage(MESSAGE_NEW_PERSON_ARRIVED,newPerson).sendToTarget();
            }
        };
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_messenger);
            Intent intent = new Intent(this, PersonManagerService.class);
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onDestroy() {
            if(mRemotePersonManager!=null && mRemotePersonManager.asBinder().isBinderAlive()){
                try {
                    Log.d(TAG, "unregister listener: "+mOnNewPersonArrivedListener);
                    mRemotePersonManager.unregisterListener(mOnNewPersonArrivedListener);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
            unbindService(mConnection);
            super.onDestroy();
        }
    }
    

4.AndroidManifest

  • 服務端註冊:

    <service android:name=".PersonManagerService"
             android:enabled="true"
             android:exported="true"
             android:process=":remote"/>
    
  • 客戶端註冊:

     <activity android:name=".PersonManagerActivity"/>
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章