Days24 Service(二)

概念:
在Android中,每個程序都有自己的進程,當需要在不同的進程間傳遞對象時,該如何實現呢?
Java中不支持跨進程內存共享,因此要傳遞對象,需要把對象解析成操作系統能夠理解的數據模式,以達到跨界對象訪問的目的。這就是遠程程序調用RPC.
RPC (Remote Procedure Call)遠程程序調用
在Android中RPC的解決方案是通過AIDL方式來實現
Activity、Broadcast、ContentProvider、Service都可以實現跨進程的訪問
IPC (Inter-Progress Communication)內部進程通信
什麼是AIDL?
(Android Interface Definition Language)它是一種Android內部進程通信接口的描述語言,通過它定義進程間的通信接口,實現進程間通信。
AIDL實現RPC步驟:
1、在服務器端新增ICounter.aidl後綴的文件,裏面的內容爲接口的定義,注意:接口定義和方法定義都不能顯式指定修飾符
2、該aidl文件會被自動編譯生成一個ICounter.java文件,其中包含一個靜態內部類Stub(Stub類繼承Binder類)和方法asInterface(方法的返回值爲ICounter實例,方法的參數爲IBinder
3、在服務器端新增Service,該service的onBind()方法的返回值爲new ICounter.Stub(){public int getNum()},在該匿名內部類中實現getNum()方法
4、需要註冊該服務,並指定action(sign)
5、在客戶端要新增一個與服務器端完全一致的aidl文件,系統會自動生成與服務器端一樣的ICounter.java文件。
6、在Acitivity中以綁定的方式啓動服務,其中第一個參數Intent的action爲之前服務註冊的action(sign),ServiceConnection()實現類的onServiceConnected()方法中通過ICounter.Stub.asInterface(IBinder)來獲得ICounter實例
7、通過ICounter的實例調用getNum()方法,就可以在Activity中得到ICounter的getNum()方法的返回值。

案例三:
activity與service之間通過Binder對象的onTransact方法進行數據傳遞。
備註:當客戶端執行了transact方法時,就會回調對應的遠程Binder對象的onTransact方法。其中code是用來區分當前客戶端所調用的方法,data是輸入參數,這個參數不能爲NULL,即使你不需要傳遞任何參數你也應該傳遞一個空的Parcel對象。reply是含有遠程客戶端執行接口的Parcel對象,flags是附加的執行遠程操作的標誌,0表示正常的遠程調用,1表示不需要返回值的one-way調用。
MainActivity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = new Intent(this,MyService.class);

        bindService(intent,new MyConn(),BIND_AUTO_CREATE);
    }

    class MyConn implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            MyService.MyBinder binder = (MyService.MyBinder) iBinder;

//          獲得一個新的Parcel,相當於new一個對象
            Parcel data = Parcel.obtain();
            data.writeString("我是你的客戶端");

            Parcel reply = Parcel.obtain();

            try {
                binder.transact(Binder.FIRST_CALL_TRANSACTION,data,reply,0);

                String replyString = reply.readString();
                Log.d("test1","從服務端來的數據====reply======"+replyString);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    }
}

Service:

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }

    class MyBinder extends Binder{

        /**
         *Parcel 容器,用來存放數據,用Binder對象進行數據的傳遞
         *          data 從activity中過來的數據
         *          reply  service到activity的回覆
         */
        @Override
        protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {

            String dataString = data.readString();
            Log.d("test2","從客戶端來的數據------data--------"+dataString);

            reply.writeString("我是你的服務端");

            return super.onTransact(code, data, reply, flags);
        }
    }
}
發佈了12 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章