NDK开发从放弃到入门

澳门新浦京娱乐游戏 4

Android和iOS开拓都扶持C++开拓,能够一套代码多平台接受。同有时间C++难以反编写翻译的风味也足感到Android开垦拉动代码的保密,另一native本性也能够抓牢代码的运营效能。

1.NDK简介

一、为啥采用C/C++

  1. 方便人民群众移植,用C/C++写得库能够一本万利在任何的平台上再也使用。
  2. 代码的保养,由于java层代码非常轻易被反编写翻译,而C/C++库反汇难度极大。
  3. 升高程序的试行效能,将须要高品质的应用逻辑使用C/C++开垦,进而加强应用程序的推行成效。
  4. 拜会现成开源库,要求探望底层的API或引用一些唯有C/C++的库。
1.1、NDK和 So

​ NDK 全称 Native Development
Kit,是Google在Android开辟中提供的一套用于急速创制native工程的叁个工具。从上航海用教室那几个Android系统框架来看,我们上层是由此JNI形式来调用NDK层的,使用那么些工具得以很有益的编纂和调治JNI的代码。因为C语言不跨平台,在Windows系统下行使NDK编写翻译在Linux下能实践的函数库——SO文件,全称Shared
Objects,其实质正是一群c、c++的头文件和兑现公文打包成二个库。前段时间Android系统当下补助以下四种不一致的CPU构造,各类对应着各自的应用程序二进制接口ABI:(Application
Binary
Interface)定义了二进制文件(特别是.so文件)怎么样运营在相应的系统平台上,从利用的指令集,内部存款和储蓄器对齐到可用的种类函数库。

  • ARMv5——armeabi

  • ARMv7 ——armeabi-v7a

  • ARMv8——arm64- v8a

  • x86——x86

  • MIPS ——mips

  • MIPS64——mips64

  • x86_64——x86_64

    ​应该尽只怕的提供专为种种ABI优化过的.so文件,(尽量不要混合着使用)。应为各类ABI目录提供对应的.so文件。当四个选择设置在配备上,独有该装备帮助的CPU构造对应的.so文件会被安装。在x86设备上,libs/x86目录中只要存在.so文件的
    话,会被设置,固然不设有,则会筛选armeabi-v7a中的.so文件,就算也不真实,则选取armeabi目录中的.so文件(因为x86设备也帮助armeabi-v7a和armeabi)。ps: Native Libs Monitor
    那几个动用能够协理咱们清楚手提式有线电话机上安装的APK用到了哪些.so文件,以至.so文件来源于哪些函数库只怕框架。

二、开拓工具介绍

即便Android
Studio能够并且编写制定C++和Java代码,写完就足以编写翻译运维,不过对联想和错误提醒并非极其要好,个人建议C++的总体代码应用Visual
Studio或Xcode编译开荒,联想功效非常和谐,编写翻译速度高速,调节和测量检验也万分有帮助。

  • Visual Studio(PC)
  • Xcode(Mac)
  • Android Studio(多平台)
  • eclipse(多平台)
1.2 、JNI

​ JNI
全称JavaNative
Inteface,即Java本土接口,是Java中定义的一种用于连接Java和C/C++接口的一种达成格局。Java语言装载到设想机中,不能够和硬件人机联作,无法使得开拓。JNI增加了Java设想机的力量,驱动开采、有线火热分享,底层语言(C、C++)成效高,数学生运动算、实时渲染的十一日游,音录像管理等等,简单的讲,正是Java代码调用c、c++代码,JNI情势一共涉及到多少个剧中人物:C/C++
代码
当地方法接口类Java层中现实业务类

三、第一行代码

1.3、JNI的变量类型与Java类型比较表
Java中变量的类型 JNI对应的类型名 C/C++变量类型
boolean jboolean unsigned char
float jfloat float
double jdouble double
byte jbyte signed char
char jchar unsigned short
short jshort short
int jint/jsize int
long jlong long long
Object jobject void *
String jstring void *

1. 怎么在Objective-C项目中使用C++;

在Objective-C使用C/C++非常轻巧,仅仅必要把.m后缀的文书改成.mm就可以使用C++,大家经常不会把.mm的文本写到整个项目都有,而是设计叁个接口,用来做三个语言之间的桥梁,他们之间的相互作用仅仅在这里个接口。

中央:String类型调换

