Android Studio中NDK的配置使用示例

使用ndk-build命令手动配置生成so共享库

正确步骤:首先生成so共享库,然后再配置到当前工程模块中进行引用

说明:Android Studio 2.2 CMake只支持64位系统(stackflow中详细说明),所以只能使用ndk-build命令手动生成so共享库(自己32位电脑zaza,没办法),CMake方式的可以查看文章后面提供的参考连接,同时也提供了谷歌官方的在线参考文档。

1. 使用native关键字来声明本地方法

HelloJni.java

package com.shellever.hellojni;

public class HelloJni {

    // A native method that is implemented by the 'hello-jni' native library (libhello-jni.so)
    public native static String getStringFromJni();
}

2. 使用JDK工具javah命令来自动创建头文件(.h)

2.1 切换工程面板为Android界面,选择app目录右键选择/NEW/Folder/JNI Folder来创建一个jni目录,此时会出现一个跟java同级的cpp目录

javah_new_jni_folder_cpp_android.png

2.2 切换工程面板为Project界面,则会出现一个跟java同级的jni目录

javah_new_jni_folder_jni_project.png

2.3 使用javah命令来生成头文件的操作如下:

> cd ./app/src/main/java
> javah -d ../jni com.shellever.hellojni.HelloJni

命令终端Terminal中javah命令详细执行情况如下:

javah_d_jni.png

执行完javah命令后会在jni目录中生成.h头文件(com_shellever_hellojni_HelloJni.h):

javah_d_jni_h.png

头文件内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_shellever_hellojni_HelloJni */

#ifndef _Included_com_shellever_hellojni_HelloJni
#define _Included_com_shellever_hellojni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_shellever_hellojni_HelloJni
 * Method:    getStringFromJni
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_shellever_hellojni_HelloJni_getStringFromJni
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

3. 创建源文件并实现头文件中声明的方法(.c/.cpp)

切换工程面板至Project界面,并选中/app/src/main/jni目录,右键选择/NEW/C/C++ Source File来创建一个与头文件同名的.c源文件(或者.cpp源文件)

javah_new_jni_file_c.png

完整的源文件实现代码如下:

//
// Created by shellever on 12/16/2016.
//

#include "com_shellever_hellojni_HelloJni.h"

// D:\MySoftware\MyDevelopment\Android\Sdk\ndk-bundle\platforms\android-17\arch-arm\usr\include\jni.h

JNIEXPORT jstring JNICALL Java_com_shellever_hellojni_HelloJni_getStringFromJni
  (JNIEnv *env, jclass clazz)
{
    // In C code
    return (*env)->NewStringUTF(env, "Hello from JNI!");

    // In C++ code
    // return env->NewStringUTF("Hello from JNI!");
}

4. 编写mk编译文件

4.1 Android.mk
切换工程面板至Project界面,并选中/app/src/main/jni目录,右键选择/NEW/File来创建Android.mk编译文件,配置内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := com_shellever_hellojni_HelloJni.c

include $(BUILD_SHARED_LIBRARY)

4.2 Application.mk
切换工程面板至Project界面,并选中/app/src/main/jni目录,右键选择/NEW/File来创建Application.mk编译文件,配置内容如下:

# Define the target architecture to be ARM or other.
#APP_ABI := all
#APP_ABI := arm64-v8a armeabi armeabi-v7a mips mips64 x86 x86_64
APP_ABI := arm64-v8a armeabi armeabi-v7a

5. 使用NDK工具ndk-build命令生成so共享库

使用ndk-build命令来生成头文件的操作如下:

> cd ../jni
> ndk-build

命令终端Terminal中ndk-build命令详细执行情况如下:

ndk_build_hello_jni_detail.png

命令ndk-build执行成功后会生成与jni同级的libsobj两个目录(可以手动删除掉obj目录):

ndk_build_hello_jni_folder_file.png

6. 将so共享库配置到当前工程模块(app)中进行引用

/app/build.gradle配置文件中配置ndk-build命令所生成的so共享库路径,或者直接创建一个jniLibs目录:/app/src/main/jniLibs/,然后将so库拷贝到此目录下即可,这样就不再需要指定libs路径了。详细配置如下:

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"
    defaultConfig {
        applicationId "com.shellever.hellojni"
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        // Specify the shared library
        sourceSets {
            main {
                // 1st step: MUST disable automatic ndk-build call
                jni.srcDirs = []

                // 2nd step: MUST specify the .so path (/app/src/main/libs)
                jniLibs.srcDirs = ['src/main/libs']     // Default: /app/libs
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

另一种libs路径配置方式:

// Config here
sourceSets.main {
    jni.srcDirs = []    // MUST disable automatic ndk-build call firstly
    jniLibs.srcDir "src/main/libs"      // MUST specify the .so path secondly
}

7. 演示结果

hello_from_jni.gif

Reference

Android Studio 2.2 更方便地创建JNI项目-CMake
Getting Started with the NDK (Google Official)
googlesamples/android-ndk

源码参考

HelloJni

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容