• java简单实现AIDL进程通信


    服务端项目

    • 右键包名,新建一个Service,名称设为NameService,如下图:

    对自动生成的代码,稍作调整,代码如下:

    public class NameService extends Service {
       public NameService() {
       }
    
       @Override
       public IBinder onBind(Intent intent) {
           return null;
       }
    }
    

    AndroidManifest.xml文件里面会自动生成如下代码:

            <service
                android:name=".NameService"
                android:enabled="true"
                android:exported="true">service>
    
    • 右键main文件夹,new 一个aidl文件

    • 名为IGetNameInterface,代码如下:

    // IGetNameInterface.aidl
    package com.exp.service;
    
    interface IGetNameInterface {
      String getInfo();
    }
    
    • 新建aidl文件后,完整目录如下:

    • rebuild一下,在build目录下会生成IGetNameInterface.java文件,如下图:

    • 看下IGetNameInterface.java完整内容:

    /*
     * This file is auto-generated.  DO NOT MODIFY.
     */
    package com.exp.service;
    public interface IGetNameInterface extends android.os.IInterface
    {
      /** Default implementation for IGetNameInterface. */
      public static class Default implements com.exp.service.IGetNameInterface
      {
        @Override public java.lang.String getInfo() throws android.os.RemoteException
        {
          return null;
        }
        @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.exp.service.IGetNameInterface
      {
        private static final java.lang.String DESCRIPTOR = "com.exp.service.IGetNameInterface";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
          this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an com.exp.service.IGetNameInterface interface,
         * generating a proxy if needed.
         */
        public static com.exp.service.IGetNameInterface asInterface(android.os.IBinder obj)
        {
          if ((obj==null)) {
            return null;
          }
          android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
          if (((iin!=null)&&(iin instanceof com.exp.service.IGetNameInterface))) {
            return ((com.exp.service.IGetNameInterface)iin);
          }
          return new com.exp.service.IGetNameInterface.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
        {
          java.lang.String descriptor = DESCRIPTOR;
          switch (code)
          {
            case INTERFACE_TRANSACTION:
            {
              reply.writeString(descriptor);
              return true;
            }
            case TRANSACTION_getInfo:
            {
              data.enforceInterface(descriptor);
              java.lang.String _result = this.getInfo();
              reply.writeNoException();
              reply.writeString(_result);
              return true;
            }
            default:
            {
              return super.onTransact(code, data, reply, flags);
            }
          }
        }
        private static class Proxy implements com.exp.service.IGetNameInterface
        {
          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;
          }
          @Override public java.lang.String getInfo() 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);
              boolean _status = mRemote.transact(Stub.TRANSACTION_getInfo, _data, _reply, 0);
              if (!_status && getDefaultImpl() != null) {
                return getDefaultImpl().getInfo();
              }
              _reply.readException();
              _result = _reply.readString();
            }
            finally {
              _reply.recycle();
              _data.recycle();
            }
            return _result;
          }
          public static com.exp.service.IGetNameInterface sDefaultImpl;
        }
        static final int TRANSACTION_getInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        public static boolean setDefaultImpl(com.exp.service.IGetNameInterface impl) {
          // Only one user of this interface can use this function
          // at a time. This is a heuristic to detect if two different
          // users in the same process use this function.
          if (Stub.Proxy.sDefaultImpl != null) {
            throw new IllegalStateException("setDefaultImpl() called twice");
          }
          if (impl != null) {
            Stub.Proxy.sDefaultImpl = impl;
            return true;
          }
          return false;
        }
        public static com.exp.service.IGetNameInterface getDefaultImpl() {
          return Stub.Proxy.sDefaultImpl;
        }
      }
      public java.lang.String getInfo() throws android.os.RemoteException;
    }
    
    
    • 这个接口里面,本身继承自IInterface。看看IInterface,里面就一个public IBinder asBinder();方法,如下:
    package android.os;
    
    /**
     * Base class for Binder interfaces.  When defining a new interface,
     * you must derive it from IInterface.
     */
    public interface IInterface
    {
        /**
         * Retrieve the Binder object associated with this interface.
         * You must use this instead of a plain cast, so that proxy objects
         * can return the correct result.
         */
        public IBinder asBinder();
    }
    
    • 除了上面父类的asBinder方法,本接口里面有一个静态共有类Default,一个静态抽象类Stub,还有我们定义的一个抽象方法getInfo()。

    • 有了这个接口,就可以修改NameService的onBind()方法了,修改后完整代码如下:

    public class NameService extends Service {
        private static final String TAG = "NameService";
        public NameService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return new IGetNameInterface.Stub() {
                @Override
                public String getInfo() throws RemoteException {
                    Log.e(TAG, "远程服务被调用");
                    return "zhangjin";
                }
            };
        }
    }
    

    服务端代码到此就结束了。

    客户端代码

    • 把服务端整个aidl文件夹,复制过来,放在main目录下面,aidl文件不要修改。如下图:
    • rebuild一下,会生成一个和服务端一样的文件:
    • 在MainActivity中启动Service,并且显示数据。MainActivity布局文件自己写哈,其他代码如下:
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "Client";
        private IGetNameInterface mGetNameService;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Intent intent = new Intent();
            intent.setComponent(new ComponentName("com.exp.service","com.exp.service.NameService"));
            bindService(intent, new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.e(TAG, "onServiceConnected: ");
                    try {
                        mGetNameService = IGetNameInterface.Stub.asInterface(service);
                        TextView tv = findViewById(R.id.tv);
                        tv.setText(mGetNameService.getInfo());
                    } catch (Exception e) {
                        Log.e(TAG, "exception: " + e.getMessage());
                    }
                }
    
                @Override
                public void onServiceDisconnected(ComponentName name) {
                    Log.e(TAG, "onServiceDisconnected: ");
                }
            }, Context.BIND_AUTO_CREATE);
        }
    }
    

    安装测试

    先安装service,再安装Client,看下效果:

  • 相关阅读:
    【二分法】多种情况下的边界条件,区间选择汇总,小结
    redis学习
    使用SemanticKernel 进行智能应用开发(2023-10更新)
    vue02模板语法
    docker部署nginx并设置挂载
    想要精通算法和SQL的成长之路 - 填充书架
    pgsql的窗口函数简述
    如何手动添加NLTK data
    【MySQL】MySQL操作库
    C++仿函数
  • 原文地址:https://blog.csdn.net/zhangjin1120/article/details/126284972