Android JNI方法

本文详细介绍了在Android环境下,通过CMake和NDK两种方式实现C/C++与Java代码的交互。包括配置环境、编写源代码、生成动态库及在Java中加载调用的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思想:

c文件或者c++文件里的实现方法被ndk或是cmake编译为动态库,java代码中加载动态库且声明方法为native就可以链接到c/c++的实现。

方法一 **** cmake方式

思路
1)build.gradle配好CMakeLists.txt的路径
2)CMakeLists里写好库名称、c源文件路径
3)按JNI规范写好c源文件
4)调用:加载库 声明native

不勾选c++ support,自己新建CMakelists.txt
1、main路径下新建cpp文件夹,新建.c文件,按jni规则写函数
2、app路径下新建CMakelists.txt

cmake_minimum_required(VERSION 3.4.1)

add_library( # Sets the name of the library.
             tryCMakeLists

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/test.c )

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 )

target_link_libraries( # Specifies the target library.
                       tryCMakeLists

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

写明库的名称、source file路径
3、app下的build.gradle加入两处externalNativeBuild

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "grl.com.jnicmakelists"
        minSdkVersion 26
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

4、以上完成了实现部分,之后java代码中可以 加载库+native声明 调用c代码。

demo项目路径AS-study/JNIcmakelists

ps:

1、新建工程时,勾选include c++ support
2、Java调用c++代码三个步骤:加载static代码块的库、声明native方法、调用JNI方法
3、由于勾选c++ support,自动生成CMakeLists.txt,将生成的native-lib.cpp,生成native-lib动态库。
4、在app的build.gradle里有两处externalNativeBuild
学习链接:
https://blog.youkuaiyun.com/quwei3930921/article/details/78820991

pps.

可以在app/src/main/cpp路径下新建自己的cpp文件或是c文件,在CMakeLists.txt中修改source file路径即可。当然要按照jni的命名规则。

demo项目路径AS-study/ndkTest

方法二 **** ndk方式

思路
1)app的build.gradle里配好ndk的moduleName
2)src/main/jni目录新建源文件(ndk应该是固定加载jni路径下的文件)
3)调用

1、SDK Manag安装NDK
2、Project Structure里配置NDK路径
3、新建java类,加载包+定义native方法

package grl.com.myjnistudy;

public class JniStudy {
    static {
        System.loadLibrary("StudyJNI");
    }

    public static native String getStr();
}

4、app的build.gradle里的defaultConfig添加(库名与上一步一致)

ndk {
            moduleName "StudyJNI"
        }

5、打开as的terminal,进入app/src/main/java/grl.com.myjnistudy(可以直接拖动文件夹到terminal)
用javac命令编译定义了native方法的java文件

:myjnistudy geng_rl$ javac JniStudy.java

出现JniStudy.class文件
6、terminal路径退到包外,即app/src/main/java
javah命令生成.h文件
grl_com_myjnistudy_JniStudy.h

java geng_rl$ javah -jni grl.com.myjnistudy.JniStudy
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class grl_com_myjnistudy_JniStudy */

#ifndef _Included_grl_com_myjnistudy_JniStudy
#define _Included_grl_com_myjnistudy_JniStudy
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     grl_com_myjnistudy_JniStudy
 * Method:    getStr
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_grl_com_myjnistudy_JniStudy_getStr
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

7、main下new->folder->jni folder新建文件夹,名为jni
Change 。。。Location勾选上
把grl_com_myjnistudy_JniStudy.h拖入jni文件夹
8、在jni文件夹新建c++源文件,文件名任意
例:study.cpp
1)include .h文件
2)实现.h文件里的方法

#include "grl_com_myjnistudy_JniStudy.h"

JNIEXPORT jstring JNICALL Java_grl_com_myjnistudy_JniStudy_getStr
  (JNIEnv * env, jclass){
  return (*env).NewStringUTF("hello study");
  }

9、由于ndk报错在gradle.properties加入
android.deprecatedNdkCompileLease=1584204476879
(加入android.useDeprecatedNdk=true没有用)
10、编译so库成功的话
app/build/intermediates会生成ndk目录,debug/lib下有各个架构的so库

demo项目路径AS-study/MyJniStudy

方法三 **** ndk-build命令

思路
1)jni文件夹写好源文件、Android.mk、Application.mk
2)ndk-build生成so库
3)app的build.gradle将so库的路径配到sourceSets
4)调用

1、 jni文件夹,按jni命名规则写.c文件

2、 在jni文件夹写Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := StudyJNI

LOCAL_SRC_FILES := ndkdemotest.c

include $(BUILD_SHARED_LIBRARY)

3、 在src文件夹下新建Application.mk

APP_ABI := all

4、 在terminal进入jni文件夹,执行ndk-build

ruolindeMacBook-Pro:jni geng_rl$ ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.    
Android NDK: WARNING: APP_PLATFORM android-16 is higher than android:minSdkVersion 1 in /Users/geng_rl/09-VideoChatGroup/AS-study/MyJniStudy/app/src/main/AndroidManifest.xml. NDK binaries will *not* be compatible with devices older than android-16. See https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md for more information.    
[arm64-v8a] Compile        : StudyJNI <= ndkdemotest.c
[arm64-v8a] SharedLibrary  : libStudyJNI.so
[arm64-v8a] Install        : libStudyJNI.so => libs/arm64-v8a/libStudyJNI.so
[armeabi-v7a] Compile thumb  : StudyJNI <= ndkdemotest.c
[armeabi-v7a] SharedLibrary  : libStudyJNI.so
[armeabi-v7a] Install        : libStudyJNI.so => libs/armeabi-v7a/libStudyJNI.so
[x86] Compile        : StudyJNI <= ndkdemotest.c
[x86] SharedLibrary  : libStudyJNI.so
[x86] Install        : libStudyJNI.so => libs/x86/libStudyJNI.so
[x86_64] Compile        : StudyJNI <= ndkdemotest.c
[x86_64] SharedLibrary  : libStudyJNI.so
[x86_64] Install        : libStudyJNI.so => libs/x86_64/libStudyJNI.so

效果在main文件夹生成libs文件夹,放着各个架构的so库
5、 App的build.gradle的android{}里加入

sourceSets{
        main{
            jniLibs.srcDirs=["src/main/libs"]
        }
    }

6、clean project,make project

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值