Android 中AIDL的简单使用

585 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

初次接触使用AIDL,之前在项目中没有使用过,今天就来简单分享一下安卓中的AIDL的使用,AIDL 是 Android Interface Definition language 的缩写,它是⼀种 Android 内部进程通信接⼝的描述语⾔,通过它我们可以定义进程间的通信接⼝。那么既然是跨进程的我们就是编写2个程序用来模拟跨进程通讯。

文章进行更新,添加callBack,进行打包aar(包含aidl文件),供clinet(clinet将不在单独引入aidl文件)使用

服务端程序(被调用的程序)

首先我们创建一个安卓project,命名为service,我们在android studio中将项目架构,切换为project,随后我们在main文件夹下右键创建Diretcory,可直接选中aidl文件夹进行创建如图所示:

image.png 接下来我们进行创建aidl文件,我们可以在aidl文件夹上右键进行创建如图所示:

image.png 创建完成后我们创建一个方法,就用来计算2个数求和使用:

// MyAidlInterface.aidl
package com.glc.service;

// Declare any non-default types here with import statements

interface MyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    //求和
    int getAdd(int num1,int num2);
}

在这里定义好AIDL类之后我们要sync project,这样我们才能找到构建的AdiL代码。 我们接下来在项目代码中在创建Service文件,如下图所示:

image.png 在Service中创建内部类,继承自Aidl类的抽象类Stub(这里必须要构建一下项目,否则找不到AIDL类),然后我们实现类里面的方法,这时就有我们定义的求和方法,我们实现求和方法里面的逻辑代码,让num1,num2相加,最后return,最后我们在Service的onBind()方法中返回内部类的实例。

public class MyService extends Service {
    private static final String TAG = "MyService";
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {

      return  new MyAidl();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: ");
    }

   private class MyAidl extends MyAidlInterface.Stub{

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }
        /**
         * 求和
         * @param num1
         * @param num2
         * @return result
         * @throws RemoteException
         */
        @Override
        public int getAdd(int num1, int num2) throws RemoteException {
            return num1+num2;
        }
    }
}

这样我们Service服务端代码就告一段落啦。

客户端程序(调用程序)

在客户端程序中我们也要引入AIDL文件,我们直接copy,服务端的AIDL文件夹即可(这里的包名路径要和服务端的AIL文件保持一致),完成之后我们同样要构建一下项目,如图所示:

image.png

接下来我们在Activity类中进行绑定服务,然后调用服务端的求和方法,进行得到2个数的值:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private  MyAidlInterface myAidlInterface;
    private ActivityMainBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding=ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        //绑定Aidl服务
        bindMyService();


        //获取结果按钮
        binding.btnGetResult.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    int add = myAidlInterface.getAdd(1, 1);
                    binding.tvResult.setText("结果:"+add);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });


    }

    private void bindMyService() {
        Log.d(TAG, "bindMyService: ");
        Intent intent=new Intent();
        //包名、类名
        intent.setComponent(new ComponentName("com.glc.service","com.glc.service.MyService"));
        bindService(intent, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                Log.d(TAG, "onServiceConnected: ");
                 myAidlInterface = MyAidlInterface.Stub.asInterface(iBinder);
            }

            @Override
            public void onServiceDisconnected(ComponentName componentName) {
                Log.d(TAG, "onServiceDisconnected: ");
                myAidlInterface=null;
            }
        },BIND_AUTO_CREATE);
    }


}

这样我们就完成服务端和客户端的代码,我们运行2个项目到设备,点击获取结果就能得到想要结果了。 github:github.com/GAOli-cong/…

image.png

在aidl中进行回调处理

在原先代码的基础上进行了修改,并且进行封装aar包(将aidl文件封装进了aar包),此时客户端的代码将不用在单独引用一遍aidl文件/同时通过callBack进行将数据回调。

首先创建ICallBack.aidl

在service的主模块代码中,新创建ICallBack.aidl 如下图:

image.png

在MyAidlInterface.aidl,新创建一个方法带有ICallBack参数

image.png

同时service中进行修改,实现新加的方法

image.png

service中新建module

在service中,新建module(用来打包aar供client使用),需要在module中,将aidl文件进行引用,如图所示:

image.png

同时新创建AidlManager文件,用来进行,调用aidl绑定服务

public class AidlManager {
    private static final String TAG = "AidlManager";
    private Context mContext;

    private MyAidlInterface myAidlService;

    private IBinder b;
    private static AidlManager mInstance;
    private boolean connected;

    private AidlManager(Context context) {
        mContext = context.getApplicationContext();
        bindService(connection);
    }

    public static synchronized AidlManager getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new AidlManager(context);
        }
        return mInstance;
    }

    public void unBind() {
        if (connected) {
            mContext.unbindService(connection);
        }
    }

    public MyAidlInterface getMyAidlService() {
        if (myAidlService != null) {
            return myAidlService;
        }
        myAidlService = MyAidlInterface.Stub.asInterface(b);
        return myAidlService;
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected: 绑定成功");
            b = service;
            connected = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected: 绑定失败");
            connected = false;
        }
    };


    private void bindService(ServiceConnection serviceConnection) {
        Log.d(TAG, "开始绑定服务bindService: ");
        Intent intent = new Intent();
        //包名、类名
        intent.setComponent(new ComponentName("com.glc.service", "com.glc.service.MyService"));
        mContext.bindService(intent, serviceConnection, BIND_AUTO_CREATE);
    }
}

然后将module进行打包 aar,同时将打包好的aar引用到client项目中,此时就可以通过aar拿到service,进行调用service端代码了。

image.png

已经更新最新代码github:github.com/GAOli-cong/…