AS添加JNI支持

JNI入坑

索引:

  1. 旧 NDK 使用姿势(AS 2.2 以下 参考链接:Create hello-JNI with android studio)
  2. 新 NDK 使用方法(AS 2.2及以上 参考链接:Add C and C++ Code to Your Project)

参考:
JNI Tips
(链接均需VPN)


旧 NDK-build:

简单来说分这么几步:

  1. 添加ndk库支持
  2. 在 gradle.properties中添加:

    1
    android.useDeprecatedNdk=true
  3. 在 app级build.gradle中添加:

    1
    2
    3
    4
    5
      defaultConfig {
    ndk {
    moduleName "test-jni" // name the jni lib you want to add
    }
    }
  4. 创建load 静态块,添加待实现native api

    1
    2
    3
    4
    5
    6
    7
    public class JniTest {
    static {
    System.loadLibrary("test-jni");
    }

    public native String getMsgFromJni();
    }

在 目标api所在行停留一会,会出现红色灯泡提示按钮,点击图标,会有Create Function Java_%full class name%_getMsgFromJni选项出现;点击之后会自动创建一个与java目录并列的cpp目录,并在目录下生成test-jni.c文件
具体代码如下:

1
2
3
4
5
6
7
8
9
10
#include <jni.h>

JNIEXPORT jstringJNICALL
Java_com_zealens_face_jnitest_JniTest_getMsgFromJni(JNIEnv
*env, jobject instance)
{

// TODO
return (*env)->NewStringUTF(env, returnValue);
}

说明:

  1. 对于第3行代码:
    AS生成的代码有错误,需将JNICALL与前面的jstring隔开;
  2. 将returnValue修改为常量值(eg:”hello”)

至此,build之后调用API就能得到刚才填入的hello值。


####新CMake

AS现在默认的C++工具已经修改为CMake(需要在SDK-Tools中安装CMake、LLDB、NDK),旧的ndk-build库也可以手动导入

准备工作:

  1. 如果有则移除:
    1
    2
    // Remove this line
    android.useDeprecatedNdk = true
  1. install build tools

(略:创建新的C++support Application)

  1. 向现有项目添加C/C++ 代码:
    a. 新建cpp目录;
    b. 添加cpp文件,代码如下:
1
2
3
4
5
6
7
8
9
10
11
#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_%your test class full name%_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

在欲链接cpp的根目录中(与build.gradle同级)创建文件:CMakeLists.txt,键入如下代码:(各API含义见参考链接末尾部分,或 CMake command

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
native-lib

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
log-lib

# Specifies the name of the NDK library that
# you want CMake to locate.
log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
native-lib

# Links the target library to the log library
# included in the NDK.
${log-lib} )

之后,在同一模块目录上单击右键,选择link c++...,选中欲链接的cpp文件,build.gradle就会生成如下代码:(android模块中)

1
2
3
4
5
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}

此时再调用相应API就可以看到效果了:

1
2
3
4
5
6
7
8
9
10
11
12
13

public class CppTest {
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();

// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
}

pay attention to the lib name

高阶设置请参考手册,这里也只是介绍一个最小的CMake环境


关注公众号“夕识”,雕刻时光,雕刻思维

Powered by KyleCe

Copyright © 2015 - 2019 KyleCe All Rights Reserved.

访客数 : | 访问量 :