Android NDK 初探

导读:本篇文章讲解 Android NDK 初探,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

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 管理

源代码下载

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/14812.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!