Android NDK 指南

本文是关于Android NDK的详细指南,涵盖了使用Android.mk和CMake构建NDK工程的方法,包括独立工具链的设置,如使用obfuscator-llvm进行代码混淆。同时,介绍了构建技巧,如独立构建和快速部署,以及Android.mk和Application.mk中的关键变量和NDK提供的函数宏。文章旨在帮助开发者更好地理解和操作Android NDK工程。

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

Android NDK 指南

前言

编写此文档的用意:

  1. 作为搭建基础 NDK 工程的教程;
  2. 作为入门 NDK 工程的参考手册。

NDK 工程构建

可采用三种方式进行 NDK 工程的构建:

  1. 基于 Make 的 ndk-build,这是传统的 ndk-build 构建方式,使用 Makefile 方式进行构建,简洁高效;
  2. CMake 是新型的构建方式,CMake 具有跨平台的特性,通过 CMake 生成 Makefile 后再进行构建,CMake 的配置文件可读性更高;
  3. 其他编译系统,通过引入其他编译系统可对编译过程进行定制,例如引入 obfuscator-llvm 对源码进行混淆和压缩,增强源代码安全性。

下面是每种构建方式的基础示例,使用 Android Studio 4.0 和 NDK 21 进行如下构建。

Android.mk

基于 Android.mk 的产物为 libfoo.so 的 NDK 基本工程搭建。

在 Android 工程的 src/main 下建立 jni 目录(Android.mk 工程的默认文件目录为 jni,也可指定其他目录进行构建,使用命令 ndk-build -C 目录),工程结构如下:

包含两个 .mk 文件用来描述 NDK 工程,和两个基本的 C++ 语言源文件,结构如下:

src/main
 |
 +-- java
 +-- jni
      |
      +-- Android.mk
      +-- Application.mk
      +-- libfoo.h
      +-- libfoo.cpp

在 Android Studio 的当前 Module 配置中指明 Android.mk 文件路径:

// app-build.gradle

android {
   
  ...
  externalNativeBuild {
   
    ndkBuild {
   
      path 'src/main/jni/Android.mk'
    }
  }
}

编写 Android.mk 文件用于向 NDK 构建系统描述工程的 C/C++ 源文件以及共享库的属性。

# Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# 指定共享库名字,产出物为 libfoo.so
LOCAL_MODULE := foo
# 指定源代码文件,多个源代码文件使用空格分隔,换行在行尾使用 \
LOCAL_SRC_FILES := libfoo.cpp

include $(BUILD_SHARED_LIBRARY)

添加 Application.mk 用于描述 NDK 工程概要设置。

# Application.mk

# 指定生成特定 ABI 的代码
APP_ABI := armeabi-v7a arm64-v8a
APP_OPTIM := debug

在 java 目录创建 Java 类,用于声明 JNI 方法,提供给其他类调用。

// class io.l0neman.mkexample.NativeHandler
public class NativeHandler {
   

  static {
   
    // 加载 libfoo.so 库
    System.loadLibrary("foo");
  }

  public static native String getHello();
}

源代码:

// libfoo.h
#ifndef NDKTPROJECT_LIBFOO_H
#define NDKTPROJECT_LIBFOO_H

#include <jni.h>

extern "C" {
   
// 注册指定 Java 层的 JNI 方法
JNIEXPORT jstring JNICALL
Java_io_l0neman_mkexample_NativeHandler_getHello(JNIEnv *env, jclass clazz);
}

#endif //NDKTPROJECT_LIBFOO_H
// libfoo.cpp
#include "libfoo.h"

jstring Java_io_l0neman_mkexample_NativeHandler_getHello(JNIEnv *env, jclass clazz) {
   
  return env->NewStringUTF("Hello-jni");
}

这样的话就完成了一个基本的 NDK 工程搭建,编译后调用代码即可得到 java 字符串 "Hello-jni"

// MainActivity.java

String hello = NativeHandler.getHello();
  • 提示

Android.mk 和 Application.mk 中可使用的系统变量请参考下文。

