AIDL 用法

AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言。 AIDL 在Android中有着广泛的应用,是IPC中最常用的通信方式。它分为了 客户端(client) 和 服务端(sever), 可以完成数据的双向通信,数据包括了常规数据类型和自定义类(其中自定义类需要进行序列化)。下面主要介绍了 AIDL的应用, 客户端如何和远程服务端进行双向通信,和传输数据。

AIDL主要步骤:

服务端:

  • 创建AIDL接口,如果需要传输自定义类,还需要对该类进行序列化,一般可以使用 parcelable对象进行序列化;如果服务端到客户端也需要回调通信,则此回调也需要一个aidl接口;
  • 在服务端中创建一个类(binder)继承自ADIL接口中的Stub类并实现Stub中的抽象方法;
  • 在onbind() 方法中返回这个类的对象;

客户端: 

  • 把编写的aidl目录和目录下的所有文件拷贝到客户端的main文件夹下,在实际应用规划总通常会将aidl接口(包括自定义类,生成的stub类)打成jar包,供服务端和所有客户端使用;
  • 创建ServiceConnection,绑定服务端时获取服务端的对象。如果有回调接口,则还需实现回调接口类;
  • 隐式启动服务端Service,开始获取服务端数据;

直接上个栗子:

服务端:

  1. 在 服务端工程中创建了 aidl接口,和自定义类,如下:

ITestInterface.aidl

package com.example.aidlserver.aidl;
import android.os.Parcel;
import android.os.Parcelable;
import com.example.aidlserver.aidl.ITestCallback;
import com.example.aidlserver.bean.TestInfo;

interface ITestInterface {
    void registerCallback(ITestCallback callback);  
    void unRegisterCallback(ITestCallback callback);  
    TestInfo getTestInfo();
    void setTestType(int type);
}

ITestCallback.aidl

package com.example.aidlserver.aidl;

interface ITestCallback {

    void onStatuChanged(int type, String arg0, String arg1);

}

2. 自定义类序列化:

如果你有一个类需要跨进程进行传输,你必须保证这个类实现了Parcelable接口并且在IPC的另外一端也有这个类。

为了创建一个支持Parcelable协议的类,必须做下面工作:

  • 保证你的类实现Parcelable接口
  • 实现writeToParce() 和 describeContents() 方法,writeToParce()方法将得到当前对象的状态,然后写入Parcel;
  • 给类增加一个叫做CREATOR的静态常量,这个静态常量实现了Parcelable.Creator接口,AIDL使用以上这些方法和域实现对象的序列化和反序列化
  • 最后,如果在AIDL中用到了这个自定义的类,那么必须创建一个和它同名的.aidl文件,并在其中这个类为Parcelable类型,如下所示,创建了一个TestInfo.aidl文件,在这个文件中声明了TestInfo为Parcelable类型。

TestInfo.java 自定义类

package com.example.aidlserver.bean;

import android.os.Parcel;

import android.os.Parcelable;

public class TestInfo implements Parcelable {

    private int mType;

    private String mMessage;

    public TestInfo() {     

    }

    public void setType(int type) {

        this.mType = type;

    }

    public int getType() {

        return this.mType;

    }

    public void setMessage(String message) {

        this.mMessage = message;

    }

    public String getMessage() {

        return this.mMessage;

    }

    private TestInfo(Parcel source) {

        readParcelInfo(source);

    }

    public static final Parcelable.Creator<TestInfo> CREATOR = new Parcelable.Creator<TestInfo>() {

        @Override

        public TestInfo createFromParcel(Parcel arg0) {

            // TODO Auto-generated method stub

            return new TestInfo(arg0);

        }

        @Override

        public TestInfo[] newArray(int arg0) {

            // TODO Auto-generated method stub

            return new TestInfo[arg0];

        }   

    };

    @Override

    public int describeContents() {

        // TODO Auto-generated method stub

        return 0;

    }

    //写入到parcel

    @Override

    public void writeToParcel(Parcel arg0, int arg1) {

        // TODO Auto-generated method stub

        arg0.writeInt(mType);

        arg0.writeString(mMessage);

    }

    private void readParcelInfo(Parcel source) {

        mType = source.readInt();

        mMessage = source.readString();

    }  

}

TestInfo.aidl 同目录下:

package com.example.aidlserver.bean;

// 声明为 parcelable 类

parcelable TestInfo;

 

3.在服务端实现 aidl接口

AidlTestService.java 在onBind 中返回实现接口的对象(此处注意和本地client进行区分);

package com.example.aidlserver;
import com.example.aidlserver.aidl.ITestCallback;
import com.example.aidlserver.aidl.ITestInterface;
import com.example.aidlserver.bean.TestInfo;

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

public class AidlTestService extends Service {
    
    private static final String TAG = "AidlTestService";
    
    final RemoteCallbackList<ITestCallback> mOtherAppCallback = new RemoteCallbackList <ITestCallback>(); 

