美文网首页Android-NDK/JNIAndroid开发半栈工程师
清晰认识Android JNI,不再说不懂JNI。

清晰认识Android JNI,不再说不懂JNI。

作者: 喵一喵哈 | 来源:发表于2017-11-25 22:35 被阅读158次

    个人的一些总结,希望能对JNI的认识有一个比较清晰的整理,方便以后回顾与使用。从理解、实现、问题、应用四个方面来一步步分析研究,JNI的分析主要包括如下几部分:

    一、NDK与JNI的理解;

    二、用JNI实现与原生代码通信;

    三、调试与故障处理;

    四、常见的应用场景。

    一、NDK与JNI的理解;

    1、什么是NDK?

    Android NDK,即Native Development Kit。知道全称才更好地理解,它是Google公司给我们提供的一套开发工具,就是为了使Android程序能够执行C&C++等部分原生代码。

    2、什么是JNI,怎么样使用?

    JNI设计的目的:标准的java类库可能不支持你的程序所需的特性。或许你已经有或写了一个用其他语言写成的库或程序,而你希望在java程序中使用它。

    JNI——Java Native Interface,它是Java平台的一个特性(并不是Android系统特有的)。其实主要是定义了一些JNI函数,让开发者可以通过调用这些函数实现Java代码调用C/C++的代码,C/C++的代码也可以调用Java的代码,就是说我们使用在Java代码里面去使用其他语言现有的API。JNI不局限于Android平台(windows一般是dll文件,linux一般是so文件等)。首先是将写好的C/C++(JNI编程支持C和C++)代码编译成对应平台的动态库,这里我们是针对Android平台,所以只讨论so库。

    3、使用JNI有什么用处?

    1)加密:产品核心或重要功能代码的保护,由于APK的Java层代码很容易被反编译,而C/C++库反汇难度较大。对代码加密这一块有比较大的保护作用;

    2)执行效率:因为c/c++比Java效率高,所以应用运行起来速度比较快,特别是一些游戏中的算法;

    2)使用成熟的C/C++库:在NDK中调用第三方C/C++库,因为大部分的开源库都是用C/C++代码编写的。所以可以有更多的可用库,方便一些特殊的实现方式;

    3)便于移植:用C/C++写的库可以方便在其他的嵌入式平台上再次使用,比如图片视频处理算法:FFmpeg;

    4)底层实现:因为Android应用程序是跑在虚拟机上面,所以有些底层的硬件调用需要使用更底层的语言去调用,比如一些驱动拓展之类的。

    二、用JNI实现与原生代码通信;

    1、先看看Android系统上那些地方用到了JNI。

    我们看看Android的消息机制(顺便了解一下消息机制),先看Handler的源码,找到里面的Looper的源码,再找到MessageQueue,看看如下代码:

    private native static longnativeInit();

    private native static voidnativeDestroy(longptr);

    private native voidnativePollOnce(longptr,inttimeoutMillis);/*non-static for callbacks*/

    private native static voidnativeWake(longptr);

    private native static booleannativeIsPolling(longptr);

    private native static voidnativeSetFileDescriptorEvents(longptr,intfd,intevents);

    这些就是MessageQueue在系统上的JNI方法,对应到系统的C源码在系统源码frameworks/base/core/jni/android_os_MessageQueue.cpp文件中。其实如果看Android的源码,可以看到很多native的身影。

    2、为了避免描述太复杂,看看下面这张图慢慢理解:

    Application、JNI与系统原理关系图

    3、JNI的实现:

    Android JNI 实现过程

    个人觉得看流程图更容易理解,具体的代码也比较简单,可以参考JNI开发流程(感谢大神)。

    主要用到的命令有 javah javac ndk-build ndk-clean ,可以注意一下:Android JNI libs 目录下的.so文件的区别

    三、调试与故障处理;

    1、先分析错误,看错误的描述,尽量读懂Error的意思;

    2、log打印大法,定位错误位置,尝试找出错误的准确位置;

    3、抛异常,在代码中断点调试。15年7月在Android Studio 1.3版本上添加了gradle-experimental插件,该插件支持NDK开发和调试,且带有代码不全和重构等高级功能。Android Studio NDk调试(基于gradle-experimental插件与LLDB)

    四、常见的应用场景;

    结合自身和他人的经验,看看jni在主要使用在那个方面:

    1、一些特定机器的项目,为了不让别人把开发出来的apk安装到其他机器上,特意用jni写了加密算法,如果别人没有反编译到jni代码,程序的入口和核心功能都无法实现运行;

    2、资源加密,在教育或其他一些行业,比如步步高点读机,读书郎点读机,有一些内容或音频是加密的,用jni使用对应的方式才能读取,这样使用jni的好处有:别人看到你加密的资源看不懂,也不知道如何读取你的资源文件;

    3、音视频处理,ffmpeg是一个非常强大的音视频编解码开源库,目前市场上流行的播放器,大部分都是基于此开发的,包括暴风,腾讯等等,还有常见的视频播放开源库vitamio、vlc、ijkplayer。通过反编译网易云音乐,以及YY等音视频app,发现网易云音乐,斗鱼用的ijkplayer,YY用的VLC。这些涉及到核心的必须熟悉JNI开发。

    4、多屏互动,构建家庭媒体共享的解决方案,牵涉到了DLNA的应用,目前来说在android中用到的UPNP框架基本为platinum、cyberlink、cling等框架。开心视频和快手看片用的是基于cling框架的dlna开发,而腾讯视频和搜狐视频用的就是基于cyberlink的dlna开发;这些库的使用和修改就需要用jni。

    5、android 上需要使用图片滤镜处理的应用越来越多,比如开源滤镜处理库GPUImage,刚开始的时候in这样图片应用也是使用这样的滤镜库,但随着自定义等要求越来越高,需要自己实现部分滤镜功能,但用java难以开发,算法处理效率也不够,这时候就需要用C或C++实现滤镜处理的功能,然后用jni在Android上使用。

    相关文章

      网友评论

        本文标题:清晰认识Android JNI,不再说不懂JNI。

        本文链接:https://www.haomeiwen.com/subject/cneauxtx.html