Android.mk 只是 Makefile 的片段,对于 Makefile 本身的熟悉有助于深入理解和编写 Android.mk,可参考 Makfile 指南

CMake

使用 CMake 和 Android.mk 在 Android Studio 中的构建步骤类似,如下:

基于 CMake 的产出物为 libfoo.so 的 NDK 基本工程搭建。

在 Android 工程的 src/main 下建立 cpp 目录,工程结构如下:

包含一个 CMakeLists.txt 文件来描述 NDK 工程,和两个基本的 C++ 语言文件。

src/main
 |
 +-- java
     jni
      |
      +-- CMakeLists.txt
      +-- libfoo.h
      +-- libfoo.cpp

在 Android Studio 的当前 Module 配置中指明 CMakeLists.txt 文件路径:

// app/build.gradle

android {
   
  ...
  externalNativeBuild {
   
    cmake {
   
      path 'src/main/cpp/CMakeLists.txt'
    }
  }
}

编写 CMakeLists.txt 文件用于向 NDK 构建系统描述工程的 C/C++ 源文件以及共享库的属性。

# CMakeLists.txt

cmake_minimum_required(VERSION 3.4.3)

add_library(
        # 共享库名字,生产物为 libfoo.so
        foo
        # 编译为共享库 .so
        SHARED
        # 源代码文件,多个文件使用空格分隔或换行
        main.cpp
)

此时将 Android.mk 工程中的 Java 源文件 NativeHandler.java 复制过来,将 libfoo.cpp 和 libfoo.h 内容填入中即可直接编译测试。

独立工具链

有时编译 NDK 工程有一些特殊需求,例如对代码进行混淆,加入第三方编译器 obfuscator-llvm 对 NDK 工程进行编译。这时就需要搭建第三方工具链的编译环境,将它加入 NDK 的一般构建过程中。

下面是一个引入 obfuscator-llvm 编译器编译代码的示例。

obfuscator-llvm 构建

环境:android-ndk-r14b,目前已知此版本可支持 obfuscator-llvm 的编译配置

ndk r14b 下载地址:https://developer.android.google.cn/ndk/downloads/older_releases

  • 首先下载编译器,指定最新版本的 obfuscator-llvm 分支,将仓库克隆至本地
git clone -b llvm-4.0 https://github.com/obfuscator-llvm/obfuscator.git
  • 编译出编译器的可执行文件

过程如下,以下命令 Windows DOS 和 Linux Shell 中可通用:

  1. 进入编译器仓库目录中 cd obfuscator
  2. 创建临时文件目录 mkdir build
  3. 进入临时文件目录 cd build
  4. 使用 CMake 生成 Makefile 或者 Vs 解决方案:

如果没有按照 CMake,可去 CMake 官网下载安装。

cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=OFF ../

CMake 将会自动检测电脑上的编译器环境,如果是 Linux,生成 Makefile,如果 Windows 上安装了 Visual Studio,将生成解决方案文件。

  1. 编译编译器源代码:

Linux 上执行:

make -j4

Windows 平台建议使用 Visual Studio 进行编译,直接打开 build 中的 LLVM.sln,然后生成解决方案(Build Solution)。

编译过程需要持续 30 分钟或更长时间,取决于电脑配置 CPU 性能。

编译过程中有可能出现错误,需要自己解决出现的不同情况,编译完成后将生成所需的 bin 和 lib 目录(Release 中)。

  • 配置 NDK 环境

设原始 NDK 工具链根目录为 android-ndk-r14b。

进入 android-ndk-r14b/toolchains 目录中,复制已存在的 llvm 目录到 ollvm-4.0,Linux 使用 cp llvm ollvm-4.0,Windows 复制文件出现 llvm-副本 后重命名为 ollvm-4.0

Windows 平台将上面编译出来的 bin 和 lib 放入 ollvm-4.0/prebuilt/windows-x86_64 中,Linux 平台放入 ollvm-4.0/prebuilt/linux-x86_64 中࿰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值