    @Override
    public IBinder onBind(Intent arg0) {

        if (arg0.getAction() != null && arg0.getAction().equals("android.intent.action.aidl")) {
            return testInterface;  // 通过Action 辨别是否是哪一个服务端
        } else {
            return new Binder();  // 返回给同进程的服务端
        }

    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        return super.onStartCommand(intent, flags, startId);
    }
    
    public class Binder extends android.os.Binder {
        public AidlTestService getService() {
            return AidlTestService.this;
        }
    }
    
    public void refreshInfo() {
        Log.i(TAG, "refreshInfo");
    }
    
    // 回调,google推荐写法,可以一个 service 对多个 client端
    private void onCallbackMsg(int type, String arg0, String arg1) {
        final int N = mOtherAppCallback.beginBroadcast();
        for (int i=0; i<N; i++) {
            try {
                mOtherAppCallback.getBroadcastItem(i).onStatuChanged(type, arg0, arg1);
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        mOtherAppCallback.finishBroadcast();
    }
    
    ITestInterface.Stub testInterface = new ITestInterface.Stub() {
        
        @Override
        public void unRegisterCallback(ITestCallback callback)
                throws RemoteException {
            // TODO Auto-generated method stub
            if (callback != null) {
                mOtherAppCallback.register(callback);
            }
        }
        
        @Override
        public void setTestType(int type) throws RemoteException {
            // TODO Auto-generated method stub
            Log.d(TAG, "setTestType " + type);
        }
        
        @Override
        public void registerCallback(ITestCallback callback) throws RemoteException {
            // TODO Auto-generated method stub
            if (callback != null) {
                mOtherAppCallback.unregister(callback);
            }
        }
        
        @Override
        public TestInfo getTestInfo() throws RemoteException {
            // TODO Auto-generated method stub
            Log.d(TAG, "getTestInfo");
            
            TestInfo info = new TestInfo();
            info.setMessage("testInfo");
            info.setType(100);
            
            return info;
        }
    };
}

4.将aidl接口打成jar包,给服务端使用。 也可以将整个aidl包复制到服务端(目录和文件名都不能更改)。如下是通过eclipse工具进行打包的

5.服务端:

实现ServiceConnection 和 回调接口,binder成功后,即可拿到远程服务端对象。

MainActivity.java

public class MainActivity extends Activity {
    
    private static final String TAG = "Client Activity";
    
    private Button mBtnBinder;
    private Button mBtnStop;
    private Button mBtnTest1;
    private Button mBtnTest2;
    
    private ITestInterface mInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        initView();
    }
    
    private void initView() {
        mBtnBinder = (Button) findViewById(R.id.btn_binder);
        mBtnStop = (Button) findViewById(R.id.btn_stop);
        mBtnTest1 = (Button) findViewById(R.id.btn_test1);
        mBtnTest2 = (Button) findViewById(R.id.btn_test2);
        
        mBtnBinder.setOnClickListener(listener);
        mBtnStop.setOnClickListener(listener);
        mBtnTest1.setOnClickListener(listener);
        mBtnTest2.setOnClickListener(listener);
    }
    
    private View.OnClickListener listener = new View.OnClickListener() {
        
        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            switch (arg0.getId()) {
            case R.id.btn_binder:
                binderService();
                break;
            case R.id.btn_stop:
                unbinderService();
                break;
            case R.id.btn_test1:
                test1();
                break;
            case R.id.btn_test2:
                test2();
                break;
            default:
                break;
            }
        }
    };
    
    private void binderService() {
        Log.i(TAG, "binderService");
        Intent intent = new Intent();
        intent.setAction("android.intent.action.aidl"); //通过aciton, binder AidlService
        this.bindService(intent, connection, BIND_AUTO_CREATE);
    }
    
    private void unbinderService() {
        this.unbindService(connection);
    }
    
    private void test1() {
        if (mInterface != null) {
            Log.d(TAG, "test1");
            try {
                mInterface.setTestType(1);
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    private void test2() {
        if (mInterface != null) {
            Log.d(TAG, "test2");
            TestInfo info = new TestInfo();
            
            try {
               info = mInterface.getTestInfo();
               Log.i(TAG, "testinfo " + info.getMessage() + " type: " + info.getType());
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    private ServiceConnection connection = new ServiceConnection() {
        
        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            // TODO Auto-generated method stub
            Log.d(TAG, "onServiceDisconnected");
        }
        
        @Override
        public void onServiceConnected(ComponentName arg0, IBinder arg1) {
            // TODO Auto-generated method stub
            Log.d(TAG, "onServiceConnected");
            mInterface = ITestInterface.Stub.asInterface(arg1);
        }
    };
    
    // service的回调实现
    private ITestCallback.Stub callback = new ITestCallback.Stub() {
        
        @Override
        public void onStatuChanged(int arg0, String arg1, String arg2)
                throws RemoteException {
            // TODO Auto-generated method stub
            
        }
    };

}

 6.测试: client -> service 端调用成功;

             service -> client 端回调成功;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值