天天看點

aidl ( 一 ) activity擷取背景service資料AIDL對Java類型的支援如下:注意事項例子

在  service和activity通信這篇文章的基礎上,我們再來學習aidl。

aidl是android跨程序通信的常用方法

AIDL對Java類型的支援如下:

1.AIDL支援Java原始資料類型。

2.AIDL支援String和CharSequence。

3.AIDL支援傳遞其他AIDL接口,但你引用的每個AIDL接口都需要一個import語句,即使位于同一個包中。

4.AIDL支援傳遞實作了android.os.Parcelable接口的複雜類型,同樣在引用這些類型時也需要import語句。(Parcelable接口告訴Android運作時在封送(marshalling)和解封送(unmarshalling)過程中實作如何序列化和反序列化對象,你可以很容易聯想到java.io.Serializable接口。有些朋友可能會有疑問,兩種接口功能确實類似,但為什麼Android不用内置的Java序列化機制,而偏偏要搞一套新東西呢?這是因為Android團隊認為Java中的序列化太慢,難以滿足Android的程序間通信需求,是以他們建構了Parcelable解決方案。Parcelable要求顯示序列化類的成員,但最終序列化對象的速度将快很多。另外要注意的是,Android提供了兩種機制來将資料傳遞給另一個程序,第一種是使用Intent将資料束(Bundle)傳遞給活動,第二種也就是Parcelable傳遞給服務。這兩種機制不可互換,不要混淆。也就是說,Parcelable無法傳遞給活動,隻能用作AIDL定義的一部分)。

5.AIDL支援java.util.List和java.util.Map,但是有一些限制。集合中項的允許資料類型包括Java原始類型、String、CharSequence或是android.os.Parcelable。無需為List和Map提供import語句,但需要為Parcelable提供import語句。

6.非原始類型中,除了String和CharSequence以外,其餘均需要一個方向訓示符。方向訓示符包括in、out、和inout。in表示由用戶端設定,out表示由服務端設定,inout表示用戶端和服務端都設定了該值。預設類型其實隐含了一個預設訓示符in

參考自http://blog.csdn.net/liuhe688/article/details/6409708

注意事項

1、oneway關鍵字在跨程序調用的時候使得調用不阻塞,直接傳回。在同一個程序内,oneway沒有任何意義。

2、aidl檔案可以引用aidl檔案,但不能引用java檔案。是以有時候我們想要在程序間傳輸某個對象,比如BaseData,首先要BaseData實作parceble,寫一個java檔案,然後在同樣的目錄下寫個同名aidl檔案,并注明parceble BaseData作為定義,然後其他aidl檔案才能引用BaseData,可參考http://blog.csdn.net/dangnianmingyue_gg/article/details/48197293 内的PayClass。

例子

activity擷取service資料關鍵連接配接點是onServiceConnected

首先寫服務端的app:  AidlServer

這裡我們建立一個Service類MyService,在MyService中放1個計時器

public void onCreate() {
        super.onCreate();
        String TAG="";
        LogFish.d("onCreate process name " + SystemUtil.getCurProcessName(MyService.this));
        Log.i(TAG, "Service is Created");
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 每間隔0.1秒count加1 ,直到quit為true
                while (!quit) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                }
            }
        });
        thread.start();
    }
           

編寫aidl接口,getCount用來擷取service的資料,complexCal用來做複雜計算,注意這裡是跨程序的

interface IMyAidlInterface {
	int getCount();
	double complexCal(String str,int t);
}
           

service中的binder重寫aidl接口方法

IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {

        @Override
        public int getCount() throws RemoteException {
            return count;
        }

        @Override
        public double complexCal(String str, int t) throws RemoteException {
            int  ret=str.hashCode()+t;
            return ret*0.3;
        }
    };
           

manifest中的MyService配置如下

<service
            android:name=".MyService"
            android:process="com.myservice">
            <intent-filter>
                <action android:name="com.example.servicetest.MyAIDLService" />
            </intent-filter>
        </service>
           

檔案目錄如下:

aidl ( 一 ) activity擷取背景service資料AIDL對Java類型的支援如下:注意事項例子

再編寫用戶端app:AidlClient

首先在同樣目錄下,放一模一樣的aidl檔案

再編寫activity檔案,代碼如下

public class MainActivity extends Activity implements View.OnClickListener {

    private Button bindService;

    private Button unbindService;


    private IMyAidlInterface myAIDLInterface;

    private ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            LogFish.d("process name"+ SystemUtil.getCurProcessName(MainActivity.this));
            myAIDLInterface = IMyAidlInterface.Stub.asInterface(service);
            try {
                int cnt = myAIDLInterface.getCount();
                double db = myAIDLInterface.complexCal("hello world",6);
                LogFish.d("result is " + cnt);
                LogFish.d( "complexCal value " + db);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService = (Button) findViewById(R.id.bind_service);
        unbindService = (Button) findViewById(R.id.unbind_service);
        Button bv = (Button) findViewById(R.id.get_num);
        bv.setOnClickListener(this);
        bindService.setOnClickListener(this);
        unbindService.setOnClickListener(this);
        Intent intent = new Intent("com.example.servicetest.MyAIDLService");
        startService(intent);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bind_service:
                Intent intent = new Intent("com.example.servicetest.MyAIDLService");
                boolean b= bindService(intent, connection, Service.BIND_AUTO_CREATE);
                LogFish.d("bind result "+b);
                break;
            case R.id.unbind_service:
//                Intent unbindIntent = new Intent(this, com.aidl.server.MyService.class);
                unbindService(connection);
                LogFish.d("unbind ");
                break;
            default:
                break;
        }

    }
}
           

Ok,代碼編寫完畢,先安裝AidlServer,再運作AidlClient

結果如下:

05-13 19:35:07.246    1734-1734/com.aidl.client D/LogFish﹕ result is 41

05-13 19:35:07.246    1734-1734/com.aidl.client D/LogFish﹕ complexCal value is 5.382318174E8

result是指service啟動到bind之間的時間,complexCal value是AidlServer計算出來的結果,AidlClient提供參數

用到module:AidlServer和AidlClient