Android AIDLの使用と双方向のデータ転送

8104 ワード

Android Interface Definition Languageは、AIDLと略称され、Androidインタフェース定義言語であり、プロセス間通信に用いられる.もちろんブロードキャストを送信することでプロセス間通信の目的を達成することもできますが、ブロードキャストは遅延などの現象に遭遇し、個人的にはAIDLを使用することをお勧めします.
AIDL転送データは、Java基本データ型、List、Map、およびParcelableを実装するクラスをサポートする.次に、AIDLの例を説明し、Android Studioを使用して開発された双方向伝送をサポートします.
AIDLにはサービス側とクライアントがあり、サービス側ではaidlにいます.com.android.demoパスの下に接尾辞を生成する.マイドのデモフォaidlファイル、内容は以下の通りです.
package com.android.demo;
parcelable DemoInfo;
         ,            。     AIDL      ,   java.com.android.demo     DemoInfo.java   。
package com.android.demo;

import android.os.Parcel;
import android.os.Parcelable;

public class DemoInfo implements Parcelable {
    private int mValue1 = -1;
    private int mValue2 = -1;

    public int getValue1() {
        return mValue1;
    }

    public void setValue1(int mValue1) {
        this.mValue1 = mValue1;
    }

    public int getValue2() {
        return mValue2;
    }

    public void setValue2(int mValue2) {
        this.mValue2 = mValue2;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public void readFromParcel(Parcel in) {
        mValue1 = in.readInt();
        mValue2 = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mValue1);
        dest.writeInt(mValue2);
    }

    public static final Creator CREATOR = new Creator() {
        @Override
        public DemoInfo createFromParcel(Parcel source) {
            DemoInfo mInfo = new DemoInfo();
            mInfo.mValue1 = source.readInt();
            mInfo.mValue2 = source.readInt();
            return mInfo;
        }

        @Override
        public DemoInfo[] newArray(int size) {
            return new DemoInfo[size];
        }
    };
}

次に、サービス側もクライアントにデータを転送できるように、クライアントがリスニングコールを登録するためにCallBackを書きます.aidlでcom.android.demoパスの下に接尾辞を生成する.アイドのデモ・キャル・バックaidlファイル.
package com.android.demo;
import com.android.demo.DemoInfo;

interface DemoCallback {
    void sendCtrlData(in DemoInfo info);
}

シーケンス化パラメータを渡すため、AIDLは方向を明記する必要があります.全部で3種類あります.in,out,inoutです.inはデータがクライアントからサービス側に流れることを示し、outはデータがサービス側からクライアントに流れることを示し、inoutはデータがサービス側とクライアントの間で双方向に流通できることを示す.次はaidlでcom.android.demoパスの下に接尾辞を生成する.マイドのデモインターフェースaidlファイル、内容は以下の通りです.
package com.android.demo;

import com.android.demo.DemoCallback;

interface DemoInterface {
    void getResult(boolean bool);
    void registListener(DemoCallback listener);
    void unregistListener(DemoCallback listener);
}

クライアントがデータを転送し、リスニングコールバックを登録し、リスニングコールバックを解放するインタフェースが書かれています.次に、サービス側はIBinderをクライアント接続のために提供し、以下のように実現する.
package com.android.demo;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;

public class AidlService extends Service {
    private static AidlService mService = null;
    private static RemoteCallbackList mListener=new RemoteCallbackList<>();
    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mListener.kill();
    }

    private DemoInterface.Stub stub = new DemoInterface.Stub() {
        @Override
        public void getResult(boolean bool) throws RemoteException {
            Log.d("AidlService","getResult="+bool);
        }

        @Override
        public void registListener(DemoCallback listener) throws RemoteException {
            mListener.register(listener);
        }

        @Override
        public void unregistListener(DemoCallback listener) throws RemoteException {
            mListener.unregister(listener);
        }
    };

    public static synchronized AidlService getInstance() {
        if (mService == null) {
            mService = new AidlService();
        }
        return mService ;
    }

    public static void notifyClient(DemoInfo mInfo) throws RemoteException {
        int count = mListener.beginBroadcast();
        for (int i = 0; i < count; i++) {
            DemoCallback broadcastItem = mListener.getBroadcastItem(i);
            if (broadcastItem != null) {
                try {
                    //     
                    broadcastItem.sendCtrlData(mInfo);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        //     finishBroadcast
        mListener.finishBroadcast();
    }
    @Override
    public IBinder onBind(Intent intent) {
        return stub;
    }
}

AndroidManifestでxmlで定義:
     

      
           
      

内のactionはクライアントバインド時のIntentが設定するactionです.これで、サービス側のAIDLに関する面が書き終わりました.今、クライアントはサービス側に接続します.まず最初にしなければならないのは、サービス側がさっき書いたものです.AIDLはクライアントにコピーされ、クライアントパスはサービス側がaidlであるようにサービス側と一致する.com.android.demo、クライアントもaidlです.com.android.demo.そして、DemoInfoへのシーケンス化が実現する.JAvaもクライアントと同じ場所にコピーします.接続操作を行います.
package com.android.clinet;


import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;

import com.android.demo.DemoCallback;
import com.android.demo.DemoInterface;
import com.android.demo.DemoInfo;


/**
 *       
 */
public class ServiceBindManage implements Handler.Callback{

    private final static String TAG = ServiceBindManage.class.getSimpleName();

    public static DemoInterface mManagerService = null;

    //      
    private static ServiceBindManage mServiceBindManage = null;

    private DemoCallback mListener=new DemoCallback.Stub(){
        @Override
        public void sendCtrlData(DemoInfo status) throws RemoteException {
            Log.d(TAG,"mValue1="+status.getValue1()+",mValue2="+status.getValue2());
        }
    };

    private ServiceConnection mConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.d(TAG, "onServiceConnected");
            mManagerService = DemoInterface.Stub.asInterface(iBinder);
            try {
                mManagerService .registListener(mListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mManagerService.unregistListener(mListener);
            mManagerService = null;
        }
    };

    public static ServiceBindManage getInstance() {
        if (mServiceBindManage == null) {
            mServiceBindManage = new ServiceBindManage();
        }

        return mServiceBindManage;
    }

    public void bindService(Context ctx) {
        Log.d(TAG, "bindService");
        //  AIDL
        bindAidlService("com.android.demo.aidl",mConn);
    }


    private void bindAidlService(String action, ServiceConnection connent) {
        Log.d(TAG, "bindAidlService:Coon = " + connent);
        Intent intent = new Intent();
        intent.setAction(action);
        //     
        intent.setPackage("com.android.demo");
        MyApplication.getInstance().bindService(intent, connent, Context.BIND_AUTO_CREATE);
    }

    public void unBindService(Context ctx) {
        if(mManagerService != null){
            MyApplication.getInstance().unbindService(mConn);
            mManagerService = null;
        }

    }
}

サービス側とAIDLをバインドする場合は、ServiceBindManagementを呼び出します.getInstance().bindService(this); 
不要な場合は、ServiceBindManagementを呼び出します.getInstance().unBindService(this);