AIDL使用的demo

467 阅读2分钟

这是一篇使用Android Studio写AIDL demo的文章,个人记录。

服务提供方,服务端。
创建AIDL文件。

package com.dc.myappAssist;
interface IMyAIDL {
    int add(int a,int b);
}

创建之后将会在build\generated\aidl_source_output_dir下生成一个同名的java文件,它是一个接口,如下:

public interface IMyAIDL extends android.os.IInterface
{
  /** Default implementation for IMyAIDL. */
  public static class Default implements com.dc.myappAssist.IMyAIDL
  {
    @Override public int add(int a, int b) throws android.os.RemoteException
    {
      return 0;
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }

  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements com.dc.myappAssist.IMyAIDL {
      ...
  }
}

接上,Service以Binder的形式对外提供服务。这个生成的接口内部包含一个Stub的抽象的静态内部类,继承于Binder,所以可以提供Service对外抛出;又它实现了AIDL接口,所以它又可以用于实现AIDL的业务。

创建服务,实现AIDL的业务并对外提供。onBind()的返回值用Stub的实现类。

public class MyAidlService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new IMyAIDL.Stub() {
            @Override
            public int add(int a, int b) throws RemoteException {
                return a + b;
            }
        }
    }
}

Service要对外提供,因此注册时,要提供隐式启动的方式(action启动),且export=‘true’。

服务调用方,即客户端。 将AIDL文件复制到客户端,切记不可修改包名。
然后启动服务,注意:1、跨进程要指定package,2、要以bindService的方式启动。

Intent i = new Intent(action);
i.setPackage("com.dc.myappAssist"); // 启动外部服务,要指定服务端的包名
bindService(i, new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder binder) {
        IMyAIDL aidl = IMyAIDL.Stub.asInterface(binder); // 客户端通过这个调用服务
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
}, Context.BIND_AUTO_CREATE);

承上,IMyAIDL aidl = IMyAIDL.Stub.asInterface(binder),这是跨进程调用强转的方式,对比同进程的转换方式,IMyAIDL aidl = (IMyAIDL.Stub) binder),跨进程这么转会报错的,看源码。

public interface IMyAIDL extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.dc.myappAssist.IMyAIDL {

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

        private static class Proxy implements com.dc.myappAssist.IMyAIDL {
            private android.os.IBinder mRemote;
            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }
            @Override public android.os.IBinder asBinder() {
                return mRemote;
            }
        }
    }
}

承上,bindService()得到的IBinder对象,是BinderProxy(class BinderProxy implements IBinder),客户端得到的是一个代理,用IMyAIDL.Stub.asInterface()。