Android JNI搭建与实现

May you return with a young heart after years of fighting.
愿你出走半生,归来仍是少年。​​​

1.创建项目与NDK配置

第一步:创建项目
项目名:JNIDemo
包名:com.pfj.jnidemo
第二步:配置NDK环境
下载ndk需要的工具:打开SDKManager 然后选择SDK Tools

下载
需要下载LLDB、CMake、NDK如图。
第三步
下载完成以后打开 File – Project Structure – SDK Location,使用SDK Tools下载成功的NDK。
在这里插入图片描述

2.JNI开发

2.1创建一个 类HelloNDK.java

public class HelloNDK {
    // 动态导入 so 库
    static {
        System.loadLibrary("HelloNDK");
    }
    //创建一个 native 方法,交给C实现
    public native static String helloWorld();
}

2.2创建 C 语言文件,创建 so 库
在命令行中执行如下两个命令:
cd app/src/main/java
javah com.pfj.jnidemo.HelloNDK
(即:javah HelloNDK全类名)
注意:先把HelloNDK的中文注释删掉,再执行命令,否则会报错。
生成了一个com_pfj_jnidemo_HelloNDK.h 文件
然后在main目录下创建cpp目录,并将上面生成的.h文件移动到该目录
com_pfj_jnidemo_HelloNDK.h代码如下:

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

#ifndef _Included_com_pfj_jnidemo_HelloNDK
#define _Included_com_pfj_jnidemo_HelloNDK
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_pfj_jnidemo_HelloNDK
 * Method:    helloWorld
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_pfj_jnidemo_HelloNDK_helloWorld
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

2.3编写 c++ 实现方法
在cpp目录下创建HelloNDK.h(可为空文件)和HelloNDK.cpp文件,并在HelloNDK.cpp编写如下代码:

#include "HelloNDK.h"
#include "com_pfj_jnidemo_HelloNDK.h"

JNIEXPORT jstring JNICALL Java_com_pfj_jnidemo_HelloNDK_helloWorld
(JNIEnv *env, jclass jclass1){

  return env->NewStringUTF("你得到了Native返回数据");
}

2.4创建一个 CMakeLists.txt 文件
在app目录下创建CMakeLists.txt,代码如下:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# 设置构建本机库所需的CMake最低版本。
cmake_minimum_required(VERSION 3.4.1)

#创建并命名一个库,将其设置为STATIC或SHARED,并提供其源代码的相对路径。
#可以定义多个库,CMake会为您构建它们。
#Gradle会自动将共享库与您的APK打包在一起。
add_library( # Sets the name of the library.
           HelloNDK
           # Sets the library as a shared library.
           SHARED
           # Provides a relative path to your source file(s).
        src/main/cpp/HelloNDK.cpp)

#搜索指定的预建库并将路径存储为
#变量。 因为CMake通过以下方式在搜索路径中默认包含系统库
#您只需要指定您要添加的公共NDK库的名称
#CMake验证该库是否存在完成其构建。

find_library( # 设置路径名
            log-lib
            # NDK library name
            log )
            
#指定库CMake应该链接到您的目标库。 您可以链接多个库,例如您在此定义的库
#构建脚本,预构建的第三方库或系统库。
target_link_libraries( # 指定目标库
                    HelloNDK
                     # Links the target library to the log library
                     # included in the NDK.
                     ${log-lib} )

CMakeLists.txt 文件进一步介绍


cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_VERBOSE_MAKEFILE on)
SET(CMAKE_BUILD_TYPE Release)

set(so_DIR ${CMAKE_SOURCE_DIR}/libs)
#生成库的版本与名字
set(VERSION "1_0_0")
set(NAMEKEY "imageinpainting-core")

#生成库完整名字,可通过NAME引用
set(NAME ${NAMEKEY}_${VERSION})

# 第三方库的根路径
set(DEP_LIBS_DIR ${CMAKE_SOURCE_DIR}/../../../deps/android)

### opencv library路径
set(opencv_DIR ${DEP_LIBS_DIR}/opencv3.4.1)

### license library
set(license_DIR ${DEP_LIBS_DIR}/license)

# src easymobile source code root directory
set(SRC_CPP_DIR ${CMAKE_SOURCE_DIR}/../../../src)
set(source_DIR ${SRC_CPP_DIR})
include_directories(${source_DIR})
include_directories(${source_DIR}/include)

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -g ")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -g ")

include_directories(${license_DIR}/include)
add_library(lib_license_so SHARED IMPORTED)
set_target_properties(lib_license_so
        PROPERTIES
        IMPORTED_LOCATION
        ${license_DIR}/libs/${ANDROID_ABI}/libbd_unifylicense.so)


# OpenCV
include_directories(${opencv_DIR}/include)
add_library(lib_opencv_so STATIC IMPORTED)
set_target_properties(lib_opencv_so
        PROPERTIES
        IMPORTED_LOCATION
        ${opencv_DIR}/libs/${ANDROID_ABI}/libopencv_java3.so)

find_library(# 指定系统名字
        log-lib
        # 系统NDK库
        log)

# 所有的cpp源文件
FILE(GLOB MyCSources
        ${source_DIR}/cluster.cpp
        ${source_DIR}/easy_mobile_mia.cpp
        ${source_DIR}/delffpcomparator.cpp
        ${source_DIR}/msvq_mobile.cpp
        ${source_DIR}/searchmobilefea_msvq.cpp
        ${source_DIR}/searchmobilefea_search.cpp
        #jni路径
        src/main/cpp/native_jni.cpp
        )

add_library( # Sets the name of the library.
        ${NAME}
        SHARED
        ${MyCSources}
        )
        
target_link_libraries( # Specifies the target library.
        ${NAME}
        # 目标库与下面库关联,可以使用下面的库
        jnigraphics
        ${log-lib}
        lib_opencv_so
        -Wl,--whole-archive
        -lz
        -Wl,--no-whole-archive
        lib_license_so
        )

2.5引用 CMakeLists.txt 文件
在app目录下的build.gradle中加上如下代码:

..
android {
    compileSdkVersion 28
    buildToolsVersion '28.0.3'
    defaultConfig {
        applicationId "com.pfj.jnidemo"
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        //jni配置
        externalNativeBuild{
            cmake{
                abiFilters 'armeabi-v7a'
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    //jni配置
    externalNativeBuild{
        cmake{
            path 'CMakeLists.txt'
        }
    }
}
..

2.6生成so文件
在这里插入图片描述
2.7运行程序
在这里插入图片描述
得到了C文件返回数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值