android ndk root,Android Studio NDK 初尝

NDK 适合的场景:

1 . 重要核心代码保护。由于java层代码很容易反编译,而C/C++代码反汇编难度很大,所以对于重要的代码,可以使用C/C++来编写,Android去调用即可。

2 . Android中需要用到第三方的C/C++库。由于很多优秀的第三方库(比如FFmpeg)都是使用C/C++来编写的,我们想要使用它们,就必须通过NDK的方式来操作。

3 . 便于代码的移植。比如我们对于一些核心的公共组件(比如微信开源的的Mars),可能需要写一套代码在多个平台上运行(比如在Android和iOS上共用一个库),那么就需要选用NDK的方式。

4 . 对于音视频处理、图像处理这种计算量比较大追求性能的场景,也需要使用到NDK。

什么是JNI

JNI的全称是Java Native Interface,它允许Java语言可以按照一定的规则去调用其他语言,与其进行交互。

编写Java代码(.java) —————> 编译生成字节码文件(.class) —————> 产生C头文件(.h) —————> 编写jni实现代码(.c) —————> * 编译成链接库(.so)**

什么是CMake

CMake是一款开源的跨平台自动化构建系统,它通过CMakeLists.txt来声明构建的行为,控制整个编译流程.

搭建NDK 环境

Tools->SDK Manager->System Settings->Android SDK ->SDK Tools->勾选CMake、LLDB、NDK 进行下载安装

9ad7c7e4eebf?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

NDK 环境变量配置:

export PATH=${PATH}:~/Library/Android/sdk/platform-tools

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home

export JAVA_HOME

CLASS_PATH=$JAVA_HOME/lib

ANDROID_NDK_ROOT=/Users/feifei/Library/Android/sdk/ndk-bundle

PATH=${PATH}:${JAVA_HOME}/bin

PATH=${PATH}:${ANDROID_NDK_ROOT}

新建NDK 工程,编译so库

新建工程时勾选 include C++ support

9ad7c7e4eebf?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

9ad7c7e4eebf?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

新建完有如下几个变化:

main目录下增加了一个cpp文件夹,用来存放编写的cpp文件

app目录下 增加了一个CMakeList.txt文件,用于指导CMake构建项目

9ad7c7e4eebf?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

buid.gradle中新增了NDK相关的配置

9ad7c7e4eebf?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

声明native函数

在任何一个java文件 用native关键字声明nativie函数,但最好统一发放到一个工具类中,这样方便管理。

然后在声明的native方法上面,点击option+Enter键,会自动在cpp目录下hello-lib.cpp中生成函数的实现体

JNIUtils.java

package com.example.myndk;

public class JNIUtils {

static {

System.loadLibrary("hello-lib");

}

public native String stringFromJNI();

public native void writeFile(String filePath);

public native void operationArray(int[]args);

public native void operationArray2(int[]args);

}

生成的navtive方法实现类:

//

// Created by 飞飞 on 2018/6/12.

//

#include

#include

#include

#include

#define LOG "JNILOG" // 这个是自定义的LOG的TAG

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG,__VA_ARGS__) // 定义LOGD类型

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG,__VA_ARGS__) // 定义LOGI类型

#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG,__VA_ARGS__) // 定义LOGW类型

#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG,__VA_ARGS__) // 定义LOGE类型

#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG,__VA_ARGS__) // 定义LOGF类型

JNIEXPORT jstring JNICALL

Java_com_example_myndk_JNIUtils_stringFromJNI(JNIEnv *env, jobject instance) {

// TODO

LOGD("stringFromJNI was called");

return (*env)->NewStringUTF(env, "Hello World");

}

这里存在一个问题,初次生成,AndroidStudio会创建一个jni文件夹,然后在里面创建hello-lib.cpp文件,并且自动生成对应的C代码,但是,由于我们在CMakeLists.txt中指定的路径为src/main/cpp/hello-lib.cpp,所以我们这里直接将我们的src/main/jni/hello-lib.cpp中的代码拷贝到rc/main/cpp/hello-lib.cpp中,并将jni目录删除即可。

buld Project,会在如下目录生成so

9ad7c7e4eebf?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

在另一个工程中使用so库

在main目录中,建立一个与java平级的jniLibs目录。将

编译生成的armeabi-v7a、x86等相关文件夹拷贝到jniLibs目录中。

9ad7c7e4eebf?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

java目录下,建立JNIUtils所声明的包名目录,将JNIUtils.java拷贝到com.example.myndk 目录下。(注意:在引用so的工程中,JNIUtils.java所处的目录结构一定要与原始包名一致,否则会报错)

在工程中使用JNIUtils

public class MainActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

TextView tv_title = (TextView) findViewById(R.id.tv_title);

tv_title.setText(new JNIUtils().stringFromJNI());

}

}

关于CMakeList.txt

# For more information about using CMake with Android Studio, read the

# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

add_library(hello-lib SHARED src/main/cpp/hello-lib.c)

find_library(log-lib log)

target_link_libraries(hello-lib ${log-lib})

cmake_minimum_required(VERSION 3.4.1) 用来设置在编译本地库时我们需要的最小的cmake版本,AndroidStudio自动生成,我们几乎不需要自己管

add_library用来设置编译生成的本地库的名字为hello-lib,SHARED表示编译生成的是动态链接库(这个概念前面已经提到过了),src/main/cpp/hello-lib.cpp表示参与编译的文件的路径,这里面可以写多个文件的路径。

find_library 是用来添加一些我们在编译我们的本地库的时候需要依赖的一些库,由于cmake已经知道系统库的路径,所以我们这里只是指定使用log库,然后给log库起别名为log-lib便于我们后面引用,此处的log库是我们后面调试时需要用来打log日志的库,是NDK为我们提供的。

target_link_libraries 是为了关联我们自己的库和一些第三方库或者系统库,这里把我们把自己的库hello-lib库和log库关联起来。

参考文章:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值