首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Android Studio 最新版 JNI 開發全流程:從 Native 方法到 C 實現的完整指南

     編輯:Java 綜合教學

Android Studio 最新版 JNI 開發全流程:從 Native 方法到 C 實現的完整指南

隨著 Android Studio 逐漸棄用 `ndk-build` 轉向 CMake,JNI 開發流程發生重大變化。本文基於最新版 AS (Gradle 4.0+、CMake 3.10+),詳細演示從聲明 `native` 方法到生成 `.so` 庫的標準化流程,並針對常見坑點給出解決方案。

核心流程圖

Java/Kotlin 類聲明 native 方法
        ↓
Build → Make Project 生成 .class
        ↓
javah / javac -h 生成 C/C++ 頭文件 (.h)
        ↓
編寫 .c/.cpp 實現對應函數
        ↓
CMakeLists.txt 配置編譯腳本 (模塊名、源文件、鏈接庫)
        ↓
Gradle 同步 → 自動調用 CMake → 編譯生成 libxxx.so
        ↓
Java/Kotlin 中 System.loadLibrary("xxx") 載入調用

步驟 1:聲明 Native 方法 (建議獨立工具類)

// JniUtil.java
package com.example.jnidemo;

public class JniUtil {
    static {
        System.loadLibrary("native-lib"); // 對應 CMake 模塊名
    }
    public native String getStringFromNative();
}

最佳實踐:不要在 Activity 中聲明 native 方法。獨立類便於單元測試、避免生命周期耦合、生成頭文件時包名更穩定。

步驟 2:生成頭文件

AS 終端執行:

# 進入模塊目錄
cd app
# 生成頭文件至 src/main/cpp (或自定義目錄)
javac -h src/main/cpp src/main/java/com/example/jnidemo/JniUtil.java

產出:`com_example_jnidemo_JniUtil.h`,包含函數簽名:
`JNIEXPORT jstring JNICALL Java_com_example_jnidemo_JniUtil_getStringFromNative(JNIEnv *, jobject);`

步驟 3:編寫 C/C++ 實現

// native-lib.cpp
#include 
#include "com_example_jnidemo_JniUtil.h"

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_jnidemo_JniUtil_getStringFromNative(JNIEnv *env, jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

步驟 4:CMakeLists.txt 核心配置

cmake_minimum_required(VERSION 3.4.1)

# 定義模塊名,對應 System.loadLibrary("native-lib")
add_library(native-lib SHARED native-lib.cpp)

# 查找 Android 日志庫
find_library(log-lib log)

# 鏈接
target_link_libraries(native-lib ${log-lib})

步驟 5:Gradle 整合 (build.gradle - 模塊級)

android {
    ...
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
    // 指定 NDK 版本 (可選,建議鎖定)
    ndkVersion "21.4.7075529"
}

常見坑點與解決方案

進階:Kotlin 調用、日志輸出、第三方庫鏈接

  • Kotlin 同樣用 `external fun` + `companion object { init { System.loadLibrary(...) } }`。
  • C++ 打印日志:`__android_log_print(ANDROID_LOG_DEBUG, "JNI_TAG", "msg: %s", str);` 需鏈接 `log` 庫。
  • 引入預編譯 `.so`:`add_library(imported-lib SHARED IMPORTED)` + `set_target_properties(... PROPERTIES IMPORTED_LOCATION ...)` + `target_link_libraries(native-lib imported-lib)`。

總結

現代 Android JNI 開發核心是 **CMake + Gradle 深度整合**。掌握「聲明 → 生成頭文件 → 實現 → CMake 配置 → Gradle 同步」標準流程,並熟悉 ABI、NDK 版本、符號導出等關鍵點,即可高效構建高性能原生模塊。建議將 JNI 層封裝為獨立 Library Module,實現多項目複用與獨立測試。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題原因解決
UnsatisfiedLinkError庫名不匹配 / ABI 不支援1. `loadLibrary` 名 = `add_library` 名 2. `defaultConfig.ndk.abiFilters` 指定 arm64-v8a/armeabi-v7a
找不到頭文件包名變更 / 生成路徑錯誤重新執行 `javac -h`,或在 CMake 中 `include_directories(${CMAKE_SOURCE_DIR}/../java)`
CMake 編譯失敗NDK 版本不兼容 / CMake 版本過低Gradle 中鎖定 `ndkVersion`、`cmake.version`
符號重複定義多模塊編譯同名 .c 文件模塊名唯一、源文件路徑隔離