// Objective-C(NSString) -> C++(std::string)
NSString * ocString = @"Hello World,OC";
std::string cppString = [ocString UTF8String];
std::cout<<cppString<<std::endl;
// C++(std::string) -> Objective-C(NSString)
std::string  cppString2 = "Hello World,C++";
NSString *ocString2= [NSString stringWithCString:cppString2.c_str() encoding:[NSString defaultCStringEncoding]];
NSLog(@"%@",ocString2);

记得要include相关的公文

#include <stdio.h>
#include <iostream>
3、JNI的着力语法
  • 命名法规

    JNIExport jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv * env,jobject thiz ) 
    

    那边写图片描述

  • Java端加载so

 System.loadLibrary("helloJni");//加载so文件,不要带上前缀lib和后缀.so11
  • Java端的调用jni

((TextView)findViewById(R.id.jni_text)).setText(helloJni());

2.在平日的JAVA项目中应用JNI编制程序

由于自个儿是在MAC下办公,所以那边就介绍如何在MAC下开展JNI开垦,在Windows平台下的Virtual
Studio也相当轻易。

第一步:在Xcode下创造八个味如鸡肋的C++项目

澳门新浦京娱乐游戏 1

澳门新浦京娱乐游戏 2

第二步:关联JavaVM的Framework

路径:

澳门新浦京娱乐游戏,/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaNativeFoundation.framework/

澳门新浦京娱乐游戏 3

其三步:创立头文件,用于和Java交互cn_taoweiji_nativemodule_NativeDemo.h

#include <JavaVM/jni.h>
#ifndef _Included_cn_taoweiji_nativemodule_NativeDemo
#define _Included_cn_taoweiji_nativemodule_NativeDemo
#ifdef __cplusplus
extern "C" {
#endif
    JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add
    (JNIEnv *, jclass, jint, jint);
    JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_say
    (JNIEnv *, jclass, jstring);
    JNIEXPORT jstring JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_getInfo
    (JNIEnv *, jclass);

    JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_nativeToJava
    (JNIEnv *, jclass, jobject);

#ifdef __cplusplus
}
#endif
#endif

第四步:创造达成 Native德姆o.cpp

#include "cn_taoweiji_nativemodule_NativeDemo.h"
#include <string>
JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add(JNIEnv *, jclass, jint param1, jint param2)
{
    jint result = param1 + param2;
    return result;
}
JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_say(JNIEnv *env, jclass, jstring param)
{
    // std::string -> jstring
    const char *param_char = env->GetStringUTFChars(param, NULL);
    std::string str = param_char;
}
JNIEXPORT jstring JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_getInfo(JNIEnv *env, jclass)
{
    // jstring -> std::string
    std::string str = "Hi,I am C++.";
    jstring result =  env->NewStringUTF(str.c_str());
    return result;
}
JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_nativeToJava(JNIEnv * env, jclass, jobject obj)
{
    // 调用Java方法
    jclass cls = env->FindClass("cn/taoweiji/nativemodule/NativeDemo");
    //int subtract(int param1, int param2) -> (II)I
    jmethodID mid = env->GetMethodID(cls, "subtract", "(II)I");
    int result = (int) env->CallIntMethod(obj, mid, 10, 2);
//    std::cout<<result<<std::endl;
    //常见类型转换例子
    //String getInfo();
    //-> ()Ljava/lang/String;

    //PackageInfo getPackageInfo(String packageName, int flags);
    //-> (Ljava/lang/String;I)Landroid/content/pm/PackageInfo;;

}

