美文网首页Android-NDK/JNI
NDK开发学习笔记(1)

NDK开发学习笔记(1)

作者: 柴泽建_Jack | 来源:发表于2017-01-15 21:18 被阅读976次

    本篇为笔记。

    学习来源主要来自Android官方教程。

    Getting Started with the NDK

    NDK环境搭建

    tools.png

    在Android Studio 2.2以上的版本好像对NDK有了不错的支持。这些之后在体验吧。先不管,按照官网上的做,把CMake,LLDB和NDK下载下来。下载不下来的朋友,嗯……自寻办法吧

    创建一个支持C++的新项目

    然后我们开始创建一个工程。

    1. Configure

    在Configure your new project的时候选择Include C++ Support。

    create1.png

    然后正常下一步,之后按照正常的情况填写内容。

    2. Customize C++ Support

    之后到达Customize C++ Support 的时候会出现一些我们之前没有见过的东西。

    create2.png
    • 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。

    其实我也不知道后面两个是什么意思。不过我先勾上看看情况。

    然后点击finish。

    查看创建出来的功能

    之后创建出来的工程如图:

    create3.png

    其中我们可以看到多了两个东西:

    1. cpp。

    在 cpp 组中,您可以找到属于项目的所有原生源文件、标头和预构建库。对于新项目,Android Studio 会创建一个示例 C++ 源文件 native-lib.cpp,并将其置于应用模块的 src/main/cpp/ 目录中。本示例代码提供了一个简单的 C++ 函数 stringFromJNI(),此函数可以返回字符串“Hello from C++”。要了解如何向项目添加其他源文件,请参阅介绍如何创建新的原生源文件的部分。

    1. CMakeLists.txt。这个属于External Build Files 组。

    在 External Build Files 组中,您可以找到 CMake 或 ndk-build 的构建脚本。与 build.gradle 文件指示 Gradle 如何构建应用一样,CMake 和 ndk-build 需要一个构建脚本来了解如何构建您的原生库。对于新项目,Android Studio 会创建一个 CMake 构建脚本 CMakeLists.txt,并将其置于模块的根目录中。要详细了解此构建脚本的内容,请参阅介绍如何创建 Cmake 构建脚本的部分。

    运行工程

    我们运行工程并查看结果。

    create4.png

    出现这个样子就是成功了。那么我们下来去看看生成工程的源码。

    生成工程源码的探究

    Activity的源码。

    package me.jack.ndk.ndkfirstdemo;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        // Used to load the 'native-lib' library on application startup.
        static {
            System.loadLibrary("native-lib");
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // Example of a call to a native method
            TextView tv = (TextView) findViewById(R.id.sample_text);
            tv.setText(stringFromJNI());
        }
    
        /**
         * A native method that is implemented by the 'native-lib' native library,
         * which is packaged with this application.
         */
        public native String stringFromJNI();
    }
    
    

    这里通过

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

    加来我们C++库。这个其实就是JNI嘛。

    然后下面有一个native方法stringFromJNI。对应着库中的一个C++方法。在setText的时候使用这个方法得到显示的字符串。

    然后我们看一下cpp中的源码。

    #include <jni.h>
    #include <string>
    
    extern "C"
    jstring
    Java_me_jack_ndk_ndkfirstdemo_MainActivity_stringFromJNI(
            JNIEnv *env,
            jobject /* this */) {
        std::string hello = "Hello from C++";
        return env->NewStringUTF(hello.c_str());
    }
    

    这里我们可以看到就是JNI的写法。

    但是这里又一个问题就是,我们通常情况下是使用C++的动态链接库。那么这个时候编译器为我们做了什么呢?

    Android Studio支持NDK的理解

    当我们点击Run之后,Android Studio 将在您的 Android 设备或者模拟器上构建并启动一个显示文字“Hello from C++”的应用。下面的概览介绍了构建和运行示例应用时会发生的事件:

    1. Gradle 调用您的外部构建脚本 CMakeLists.txt。
    2. CMake 按照构建脚本中的命令将 C++ 源文件 native-lib.cpp 编译到共享的对象库中,并命名为 libnative-lib.so,Gradle 随后会将其封装到 APK 中。
    3. 运行时,应用的 MainActivity 会使用 System.loadLibrary() 加载原生库。现在,应用可以使用库的原生函数 stringFromJNI()。
    4. MainActivity.onCreate() 调用 stringFromJNI(),这将返回“Hello from C++”并使用这些文字更新 TextView。

    现在Android Studio已经又了Analyze APK,那么去看一看。

    create5.png

    然后被吓尿了。

    那么下来对CMakeLists.txt一探

    一探CMake构建脚本

    CmakeLists.txt源码:

    # Sets the minimum version of CMake required to build the native
    # library. You should either keep the default value or only pass a
    # value of 3.4.0 or lower.
    
    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 it 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).
                 # Associated headers in the same location as their source
                 # file are automatically included.
                 src/main/cpp/native-lib.cpp )
    
    # Searches for a specified prebuilt library and stores the path as a
    # variable. Because system libraries are included 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 the
    # build script, prebuilt third-party libraries, or system libraries.
    
    target_link_libraries( # Specifies the target library.
                           native-lib
    
                           # Links the target library to the log library
                           # included in the NDK.
                           ${log-lib} )
    
    
    

    看里面的注释基本上都是可以理解的。比如我们更改一个名字,把其中的add_Library中的名字改成first-lib,然后把target_link_libraries中对应的名字也改了,然后把MainActivity中加载动态链接库的地方的名字也改了。然后Clean工程,再运行一下。运行结果是一致的,但是我们再次分析apk,发现里面的so库的名字变了。

    然后我们把第二个参数,SHARED改一下,改成STATIC,再次看看情况。然后报错了。我们去看一下apk包:

    create6.png

    果然没有打包到apk中。看来我们只能使用SHARED了。

    版权印为您的作品印上版权78454335

    相关文章

      网友评论

      本文标题:NDK开发学习笔记(1)

      本文链接:https://www.haomeiwen.com/subject/rulubttx.html