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

写在前面

刚入职那会,经理就布置了一道题目,由于涉及到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的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值