Android NDK 初探

1.Android NDK 介绍

NDK(Native Develop Kit 原生开发工具包)是一组可让在 Android 应用中利用 C 和 C++ 代码的工具。 可以直接将C和C++代码写在项目里,直接构建,也可以使用其他人开发好的C 或者C++库构建自己的项目。

什么情况下需要NDK:

  • 计算密集型应用,例如游戏或物理模拟等性能关键项目。
  • 重用已经存在的 C 或 C++ 库。
  • 有时为了防止算法等机密泄漏

2.创建一个包含C++代码的Android 程序

环境 1
使用 Android Studio 2.3.3 (需要2.2以后版本)
gradle 插件 2.3.3(需要2.2.0以后版本)
已经安装了 NDK
CMake 一款外部构建工具,可与 Gradle 搭配使用来构建原生库。如果您只计划使用 ndk-build,则不需要此组件。
LLDB 一种调试程序,Android Studio 使用它来调试原生代码。
以上可以从 Tools > Android > SDK Manager 中下载安装(注意科学上网)
创建 2
1
创建支持C++文件的项目
2
中间各种下一步,直到下面这个页面
这里写图片描述
  • C++ Standard使用下拉列表选择您希望使用哪种 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。
  • Exceptions Support如果您希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android
    Studio 会将 -fexceptions 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
  • Runtime Type Information Support如果您希望支持 RTTI,请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
    点击完成按钮,一个牛逼哄哄的程序就出来了,点击运行按钮就会看到运行结果

3 程序剖析

1.文件结构
这里写图片描述

src/main/cpp/native-lib.cpp 就是我们的C++文件,这里面编写我们要实现的原生方法,然后从我们的MainActivity里通过JNI 来调用。

2.代码剖析

  • native-lib.cpp 文件
#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_com_ss007_myfirstndkapp_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */)
{
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

代码很简单,包括了两个头文件,声明并实现了一个方法,这个方法供Java调用。作用就是返回一个字符串”Hello from C++”给调用者。(关于方法的声明规则请参考JNI相关)

  • MainActivity 文件
package com.ss007.myfirstndkapp;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity
{
    //加载'native-lib' 和'my-lib'两个库
    static
    {
        System.loadLibrary("native-lib");
        System.loadLibrary("my-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(String.format("调用native-lib(从源码构建的库) 库中的stringFromJNI函数返回值》%s%n%n调用my-lib(预构建的库)sum函数返回值》%s ",
                 stringFromJNI(),sum(30,20)));
    }

    /**
     * native-lib 中实现的方法
     * @return
     */
    public native String stringFromJNI();

    /**
     * my-lib 中实现的方法
     * @param a
     * @param b
     * @return
     */
    public native int sum(int a,int b);
}

这一切是什么发生的呢,关键在CMake。如图所示,你需要将CMark文件配置到模块Gradle中

图

CMakeList.txt 文件

# 需要获取更多关于CMake的知识请移步到: https://d.android.com/studio/projects/add-native-code.html

#根据你的需要设置要使用CMake的最低版本,版本之间包含的功能有区别
cmake_minimum_required(VERSION 3.4.1)

#创建一个库,三个参数意义:1:库名称;2:库类型,是static的还是shared的;3:要编译为库的源文件
#多次调用这个函数会生成多个库,而且Gradle会自动将Shared类型的库打包到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 )

# 如果C++有头文件,最好还是在这边声明一下路径
include_directories(src/main/cpp/include/)


#********************************NDK API  start**********************************
#Android 平台包含了很多预编译的库,CMake会搜索这些库所在的路径,所以你只需提供库名称CMake就可以找到这些库
#find_library 找到目标库(此处为log库)并申明一个变量(log-lib),将这个库的路径存储在这个变量中,以供其他地方使用
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 )

#为了使我们自己生成的原生库native-lib 可以调用NDK 中的log库的函数,需要将原生库链接到log库中
#参数意义:1:要目标库 2:find_library 中找到的库
target_link_libraries( # Specifies the target library.
                       native-lib

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

#我们不仅可以通过上面的方法使用NDK中编译好的库,也可以使用NDK中的源代码文件
#add_library( app-glue

             #STATIC

             #${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )
# You need to link static libraries against your shared native library.
#target_link_libraries( native-lib app-glue ${log-lib} )
#********************************NDK API end**********************************

#********************************使用第三方库 start**********************************
add_library( #给导入的库定义一个变量,以便下面函数调用
             imported-lib
             SHARED
             IMPORTED )
set_target_properties( # Specifies the target library.
                       imported-lib

                       # Specifies the parameter you want to define.
                       PROPERTIES IMPORTED_LOCATION

                       # Provides the path to the library you want to import.
                       src/main/jniLibs/${ANDROID_ABI}/my-lib.so )
#********************************使用第三方库 end**********************************

具体如何构建,我已经在CMarkLists.txt 文件做了详细的注释。

note 为了演示 my-lib.so 我只是生成了 armeabi 架构的,如果想了解更多CPU 架构的知识,参考ABI 管理

源代码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShuSheng007

亲爱的猿猿,难道你又要白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值