Android: 使用CMake 构建 JNI 项目

使用Android Studio 2.2 或更高版本构建JNI项目时默认工具是CMake,最近由于需要编译C文件故尝试了下,确实比 ndk-build方便不少。下面会以android-gpuimage 这个项目为例。

一、下载 NDK 和构建工具
打开SDK管理器:从菜单栏选择 Tools > Android > SDK Manager。或者点击图标 这里写图片描述

这里写图片描述

图来至谷歌开发者中心

下载如图蓝底三项

NDK:这套工具集允许您为 Android 使用 C 和 C++ 代码,并提供众多平台库,让您可以管理原生 Activity 和访问物理设备组件,例如传感器和触摸输入。

CMake:一款外部构建工具,可与 Gradle 搭配使用来构建原生库。如果您只计划使用 ndk-build,则不需要此组件。

LLDB:一种调试程序,Android Studio 使用它来调试原生代码。

二、构建项目

构建支持NDK的项目分两种:
1、第一种是 创建支持 C/C++ 的新项目,这种比较简单,创建新项目时选中 Include C++ Support 复选框。 即可,这里不多说了。如图:
这里写图片描述

创建成功后运行即可看见输出一段字符串。

2、第二种是向现有项目添加 C/C++ 代码,这里以将android-gpuimage 里面的library/jni/yuv-decoder.c添加到我们自己的项目中为例。

首先添加源文件:
(1)从 IDE 的左侧打开 Project 窗格并从下拉菜单中选择 Project 视图。
(2)导航到 您的模块 > src,右键点击 main 目录,然后选择 New > Directory。
(3)为目录输入一个名称(例如 cpp)并点击 OK。
(4)右键点击你刚刚创建的目录,然后选择 New > C/C++ Source File。这里命名:gpuimage-library.c,内容则是上面yuv-decoder.c的内容,请自行拷贝下来。
(5)接着右键点击你刚刚创建的目录,然后选择 New > C/C++ Header File。命名:gpuimage-library.h,内容如下:

#include <jni.h>
#ifndef CAMERA_GPUIMAGE_LIBRARY_H
#define CAMERA_GPUIMAGE_LIBRARY_H
#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT void JNICALL Java_cn_zz_camerasdk_filter_GPUImageNativeLibrary_YUVtoRBGA(JNIEnv *, jobject, jbyteArray, jint, jint, jintArray);
JNIEXPORT void JNICALL Java_cn_zz_camerasdk_filter_GPUImageNativeLibrary_YUVtoARBG(JNIEnv *, jobject, jbyteArray, jint, jint, jintArray);

#ifdef __cplusplus
}
#endif //CAMERA_GPUIMAGE_LIBRARY_H
#endif

Tips: 这里需要注意下:方法名跟之前方法一样,Java_包名_类名_方法名 ,请根据自己项目更改!!!

创建完毕后目录如下:


这里写图片描述

接着创建 CMake 构建脚本:
如果你的原生源文件还没有 CMake 构建脚本,则您需要自行创建一个并包含适当的 CMake 命令。CMake 构建脚本是一个纯文本文件,必须将其命名为 CMakeLists.txt。

(1)从 IDE 的左侧打开 Project 窗格并从下拉菜单中选择 Project 视图。
(2)右键点击 您的模块 的根目录并选择 New > File。
(3)输入“CMakeLists.txt”作为文件名并点击 OK。

编辑CMakeLists.txt内容如下:

# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.

cmake_minimum_required(VERSION 3.4.1)

# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add.library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.

add_library( # Specifies the name of the library.
             gpuimage-library

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/gpuimage-library.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 )

           # 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.
                                  gpuimage-library

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

这里写图片描述

红色部分根据自己项目修改。其中用到的命令可以查看文档:cmake_minimum_required()add_library() find_library()

然后Gradle 文件配置 CMake

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.0"

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
        ndk {
          // Specifies the ABI configurations of your native
          // libraries Gradle should build and package with your APK.
          abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
                   'arm64-v8a'
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    lintOptions {
        abortOnError false
    }

    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

最后添加Java代码调用部分:
该类也是来自android-gpuimage 项目里面。具体效果可以下载查看。

public class GPUImageNativeLibrary {
    static {
        System.loadLibrary("gpuimage-library");
    }

    public GPUImageNativeLibrary() {
    }

    public static native void YUVtoRBGA(byte[] var0, int var1, int var2, int[] var3);

    public static native void YUVtoARBG(byte[] var0, int var1, int var2, int[] var3);
}

配置完毕我们编译运行,注意每次修改native方法名时都要clean,然后重新Make Project。

运行成功后选择 Build > Analyze APK。
从 app/build/outputs/apk/ 目录中选择 APK 并点击 OK。
你会在 APK 分析器窗口的 lib// 下看到 libnative-lib.so。

这里写图片描述

好了,今天的分享就到这了,更多信息可以查看:https://developer.android.com/studio/projects/add-native-code.html?hl=zh-cn#new-project

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值