Android studio 创建AIDL

一  前言

       用startService,bindService创建的服务只能在本应用程序内访问,如果要使得本程序的服务能够被其他应用程序访问,这时候就要使用远程过程调用(Remote Procedure Call,RPC)方式来实现,安卓定义了一种接口定义语言Android Interface Definition Language,简称AIDL。今天记录一下如何在Android Studio下创建AIDL Serivce。

      建立ADIL Service的步骤比建立普通Service要多一些,主要有:

  • 创建AIDL文件(在src/main/aidl/...下,aidl目录需要自己创建),在这里面定义远程接口(例如下面的ICat.adl)。
  • Rebuild项目,生成Java接口文件(ICat.java,AS中,这个文件位置在build/generated/source/aidl/debug/目录下),并且在其内部自动生成了一个Stub的内部类,Stub继承了Binder和实现了ICat 接口,因此它可以作为远程Service的回调类。
  • 建立一个Service的子类,并且记得在AndroidManifest.xml文件中配置。

       在客户端调用ADIL Servie:

  • 拷贝服务器端的AIDL文件,并生成Java接口文件。
  • 用BindService来调用Service,与调用普通Serivce相类似,只是获取IBinder的方式有点不一样。下面贴出来ICat.java代码

ICat.java代码如下:

package com.sysu.aidlclient.aidlclient;
// Declare any non-default types here with import statements

public interface ICat extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.sysu.aidlclient.aidlclient.ICat {
        private static final java.lang.String DESCRIPTOR = "com.sysu.aidlclient.aidlclient.ICat";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.sysu.aidlclient.aidlclient.ICat interface,
         * generating a proxy if needed.
         */
        public static com.sysu.aidlclient.aidlclient.ICat asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.sysu.aidlclient.aidlclient.ICat))) {
                return ((com.sysu.aidlclient.aidlclient.ICat) iin);
            }
            return new com.sysu.aidlclient.aidlclient.ICat.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_getColor: {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _result = this.getColor();
                    reply.writeNoException();
                    reply.writeString(_result);
                    return true;
                }
                case TRANSACTION_getWeight: {
                    data.enforceInterface(DESCRIPTOR);
                    double _result = this.getWeight();
                    reply.writeNoException();
                    reply.writeDouble(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.sysu.aidlclient.aidlclient.ICat {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            /**
             * Demonstrates some basic types that you can use as parameters
             * and return values in AIDL.
             */
            @Override
            public java.lang.String getColor() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.lang.String _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getColor, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readString();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public double getWeight() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                double _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getWeight, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readDouble();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_getColor = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getWeight = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    public java.lang.String getColor() throws android.os.RemoteException;

    public double getWeight() throws android.os.RemoteException;

二 建立AIDL文件

        在项目名称上右键>NEW>AIDL>AIDL File,这样就创建了一个ADIL文件,命名为ICat


文件内容为:

 // ICat.aidl  

package com.sysu.aidlclient.aidlclient;  
  
interface ICat {  
   String getColor();  
   double getWeight();  
} 

然后菜单中选择Build>Rebulid Project,这样就生成了java接口文件,地址在项目文件夹/app/build/generated/aidl里面。
二  编写Service子类:

        这一步跟建立普通的Serivce步骤一样,同样右键>New>Service,这样会创建一个Service的子类以及在AndroidManiFest中添加Service的的内容,主要要添加action标签并且定义android:name。它的onBind方法返回的IBinder对象要是ICat.Stub的子类的实例,ICat.Stub这个类基本不用去管它,是自动生成的。

public class AidlService extends Service {  
  
    private CatBinder catBinder;  
    //此处要继承Stub,实现ICat和IBinder接口  
    public class CatBinder extends ICat.Stub  
    {  
        @Override  
        public String getColor() throws RemoteException {  
            return "get from remote service";  
        }  
  
        @Override  
        public double getWeight() throws RemoteException {  
            return 999.9;  
        }  
    }
  
    @Override  
    public void onCreate() {  
        super.onCreate();  
        <span style="color:#ff0000;">catBinder = new CatBinder();
  
    @Override  
    public IBinder onBind(Intent intent) {  
        <span style="color:#ff0000;">return catBinder;
    }  
  
    @Override  
    public void onDestroy() {  
        System.out.println("remote service destroy");  
    }  
}  
然后将应用部署到手机上。

三  客户端调用

        首先要拷贝AIDL文件,这里要保证文件的内容一模一样,包括包的名称,比如本例子中服务器端AIDL文件所在包的名称是com.sysu.aidlclient.aidlcilent,如何做到这一点,先新建一个项目,然后在:项目文件夹/app/src/main目录下建立一个aidl文件夹,与java文件夹同级,在Android Studio中就可以看到这个目录,在这个目录上右键New>Package,建立一个com.sysu.aidlclient.aidlclient的包,再将aidl文件拷进去。这样才能保证生成的java接口文件完全一样,否则会提示找不到接口。


      在MainActivity中调用,用bindService方法,记得要定义一个显式的intent,如红色代码获取Service的IBinder的代理

private ServiceConnection conn = new ServiceConnection() {  
        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) {  
              catService = ICat.Stub.asInterface(service);</span>  
        }  
  
        @Override  
        public void onServiceDisconnected(ComponentName name) {  
            catService = null;  
  
        }  
};  


@Override  
protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
  
        Intent intent = new Intent();  
        intent.setAction("com.sysu.aidlclient.action.AIDL_SERVICE");  
        //this is important  
        intent.setPackage("com.sysu.aidlclient.aidlclient");  
        bindService(intent,conn, Service.BIND_AUTO_CREATE);  
}  
之后就可以用catService来调用远程service中的方法了
public void getRemoteService(View view)  
    {  
        try  
        {  
            Toast.makeText(this,"the color and weight is: "+catService.getColor()+":",  
                    Toast.LENGTH_LONG).show();  
            System.out.println(catService.getColor()+"----"+catService.getWeight());  
        }catch (RemoteException e)  
        {  
            e.printStackTrace();  
        }  
        System.out.println("button click");  
}  









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值