您的位置:首页 > 移动开发 > Android开发

Android之一个简单的NDK使用(一)

2017-10-05 15:55 309 查看

写在前面

刚入职那会,经理就布置了一道题目,由于涉及到NDK的知识,所以还是显得有些不知所措,但经理说不难,下载官方的Demo做些修改就可以搞定了。所以通过经理的一些提示和资料的查找,也算在周末里完成了,做了之后才发现这题确实不难……

GitHub代码

同样地,这一篇也还是直接地写实现方法,然后也要其它时间写一些原理性地东西。另外由于经理对结构有一些要求,所以这道题目里也做了一些调整,可能会被看作是“过度设计”。

另外这里用的是Android Studio 2.2后使用的CMake,所以应该是跟之前需要的使用mk的方法不一样,当时不了解,看了一些文章比较旧,所以有些概念混淆了,是经理提醒了才明白。

结构和流程

同样地先看下结构



这个project里包含了两个module,app和library,library是个依赖库,用于提供C++的方法。

主要的实现流程:

Created with Raphaël 2.1.0开始build.gradle里添加CMake使用编写C(C++)代码CMakeLists文件里添加C依赖app里使用编写好的C(C++)结束

实现

library

1. 添加CMake

在创建library后需要在build.gradle里添加CMake的使用:

android {

defaultConfig {
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
}

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


2. 编写C(C++)代码

在main目录下创建cpp文件夹,在这里进行C代码的编写。本来只有一个native-lib.cpp,但后来我还是做了拆分。

calculateBeerResult.cpp和calculateBeerResult.h是对计算方法的封装,把.cpp里的方法在.h头部文件里进行声明,这样我们在native-lib.cpp里引用calculateBeerResult.h的时候就能使用该方法了。

如下:

calculateBeerResult.cpp

#include "calculateBeerResult.h"
/**
* 返回一个int数组
* 第一个数表示已经喝的瓶数
* 第二个数表示剩下的空瓶子
* 第三个数表示剩下的盖子
*/
int* calculateBeerResult(int money){
//总价格
int allMoney = money;
//已经喝的瓶数
int drunkBottle = allMoney / 2;
//剩下的空瓶子
int emptyBottle = drunkBottle;
//剩下的瓶盖
int top = drunkBottle;
int size = 3;
int *result = new int[size];

while (emptyBottle >= 2 || top >= 4) {
int tmp = emptyBottle / 2 + top / 4;
drunkBottle = drunkBottle + tmp;
emptyBottle = tmp + emptyBottle % 2;
top = tmp + top % 4;
}

result[0] = drunkBottle;
result[1] = emptyBottle;
result[2] = top;
return result;
}


calculateBeerResult.h

#ifndef DRINKBEER_CALCULATEBEERRESULT_H
#define DRINKBEER_CALCULATEBEERRESULT_H
//声明我们写的计算方法
int* calculateBeerResult(int money);

#endif //DRINKBEER_CALCULATEBEERRESULT_H


native-lib.cpp

#include <jni.h>
#include "calculateBeerResult.h" //引入计算方法的头部

extern "C"
JNIEXPORT jintArray JNICALL
Java_message_license_szca_com_drinkbeer_presenter_CalculateBeerPresenter_getCalculateResult(
JNIEnv *env,
jobject /* this */,
int money//java传进来的金额) {

//因为返回的结果是个数组,所以这里查阅后使用了指针这种方法
int *result =  calculateBeerResult(money);
int size = sizeof(result);

jintArray arry = env->NewIntArray(size);
env->SetIntArrayRegion(arry, 0, size, result);

return arry;
}


这样我们就可以看出来,在native-lib.cpp里,主要是接收java传进来的金额,然后通过计算后,返回一个数组结果给java即可。

3. CMakeLists文件里添加C依赖

在当前module目录下的CmakeLists.txt里添加我们用到的C文件:

# 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)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets 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

)

add_library(
calculateBeerResult SHARED src/main/cpp/calculateBeerResult.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

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

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


app

1. app使用编写好的C

在app这个module里我们要做的就只是对我们编写的C的引用,传入数据和获取结果即可:

public class CalculateBeerPresenter {
//1.声明我们要引入的cpp文件
static {
System.loadLibrary("native-lib");
}

//2.声明我们要使用该cpp文件里的哪个方法
public native int[] getCalculateResult(int money);

private Activity mContext;
private ICalculateBeerView mICalculateBeerView;
public CalculateBeerPresenter(Activity context , ICalculateBeerView iCalculateBeerView){
this.mContext = context;
this.mICalculateBeerView = iCalculateBeerView;
}

/**
* 计算结果
* @param str
*/
public void calculateBeer(String str) {
String input = str;
if (TextUtils.isEmpty(input)) {
mICalculateBeerView.calculateFailed("输入金额");
return;
}
//3.调用该方法
int result[] = getCalculateResult(Integer.valueOf(input));
mICalculateBeerView.calculateSuccess(result);

}
}


至此,我们就完成了一个简单的NDK的使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android ndk