第五步:编写翻译生成JNI文件,按 ⌘+B (Product -> Build卡塔尔(قطر‎.

编写翻译后文件
澳门新浦京娱乐游戏 4

听大人讲自个儿的微机遭受,查找编写翻译后的文件,作者的路线是

/Users/Wiki/Library/Developer/Xcode/DerivedData/DEMO_MAC_JNI-clxymnzifegyfaajsaattzgxqfbr/Build/Products/Debug/DEMO_MAC_JNI

第六步:编写JNI接口

package cn.taoweiji.nativemodule;
/**
 * 包名和类名称一定要和前面的C++头文件对应
 * cn_taoweiji_nativemodule_NativeDemo.h
 */
public class NativeDemo {
    public static native int add(int param1, int param2);
    public static native void say(String name);
    public static native String getInfo();
    public static native void nativeToJava(NativeDemo nativeDemo);
    public int subtract(int param1, int param2) {
        System.out.println("NativeDemo:" + String.format("%s - %s = %s", param1, param2, param1 - param2));
        return param1 - param2;
    }
}

第七步:调用C++

public class Main {
    static {
        System.load("/Users/Wiki/Library/Developer/Xcode/DerivedData/DEMO_MAC_JNI-clxymnzifegyfaajsaattzgxqfbr/Build/Products/Debug/DEMO_MAC_JNI");
    }
    public static void main(String[] args) {
        System.out.println("Hello World!");
        int result = NativeDemo.add(1, 2);
        System.out.println("1+2=" + String.valueOf(result));
        NativeDemo.say("Hello,I am Java.");
        System.out.println("getInfo:" + NativeDemo.getInfo());
        NativeDemo.nativeToJava(new NativeDemo());
    }
}

2.守旧的NDK开采方法:

3. 在ANDROID项目中行使NDK

Android的JNI开荒,C++文件必得编写制定在单身的module里面,Java接口代码能够编写在app(moduleState of Qatar,也得以和C++放在同一个module,通过gradle关联。详细代码请自行下载demo浏览

gradle配置(NativeModule)
apply plugin: 'com.android.library'
android {
    compileSdkVersion 23
    buildToolsVersion "24.0.0 rc2"
    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            ndk {
                moduleName "joyrun"
                stl "stlport_static"
                ldLibs "log"//用于解决__android_log_print
                abiFilters "armeabi", "armeabi-v7a", "x86", "x86_64", "arm64-v8a"
                //add -fexceptions to allow throw error
                //add -w to "format not a string literal and no format arguments [-Werror=format-security"
                cFlags "-w -fexceptions"
            }
        }
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

编写JNI接口

// NativeDemo.java
package cn.taoweiji.nativemodule;
public class NativeDemo {
    public static native int add(int param1, int param2);
}

编辑C++接口代码,JNI文件目录默许是module/src/main/jni,能够经过gradle配置改换

// cn_taoweiji_nativemodule_NativeDemo.h
#include <jni.h>
#ifndef _Included_cn_taoweiji_nativemodule_NativeDemo
#define _Included_cn_taoweiji_nativemodule_NativeDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     cn_taoweiji_nativemodule_NativeDemo
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif

// NativeDemo.cpp
#include "cn_taoweiji_nativemodule_NativeDemo.h"
JNIEXPORT jint JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_add(JNIEnv *, jclass, jint param1, jint param2)
{
    jint result = param1 + param2;
    return result;
}

调用

// 静态加载
static {
     System.loadLibrary("joyrun");
}
//调用
int result = NativeDemo.add(1,2);
Log.i("1+2=",String.valueOf(result));
2.1 NDK开采条件布署:

四、NDK开垦大旨

2.2 代码开采

​ 在Java代码中宣称Native方法,命令行踏向当前类所在的src/main/Java
目录,然后 javah +com…(包名+类名)
,会在src下转移当前类中Native方法的证明头文件,对Native方法进行宣示。

public static native int EncodeInit(int speexMode);

​ 手动新建c/c++文件,用于编写JNI代码,供给达成.h文件中所评释的主意。

​ 因为Eclipse或Android Studio
并不扶植c/c++的代码开采,由此须求在在VS等c/c++开垦平台支付Native代码,并完成测量试验。

编写翻译文件解析

将NativeModule编写翻译后变动的aar文件后缀改成.zip解压,能够窥见中间有个jni文件,张开药方可观察”armeabi”,
“armeabi-v7a”, “x86”, “x86_64”,
“arm64-v8a”等公事夹,再展开方可知到是以lib前缀的so格式文件,这正是编写翻译后的native层文件,大家日常引用的第三方库(百度地图)也是要抬高这个文件到大家的libs文件夹,分化的名号代表着分裂平台相关的编写翻译文件,市道上海大学好些个的手提式无线电话机都以arm构造CPU,x86结构的无绳电话机大约没人用(genymotion模拟器归于x86平台),所以大家普通发表应用程式不会虚构x86平台,仅仅增加armeabi文件就可以,可是在付出进度中国建工业总会公司议也加多x86的so文件,以福利大家在模拟器上运转。

2.3 对须求调换的so包实行布置


将支付产生的Native文件全部导入Android工程jni目录下,并编写Android.mk和Application.mk文件,对亟待更改的so包实行布置。

  • Application.mk指标是描述在您的应用程序中所须求的模块(即静态库或动态库State of Qatar,如下是表示编写翻译出装有对应的平台。

 APP_ABI := all
  • Android.mk是Android提供的一种makefile文件,用来钦赐诸如编写翻译生成so库名、援用的头文件目录、供给编写翻译的.c/.cpp文件和.a静态库文件等。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni   //ps:生成的so文件名格式为:lib+声明的so名字
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

运行库

Android平台包蕴贰个微型的C运维库援助库,成为系统运转库。该运转库不帮衬一下表征:C规范库、相当帮助、RTTI支持。NDK提供了用于补充系统运转库作用的一部分特出的C++运营库。

C++运行库 C++异常支持 C++RTTI C++标准库
系统库 No No No
GAbi++ No Yes No
STLport No Yes Yes
GNU STL Yes Yes Yes
  1. STLportSTLport是多少个开源的、多平台的C规范库完成。它提供一个C规范库头文件的全体集结甚至对RTTI的帮忙。
  2. GNU STLGNU标准C库,也叫libstdc-v3,是Android
    NDK最全面包车型地铁标准C运转库。它是叁个正值开荒的、以落实ISO标准C库为对象的开源项目。
2.4 生成so包

一声令下行下步向JNI代码所在地点,试行ndk-build 便会调换钦定的so。

gradle配置

  1. STL运营库引用
  2. “armeabi”, “armeabi-v7a”, “x86”, “x86_64”, “arm64-v8a”等楼台配置
  3. C++输出logcat配置
  4. 贰个编写翻译万分消除
  5. 格外捕获

    // 生成so文件的名称
    moduleName "joyrun"
    // 引入STL标准库
    stl "stlport_static"//gnustl_static
    //用于解决__android_log_print
    ldLibs "log"
    abiFilters "armeabi", "armeabi-v7a", "x86", "x86_64", "arm64-v8a" //添加编译的平台
    //add -fexceptions to allow throw error
    //add -w to "format not a string literal and no format arguments [-Werror=format-security"
    cFlags "-w -fexceptions"
    
2.5 引用so包

​ 首先在Gradle中引用so包

    sourceSets{
        main {
            jniLibs.srcDirs 'libs'
        }
    }

​ 在java的native方法证明处加载so包:

static {
        try {
            System.loadLibrary("hello-jni");
            mIsloaded = true;
        } catch (UnsatisfiedLinkError e) {
            Logging.e(TAG, "", e);
        }

    }

public static native int EncodeInit(int speexMode);

LOGCAT输出

#include <android/log.h>
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, "tag_joyrun", __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, "tag_joyrun", __VA_ARGS__)
LOGE("Hello Logcat");

3.Android Studio 新的 ndk-build

​ Android Studio 在2.2日增了对NDK的支撑,这里根本指ndk-build
和cMake。这里的ndk-build 是相对于早前的ndk-build特别有益于。

支出步骤:

类型转变

// std::string -> jstring
std::string str = "Hello World";
jstring result =  env->NewStringUTF(str.c_str());
// jstring -> std::string
jstring param;
const char *param_char = env->GetStringUTFChars(param, NULL);
std::string str = param_char;
// jboolean 两个值 JNI_TRUE、JNI_FALSE
3.1 遭遇安排

​ 需要在gradle.properties中支持NDK开发

android.useDeprecatedNdk=true

C++调用JAVA代码

//Java

public static native void nativeToJava(NativeDemo nativeDemo);
public int subtract(int param1, int param2) {
Log.e("NativeDemo", String.format("%s - %s = %s", param1, param2, param1 - param2));
return param1 - param2;
}

//C++

JNIEXPORT void JNICALL Java_cn_taoweiji_nativemodule_NativeDemo_nativeToJava(JNIEnv * env, jclass, jobject obj)
{
    // 调用Java方法
    jclass cls = env->FindClass("cn/taoweiji/nativemodule/NativeDemo");
    jmethodID mid = env->GetMethodID(cls, "subtract", "(II)I");
    int result = (int) env->CallIntMethod(obj, mid, 10, 2);

    //常见类型转换例子
    //String getInfo();
    //-> ()Ljava/lang/String;
    //PackageInfo getPackageInfo(String packageName, int flags);
    //-> (Ljava/lang/String;I)Landroid/content/pm/PackageInfo;;
}
3.2 声Bellamy个原生的办法
public class NdkJniUtils {

    static {
        System.loadLibrary("native-lib");   
    }

    public native String getString();

}

一键生成从JAVA到C++接口代码脚本

文件:autojavah.sh

#!/bin/sh
export ProjectPath=$(cd "../$(dirname "$1")"; pwd)
export TargetClassName="co.runner.app.jni.NativeDemo"
export SourceFile="${ProjectPath}/app/src/main/java"
export TargetPath="${ProjectPath}/jni-joyrun/src/main/jni"
cd "${SourceFile}"
javah -d ${TargetPath} -classpath "${SourceFile}" "${TargetClassName}"
echo -d ${TargetPath} -classpath "${SourceFile}" "${TargetClassName}"
3.3 头文件的更动

​ 命令行步向当前类所在的src/main/Java 目录,然后 javah +com…(包名+类名)
,会在src下转移当前类中Native方法的评释头文件,对Native方法开展宣示。

五、C++面向对象及规范库入门

C++类定义

// Demo.hpp
#ifndef Demo_hpp
#define Demo_hpp
#include <stdio.h>
#include <string>
class Demo{
public:
    std::string name;
    int age = 0;
    void say();
    static int add(int param1,int param2)
    {
        return param1 + param2;
    }
};
#endif /* Demo_hpp */

类措施的贯彻

// Demo.cpp
#include "Demo.hpp"
#include <iostream>
void Demo::say()
{
    std::cout<<"name = "<<name<<",age = "<<age<<std::endl;
}

对象创造及拜会对象的成员

//对象创建
Demo d1;
Demo * d2 = new Demo;
// 运算符访问
d1.say();
// 指针访问
d2->say();
//静态函数访问
int result = Demo::add(1,2);
std::cout<<"1 + 2 = "<<result<<std::endl;

LIST链表

//include相关文件
#include <stdio.h>
#include <iostream>
#include <list>
#include "Demo.hpp"
// 链表定义
std::list<Demo> * demos = new std::list<Demo>;
Demo * demo = new Demo;
demo->name = "Wiki";
demo->age = 24;
// 在后面插入数据
demos->push_back(*demo);
demo = new Demo;
demo->name = "Wiki2";
demo->age = 25;
// 在前面插入数据
demos->push_front(*demo);
// 顺序链表遍历
for (std::list<Demo>::iterator iter = demos->begin(); iter != demos->end(); ++iter) {
    iter->say();
}
// 反顺序链表遍历
for (std::list<Demo>::reverse_iterator iter = demos->rbegin(); iter != demos->rend(); ++iter) {
    iter->say();
}
// 获取指定位置元素
std::list<Demo>::iterator iter = demos->begin();
advance(iter, 1);
iter->say();

指南针、引用和值

在C++中,函数能够用超级多例外的点子传递参数,比方通过指针、援用或是直接传值。

// 通过指针
void handle1(Demo *p);
// 通过引用
void handle1(Demo& p);
// 通过值
void handle1(Demo *demo);

堆和栈的掌握

  • 栈(stack):由操作系统自动分配释放
    ,寄存函数的参数值,局地变量的值等。其操作格局临近于数据构造中的栈;
  • 堆(heap): 一般由程序员分配释放,
    若技士不自由,程序停止时恐怕由OS回笼,分配格局倒是形似于链表。

    Demo d1;//栈
    Demo * d2 = new Demo;//堆
    char c; //栈上分配
    char *p = new char[3]; //堆上分配,将地址赋给了p;
    

污源回笼

new和C++
delete运算符用于动态分配和收回内部存款和储蓄器的运算符,自身new出来的靶子将在通过delete释放内部存款和储蓄器。

delete demos;
3.4 JNI代码的切实贯彻

将.h文件移动到花色的JNI开辟目录,并可遵照要求改名。新建C/C++文件,对.h文件中的方法举行贯彻。

六、开采中常用的法子及注意事项(坑)

  • 光阴戳获取格局。

    long time = time(0);
    

  • 在意so文件防盗用难点。
  • 尽量幸免调用与平台有关的艺术,制止移植带来难题。
  • JNI接口的包名无法带有下划线‘_’。
3.5 Gradle配置

​ 在defaultConfig 中步入对NDK的有的安排

ndk{
            moduleName "native-lib"         //生成的so名字
            abiFilters "armeabi", "armeabi-v7a", "x86"  //输出指定三种abi体系结构下的so库
        }

一直编写翻译生成so包并被引述。

ps :直接利用so包实行付出


1.上述进程编写翻译成功后会在build/intermediates目录下转移对应的ABI的so包,能够平素拿来使用。

​ 2.将so包复制到项目的libs文件夹下

​ 3.在Gradle中引入so包:

sourceSets{
        main {
            jniLibs.srcDirs=['libs']
        }
    }

​ 4.在native方法注脚处直接加载so包就能够不荒谬使用了

static {
        System.loadLibrary("native-lib");   
    }


5.那时候因为是直接行使so包,那么大家的jni目录下的jni代码以至NDK{}配置均可移除。

相关源代码:

  • Android: 
  • Objective-C: 
  • MAC-JNI: 

4. cMake -全新的开荒方式

4.1 首要优点:
  • 便于管理援引的第三方包
  • 最要害!旧的JNI开采 JNI代码文件满屏的新民主主义革命报错,未有其它轮代理公司码提醒!
    now,援助代码提醒,扶助电动创立方法!
4.2 开垦步骤

(不要求配置gradle.properties中android.useDeprecatedNdk=true)

1.声称贰个原生的法子

2.实现c/c++ 文件

3.创建cMake脚本,编写cMakeLists.txt 文件

4.提供三个针对 CMake 脚本文件的渠道,将 Gradle 关联到原生库。Gradle
使用营造脚本将源代码导入Android Studio 项目并将原生库(SO 文件)打包到
APK 中。在Gradle中配备cMake

defaultConfig {
        applicationId "com.iflytek.cmaketest"
        minSdkVersion 21
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
        ndk {
            abiFilters "armeabi" 
        }
    }

externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
4.3 cMakeList语法:

cMakeLists文件地方可自定义,平时坐落于module的根目录下,对应Gradle中cmake的path路径

# 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.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )

# Specifies a path to native header files. 
include_directories(src/main/cpp/include/)

1.底子运用:

  • cmake_minimum_required 表示所支撑的CMake编写翻译器最低版本(不根本)

  • addLibrary(State of Qatar 要求CMake依照钦点的源文件生成库文件.

    内部第三个参数表示生成的库的称呼,第叁个参数选择[SHARED|STATIC|MODULE]其间的八个,表示生成的库的项目,第八个参数为具备的供给投入那一个库的源文件地址。

  • 使用 add_library() 向您的 CMake 创设脚本增加源文件或库时,Android
    Studio 还有只怕会在你协同项目后在 Project
    视图下展现关联的标头文件。不过,为了有限援助 CMake
    能够在编写翻译时一向你的标头文件,您供给将
    include_directories()
    命令增多到 CMake 营造脚本中并点名标头的路线.

2.升级使用:

  • 上述是选拔我们团结写的jni代码,假如须要依附第三方的so包,并在这基本功上拓宽JNI开拓,须要引入第三方库

    add_library(
                fmodL  
                SHARED
                IMPORTED)
    set_target_properties(
                fmodL
                PROPERTIES IMPORTED_LOCATION
                ../../../../libs/${ANDROID_ABI}/libfmodL.so
    
  • 在调式的时候大家必要张开打log,那么些应用就须求引进log库,那么大家将要引进系统的NDK
    API。

    find_library( # Defines the name of the path variable that stores the
                  # location of the NDK library.
                  log-lib
    
                  # Specifies the name of the NDK library that
                  # CMake needs to locate.
                  log )
    
    # Links your native library against one or more other native libraries.
    target_link_libraries( # Specifies the target library.
                           native-lib
    
                           # Links the log library to the target library.
                           ${log-lib} )
    

5.比照分析

5.1二种办法优劣势
改进ndk-build 原始ndk-build cMake
优点 1.三方源代码保留,可以随时查看 1.支持动态调试 1.支持代码提示 2.代码调试 3.管理方便
缺点 1.不支持代码编辑,调试 1.不支持代码提示 1.每次调试都需要编译JNI
5.2 推荐方案
You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图