Android JNI开发-实际项目开发总结(回调函数)
这篇文章想要介绍一下我之前做的一个真实项目,感觉比较有意思,记录一下。
项目介绍
这个项目比较有特点的是项目的主要业务逻辑由C语言开发同事完成,在他的SO库中去做初始化、网络操作、数据库存储、硬件设备操作等等的逻辑,我这边Android主要就是调用他的接口结合界面完成业务。
但是由于我们在第三方硬件设备操作,而第三方只提供了Android的SDK,在C层面无法调用,所以硬件操作的接口也需要由我进行封装,提供操作的接口(回调函数,不了解的请看这里)给C开发同事调用。这样就形成了下面的结构:
我在APP初始化的时候,就将所有有关界面操作和硬件操作的函数以参数的形式传给SO。SO库中实际业务中,如果需要修改界面,比如要显示黑名单下载进度,就调用传入downloadBlackListCallBack函数,这个函数中会以JNI反射的方式调用到Java层代码,再由Java层代码实现进度的更新。硬件操作接口同样的道理。
代码实现
SO库函数定义
在一步中除了正常的参数传入,重要的就是传入回调函数了。
和同事做好协商,以显示进度为例,在SO库对外提供的函数中有这样一个函数,用来设置进度回调。
1 | void APi_SetProgressCallback(Processfun Callback); |
在他的头文件中Processfun的定义如下,要求我们传入两个int类型的值,第一个参数为已下载数量,第二个参数为总数量。
1 | typedef void (*Processfun)(int,int); |
这个是SO库中要求的函数形式,接下来我们就要写自己的实现函数
Java层实现
我们首先实现一个Java层真正去控制进度显示的函数。
在JNIController类中实现函数:
1 | /** |
入参和上面定义的一样,已下载数量和总数量,当函数调用后通过广播的方式将传入的数量发送出去,广播接收器去修改界面。
JNI层实现
然后要从JNI层以反射的方式调用Java层的downloadBlackListCallBack函数。
1 | void downloadBlackListCallBack(int downloaded, int all); |
在JNI中入参也是一致的形式,再通过反射的方式调用Java层代码,将downloaded, all参数传给Java函数。
传递函数
JNI层的downloadBlackListCallBack函数已经写好了,最后就在初始化的函数中,调用SO库提供的APi_SetProgressCallback(Processfun Callback)
将函数以参数的形式传入
1 | APi_SetProgressCallback(downloadBlackListCallBack); |
1 | Processfun processFun = null; |
这样就是一个完整的流程了。
设备的硬件操作接口也是同样的逻辑完成。
总结
整体而言,主要还是用了C语言回调函数的方式,将上层的操作封装成接口,交给底层逻辑自己控制,这样比较灵活,双方的代码量也减少,就是需要在前期双方梳理好需要的接口,完工!