android studio 下如何配置JNI环境

来源:互联网 发布:妮维雅 爽肤水 知乎 编辑:程序博客网 时间:2024/06/14 16:58

android stuido 下如何配置JNI环境

版本:Android stuido 2.2 windows 10操作系统

网上很多都是基于早期的eclipse环境配置的,studio的很少。以下是我亲测可用的一个详细过程。

安装配置NDK

一般如果你是第一次做jni的开发,studio的环境应该是没有ndk的,需要安装。在tools-android-sdk manager,进入sdk-tools选项,然后选中NDK进行安装。

这里写图片描述

这里写图片描述

默认安装在了
C:\android\sdk\android-sdk-windows\ndk-bundle

然后配置下环境变量:
新增NDK_ROOT,value为:
C:\android\sdk\android-sdk-windows\ndk-bundle

然后在path中增加%NDK_ROOT%

这里写图片描述

这里写图片描述

编写测试工程

新建一个工程,名为ssl_socket,package的全路径是com.example.pony.ssl_socket(很重要,后面会用到)。

我的MainActivity.java源码如下:

package com.example.pony.ssl_socket;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;public class MainActivity extends AppCompatActivity {    private static final String TAG = "MainActivity";    //声明native方法    public native String getStringFromNative();//    static表示在系统第一次加载类的时候,先执行这一段代码,在这里表示加载动态库libHelloWorldJni.so文件    static    {        Log.i(TAG, "loadLibrary");        System.loadLibrary("helloNDK");    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Log.i(TAG, "onCreate");        Log.i(TAG, getStringFromNative());    }}

public native String getStringFromNative();
这一行是声明一个native方法,也是我们一会在.c文件中要实现的方法。

System.loadLibrary(“helloNDK”);
这是让类启动时,加载名为helloNDK的模块,这是我们的jni模块名,这个名字和后面ndk编译时指定的名字一致。


编辑gradle.properties文件,增加:
android.useDeprecatedNdk=true


编辑app下的build.gradle,增加:

ndk {            moduleName "helloNDK" // <-- This is the name of my C++ module!            abiFilters "armeabi", "armeabi-v7a", "x86"//            cFlags "-DANDROID_NDK -D_DEBUG DNULL=0"   // Define some macros//            ldLib编辑呢编辑s "EGL", "GLESv3", "dl", "log"       // Link with these //            stl "stlport_shared"                      // Use shared stlport library        }

完整如下:

apply plugin: 'com.android.application'android {    compileSdkVersion 24    buildToolsVersion "24.0.0"    defaultConfig {        applicationId "com.example.pony.ssl_socket"        minSdkVersion 16        targetSdkVersion 24        versionCode 1        versionName "1.0"        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"        ndk {            moduleName "helloNDK" // <-- This is the name of my C++ module!            abiFilters "armeabi", "armeabi-v7a", "x86"//            cFlags "-DANDROID_NDK -D_DEBUG DNULL=0"   // Define some macros//            ldLib编辑呢编辑s "EGL", "GLESv3", "dl", "log"       // Link with these libraries!,makefile里链接的库//            stl "stlport_shared"                      // Use shared stlport library        }    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }}dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {        exclude group: 'com.android.support', module: 'support-annotations'    })    compile 'com.android.support:appcompat-v7:24.0.0'    compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha4'    testCompile 'junit:junit:4.12'}

abiFilters是指明支持那些目标平台(ABI)。在Android系统上,每一个CPU架构对应一个ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64等。如果不加abiFilters这个选项,会生成所有abi平台的so文件


build-make project,编译一下。这里可能会有疑问,上面的代码应该会报错呀,模块和方法明明都没有! 其实可以编译过的,你可以试下。

编译完后,会生成class文件。我的路径是:

d:\study\android\projects\SSL_Socket\app\build\intermediates\classes\debug\com\example\pony\ssl_socket\

其中com\example\pony\ssl_socket\是包名对应的路径。


打开studio的terminal,进入工程下的src/main目录下。然后执行:

javah -d jni -classpath C:\android\sdk\android-sdk-windows\platforms\android-24\android.jar;C:\android\sdk\android-sdk-windows\extras\android\support\v7\appcompat\libs\android-support-v7-appcompat.jar;C:\android\sdk\android-sdk-windows\extras\android\support\v4\android-support-v4.jar;..\..\build\intermediates\classes\debug com.example.pony.ssl_socket.MainActivity

这里写图片描述

命令有点长,拆开了分析:

javah是生成头文件需要的工具,-d jni表示在工程下生成jni目录,紧接着,

C:\android\sdk\android-sdk-windows\platforms\android-24\android.jar
指明android.jar路径。根据你自己的电脑相应修改。

C:\android\sdk\android-sdk-windows\extras\android\support\v7\appcompat\libs\android-support-v7-appcompat.jar;
指明依赖的v7库,这个是因为你的类继承了AppCompatActivity。

同理指明v4库,
C:\android\sdk\android-sdk-windows\extras\android\support\v4\android-support-v4.jar

如果不指明这些库,会下面这样的错误:

这里写图片描述

路径都根据自己的电脑相应修改


命令运行成功后,会生成jni目录和一个头文件。

这里写图片描述

头文件的源码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_pony_ssl_socket_MainActivity */#ifndef _Included_com_example_pony_ssl_socket_MainActivity#define _Included_com_example_pony_ssl_socket_MainActivity#ifdef __cplusplusextern "C" {#endif#undef com_example_pony_ssl_socket_MainActivity_BIND_ABOVE_CLIENT#define com_example_pony_ssl_socket_MainActivity_BIND_ABOVE_CLIENT 8L#undef com_example_pony_ssl_socket_MainActivity_BIND_ADJUST_WITH_ACTIVITY#define com_example_pony_ssl_socket_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L#undef com_example_pony_ssl_socket_MainActivity_BIND_ALLOW_OOM_MANAGEMENT#define com_example_pony_ssl_socket_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L#undef com_example_pony_ssl_socket_MainActivity_BIND_AUTO_CREATE#define com_example_pony_ssl_socket_MainActivity_BIND_AUTO_CREATE 1L#undef com_example_pony_ssl_socket_MainActivity_BIND_DEBUG_UNBIND#define com_example_pony_ssl_socket_MainActivity_BIND_DEBUG_UNBIND 2L#undef com_example_pony_ssl_socket_MainActivity_BIND_EXTERNAL_SERVICE#define com_example_pony_ssl_socket_MainActivity_BIND_EXTERNAL_SERVICE -2147483648L#undef com_example_pony_ssl_socket_MainActivity_BIND_IMPORTANT#define com_example_pony_ssl_socket_MainActivity_BIND_IMPORTANT 64L#undef com_example_pony_ssl_socket_MainActivity_BIND_NOT_FOREGROUND#define com_example_pony_ssl_socket_MainActivity_BIND_NOT_FOREGROUND 4L#undef com_example_pony_ssl_socket_MainActivity_BIND_WAIVE_PRIORITY#define com_example_pony_ssl_socket_MainActivity_BIND_WAIVE_PRIORITY 32L#undef com_example_pony_ssl_socket_MainActivity_CONTEXT_IGNORE_SECURITY#define com_example_pony_ssl_socket_MainActivity_CONTEXT_IGNORE_SECURITY 2L#undef com_example_pony_ssl_socket_MainActivity_CONTEXT_INCLUDE_CODE#define com_example_pony_ssl_socket_MainActivity_CONTEXT_INCLUDE_CODE 1L#undef com_example_pony_ssl_socket_MainActivity_CONTEXT_RESTRICTED#define com_example_pony_ssl_socket_MainActivity_CONTEXT_RESTRICTED 4L#undef com_example_pony_ssl_socket_MainActivity_MODE_APPEND#define com_example_pony_ssl_socket_MainActivity_MODE_APPEND 32768L#undef com_example_pony_ssl_socket_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING#define com_example_pony_ssl_socket_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L#undef com_example_pony_ssl_socket_MainActivity_MODE_MULTI_PROCESS#define com_example_pony_ssl_socket_MainActivity_MODE_MULTI_PROCESS 4L#undef com_example_pony_ssl_socket_MainActivity_MODE_NO_LOCALIZED_COLLATORS#define com_example_pony_ssl_socket_MainActivity_MODE_NO_LOCALIZED_COLLATORS 16L#undef com_example_pony_ssl_socket_MainActivity_MODE_PRIVATE#define com_example_pony_ssl_socket_MainActivity_MODE_PRIVATE 0L#undef com_example_pony_ssl_socket_MainActivity_MODE_WORLD_READABLE#define com_example_pony_ssl_socket_MainActivity_MODE_WORLD_READABLE 1L#undef com_example_pony_ssl_socket_MainActivity_MODE_WORLD_WRITEABLE#define com_example_pony_ssl_socket_MainActivity_MODE_WORLD_WRITEABLE 2L#undef com_example_pony_ssl_socket_MainActivity_DEFAULT_KEYS_DIALER#define com_example_pony_ssl_socket_MainActivity_DEFAULT_KEYS_DIALER 1L#undef com_example_pony_ssl_socket_MainActivity_DEFAULT_KEYS_DISABLE#define com_example_pony_ssl_socket_MainActivity_DEFAULT_KEYS_DISABLE 0L#undef com_example_pony_ssl_socket_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL#define com_example_pony_ssl_socket_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L#undef com_example_pony_ssl_socket_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL#define com_example_pony_ssl_socket_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L#undef com_example_pony_ssl_socket_MainActivity_DEFAULT_KEYS_SHORTCUT#define com_example_pony_ssl_socket_MainActivity_DEFAULT_KEYS_SHORTCUT 2L#undef com_example_pony_ssl_socket_MainActivity_RESULT_CANCELED#define com_example_pony_ssl_socket_MainActivity_RESULT_CANCELED 0L#undef com_example_pony_ssl_socket_MainActivity_RESULT_FIRST_USER#define com_example_pony_ssl_socket_MainActivity_RESULT_FIRST_USER 1L#undef com_example_pony_ssl_socket_MainActivity_RESULT_OK#define com_example_pony_ssl_socket_MainActivity_RESULT_OK -1L#undef com_example_pony_ssl_socket_MainActivity_MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS#define com_example_pony_ssl_socket_MainActivity_MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS 65534L#undef com_example_pony_ssl_socket_MainActivity_HONEYCOMB#define com_example_pony_ssl_socket_MainActivity_HONEYCOMB 11L#undef com_example_pony_ssl_socket_MainActivity_MSG_REALLY_STOPPED#define com_example_pony_ssl_socket_MainActivity_MSG_REALLY_STOPPED 1L#undef com_example_pony_ssl_socket_MainActivity_MSG_RESUME_PENDING#define com_example_pony_ssl_socket_MainActivity_MSG_RESUME_PENDING 2L/* * Class:     com_example_pony_ssl_socket_MainActivity * Method:    getStringFromNative * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_pony_ssl_1socket_MainActivity_getStringFromNative  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif

重点是Java_com_example_pony_ssl_1socket_MainActivity_getStringFromNative这个方法的声明。它的规则是

Java_ + 类的全限定名,用下划线进行分隔 + 方法名,

这样jvm运行的时候根据这个命名规则去找到对应的native方法。

然后在jni目录新建一个jni.c文件(名字随便取),源码如下:

#include <jni.h>/* Header for class com_example_pony_ssl_socket_MainActivity */#ifndef _Included_com_example_pony_ssl_socket_MainActivity#define _Included_com_example_pony_ssl_socket_MainActivity#ifdef __cplusplusextern "C" {#endifJNIEXPORT jstring JNICALL Java_com_example_pony_ssl_1socket_MainActivity_getStringFromNative        (JNIEnv *env, jobject jobj){    return (*env)->NewStringUTF(env,"Hello From JNI!");}#ifdef __cplusplus}#endif#endif

所有的本地方法的第一个参数都是指向JNIEnv结构的。这个结构是用来调用JNI函数的。


编辑运行,可以在输出窗口看到:

Hello From JNI!

同时,c文件也生成了.so文件:

这里写图片描述

0 0
原创粉丝点击