Android Studio中jni的使用

最近在项目中需要使用JNI的相关东西,尤其是.so文件,发现许多开发者都是非常陌生的,所以有必要在这里做个简单的介绍。

JNI的基本概念

CPU的基本架构

早起Android只支持ARMv5的CPU架构,而发展到现在,支持一下7种架构:
ARMv5:现在很少了,应该不需要支持了
ARMv7(2010年起):魅族M9,iphone 3GS,三星I9000等
x86(2011年起):联想K800,使用这种架构的较少,毕竟Android手机大部分是ARM。
MIPS(2012年):可能有些国产厂商在用
ARMv8:华为 Mate 8,Galaxy S
MIPS64:暂时没发现什么手机在用
x86_64(2014年):64位平板
每种架构关联着一种ABI(application binary interface应用程序二进制接口),所以每一种架构都对应一个.so文件。
如图所示:

《Android Studio中jni的使用》 Paste_Image.png

这里需要注意很重要的一点:
arm64-v8a是可以向下兼容的,但前提是你的项目里面没有arm64-v8a的文件夹,如果你有两个文件夹armeabi和arm64-v8a,两个文件夹,armeabi里面有a.so 和 b.so,arm64-v8a里面只有a.so,那么arm64-v8a的手机在用到b的时候发现有arm64-v8a的文件夹,发现里面没有b.so,就报错了,所以这个时候删掉arm64-v8a文件夹,这个时候手机发现没有适配arm64-v8a,就会直接去找armeabi的so库,所以要么你别加arm64-v8a,要么armeabi里面有的so库,arm64-v8a里面也必须有。

如何依赖.so文件

对于eclipse就不用多说了,放在libs中即可。
如果使用Android Studio,有两种方式可以依赖.so文件
第一种放在src/main/jniLibs中如图所示:

《Android Studio中jni的使用》 Paste_Image.png

第二种方式,也可以放到libs中,但是需要在build.gradle中设置一下目录结构:

sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

编写.so文件

配置工程

在app的build.gradle中:

 defaultConfig {
        applicationId "umeng.testjni"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        ndk {
            moduleName "JniTest"
            ldLibs "log", "z", "m"
            abiFilters "armeabi", "armeabi-v7a", "x86"
        }
    }

其中moduleName是生成的.so文件的名字,如果设置成JniTest,生成的.so文件会是libJniTest.so,ldLibs是依赖的库。
打开gradle.properties文件,增加配置:

android.useDeprecatedNdk = true

local.properties增加ndk的配置路径:

ndk.dir=/Users/xxxx/xxxx/sdk/android-ndk-r10e
sdk.dir=/Users/xxxxx/Library/Android/sdk

代码文件

然后在工程中建立调用jni的文件:

public class UmengJni {

   static {
        System.loadLibrary("JniTest");
    }
    public static native String sayHello();

}

其中 System.loadLibrary(“JniTest”);是加载.so文件,sayHello是c++的方法名字。
这时打开命令行,切到当前应用工程的目录下,输入如下命令:

《Android Studio中jni的使用》 Paste_Image.png

其中umeng.testjni.UmengJni是我们刚刚编写的文件,这时会在对应的路径下生成一个.h文件

《Android Studio中jni的使用》 Paste_Image.png

在java目录下建立jni文件夹,新建main.c实现刚才生成的头文件中的方法:

#include <jni.h>
/* Header for class umeng_testjni_UmengJni */

#ifndef _Included_umeng_testjni_UmengJni
#define _Included_umeng_testjni_UmengJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     umeng_testjni_UmengJni
 * Method:    sayHello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_umeng_testjni_UmengJni_sayHello
  (JNIEnv *env, jclass object){
    return (*env)->NewStringUTF(env,"JNI hahahahahahahaha");
}

#ifdef __cplusplus
}
#endif
#endif

此时运行即可编译.so文件,在build/intermediates/ndk目录下可以找到对应文件:

《Android Studio中jni的使用》 Paste_Image.png

*更多的开发知识,可以关注我的公众号:

《Android Studio中jni的使用》

    原文作者:mymdeep
    原文地址: https://www.jianshu.com/p/be1f7112dfee
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