Linux下NDK编译与Android Studio的NDK

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liny000/article/details/83020530

**

1.Linux下NDK编译:

编译的so可用于Android Studio进行链接
1.下载ndk:https://developer.android.google.cn/ndk/downloads/
在这里插入图片描述
2.解压
3.配置系统环境变量
#vim /etc/profile 在文件末尾添加如下
export ANDROID_NDK=“ndk路径”
export PATH="$ANDROID_NDK:$PATH"
4.更新系统变量
#source /etc/profile
5.检查ndk环境配置正确与否
#ndk-build //出现如下界面即配置成功
AndroidNDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable topoint to it.
/xxx:
* Android NDK: Aborting . Stop.

NDK编译so:

//ndk-build命令 根据jni目录下的Android.mk进行编译
#mkdir jni
#cd jni
例子如下:
#vim Android.mk

//my-dir宏返回Android.mk所在位置 即将LOCAL_PATH赋值
LOCAL_PATH:=$(call my-dir)
//清理LOCAL_XXX变量的值
include $(CLEAR_VARS)
//模块名字
LOCAL_MODULE :=testC
//打包给模块的C/C++源码 头文件不用列出 此源文件可以用具体路径表示
LOCAL_SRC_FILES:=testC.cpp
//编译输出 STATIC为静态库 SHARED为动态库 BUILD_EXECUTABLE为可执行程序
include $(BUILD_SHARED_LIBRARY)

#vim testC.h

#ifndef TESTC_H
#define TESTC_H
int testC();
#endif

#vim testC.cpp

#include "testC.h"
int testC(){
    return 6;
}

//ndk-build编译 APP_ABI为编译输出的不同cpu架构的so
#ndk-build APP_ABI=“armeabi armeabi-v7a arm64-v8a x86 x86_64”
在jni同级路径下生成libs目录和obj目录(libs下即为刚刚编译的so)

NDK编译so并依赖第三方so:
此时将刚刚编译的libtestC.so作为第三方so
#vim testCC.h

#ifndef TESTCC_H
#define TESTCC_H
#include "testC.h"
int testCC();
#endif

#vim testCC.cpp

#include "testCC.h"
int testCC(){
    int a= testC();
    if(a==6)
        return 66;
     return 0;
}

#vim Android.mk


LOCAL_PATH:=$(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE :=testC
//因为链接第三方库,此时源文件为so
LOCAL_SRC_FILES:=libtestC.so
//链接时为预编译
include $(PREBUILT_SHARED_LIBRARY)



include $(CLEAR_VARS)
LOCAL_MODULE :=testCC
LOCAL_SRC_FILES:=testCC.cpp
//链接的第三方库
LOCAL_SHARED_LIBRARIES:=testC
include $(BUILD_SHARED_LIBRARY)

#ndk-build APP_ABI=“armeabi armeabi-v7a arm64-v8a x86 x86_64”

**

2.Android Studio ndk-build

**
SDK manager 安装ndk
在这里插入图片描述

项目设置里查看ndk下载路径
在这里插入图片描述
在这里插入图片描述

SDKmanager External Tools 设置编译命令 javah和ndk-build
javah 根据java class 生成对应的JNI的头文件.h
ndk-build 依据JNI的头文件实现的.cpp生成对应的so

在这里插入图片描述

Program: $JDKPath$/bin/javah
Parameters: -encoding UTF-8 -d ../jni -jni $FileClass$
Working directory: $SourcepathEntry$\..\java

在这里插入图片描述

//program为ndk路径 + ndb-build
Program: G:\Android\Sdk\ndk-bundle\ndk-build.cmd
Parameters: NDK_LIBS_OUT=$ModuleFileDir$/src/main/jniLibs
Workingdirectory: $ModuleFileDir$\src\main

在这里插入图片描述

在这里插入图片描述

jni目录下编写 Android.mk,以及对javah命令产生的.h进行函数实现(编写.cpp)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

3.Android Studio 链接Linux下NDK编译的so

将视图切换为Project 新建libs来存放链接的so
在这里插入图片描述

编写CmakeList.txt

cmake_minimum_required(VERSION 3.4.1)
#定义变量ProjectRoot为工程根目录
set(ProjectRoot G:/Android/AndroidStudioProjects/MyApplication)
#将native-lib加入到编译源中
add_library( native-lib SHARED src/main/cpp/native-lib.cpp )
 #动态方式加载 libtestC.so
add_library(testC SHARED IMPORTED)
#设置链接so的路径,${ANDROID_ABI}为so文件的cpu架构类型
set_target_properties(testC  PROPERTIES IMPORTED_LOCATION ${ProjectRoot}/app/libs/${ANDROID_ABI}/libtestC.so)
target_link_libraries(native-lib testC)

native-lib.cpp引用so的头文件,调用函数
在这里插入图片描述

4.Android Studio 链接JNI的.h和.cpp生成的so

在这里插入图片描述

javah命令生成NdkTest的JNI的头文件

在这里插入图片描述
实现.cpp
在这里插入图片描述

ndk-build命令生成so 拷贝到指定的库目录 (我指定的是libs build.gradle里指定)
//调用函数需要 NdkTest 与相应的so (JNI 的.h和.cpp只是用于生成so)
此时可以直接在MainActivity 里通过NdkTest.getString()调用ndk-build生成so里的函数;

5.Android Studio 链接Linux下的NDK编译的so(JNI的.h和.cpp)

对比上面的 Android Studio 链接JNI的.h和.cpp生成的so
仅仅缺少了java.class,即除了将linux下的so导入库目录对应cpu架构目录下,需要再构造一个java.class
借用上面的例子,Linux下的 JNI .h与.cpp
即对应于com_example_linyuan_myapplication_NdkTest.h 和com_example_linyuan_myapplication_NdkTest.cpp;
Linux下 ndk-build 生成 libNdkTest.so ,将so导入Android Studio的库目录;
此时我们新建一个java class ,完全参照NdkTest编写即可;
最后在MainActivity调用NdkTest.getString().

问题:
将第三方so放到app/libs目录下时,虽然在CMakeList.txt指定了库的路径,运行app时仍然出现闪退。
解决方法:
在buiild.gradle buildTypes属性后面添加
sourceSets{
main{
jniLibs.srcDirs = [‘libs’]
}
}

猜你喜欢

转载自blog.csdn.net/liny000/article/details/83020530