NDK开发(一) :NDK入门指南

作者: 2c3d4f7ba0d4 | 来源:发表于2019-08-20 16:25 被阅读5次

    本文操作以 Android Studio 3.4.2 版本为例


    目录

    • 环境配置
    • 创建支持 C/C++ 的新项目
    • 向现有项目添加 C/C++ 代码
    • 参考文章

    环境配置

    • 下载安装 Android Studio
    • 配置 NDK 环境
      • 启动 Android Studio.

      • 如下图:在界面的 Configure 中 打开 Settings 界面。

        image
      • 如下图: 在 左上角 输入框输入sdk → 点击 Android SDK → 点击 SDK Tools → 然后勾选上 LLDBCMakeNDK → 然后点击 OK → 点击弹出框中的 OK.

        image
      • 下载安装完成之后,重启 Android Studio.


    创建支持 C/C++ 的新项目

    • Android Studio 的界面,点击 Start a new Android Studio project

    • 如下图,在弹出界面选择 Native C++ ,然后点击 Next

      image
    • 在新的界面直接点击 Next, 或者修改Name, Package name , Save location 中的值;

    • 在新的界面点击 Finish.

    Android Studio将会为我们生成一个模板工程,我们可以直接运行,启动之后界面上会显示 Hello from C++


    支持 C/C++ 的项目文件介绍

    Android Studio 左侧打开 Project 窗格并选择 Android 视图,如下图:

    image

    我们只要关心上图红框标记出来的以下这些文件就好:

    • MainActivity :应用视图界面,加载了一个名为native-lib的库,定义了一个native的方法stringFromJNI,然后将stringFromJNI返回的值设置到TextView上。

      public class MainActivity extends AppCompatActivity {
          static {
              System.loadLibrary("native-lib");
          }
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              ...
              tv.setText(stringFromJNI());
          }
          public native String stringFromJNI();
      }
      
      
    • CMakeLists.txt :CMake 构建脚本。

       # 设置CMake的最低版本
      cmake_minimum_required(VERSION 3.4.1)
      # 添加源文件或者库
      add_library(
              native-lib # 库的名字
              SHARED # 库的类型  
              native-lib.cpp) # 库的源文件
      # 引用NDK中的库log,命名为log-lib
      find_library(
              log-lib # 库路径对应的变量名
              log) # NDK中的库名
      # 关联库,确保 native-lib 中 能使用 log 库
      target_link_libraries(
              native-lib 
              ${log-lib})
      
      
    • native-lib.cpp : 示例 C++ 源文件,位于src/main/cpp/目录。

      #include <jni.h>
      #include <string>
      
      extern "C" JNIEXPORT jstring JNICALL
      //MainActivity 中 stringFromJNI方法 对应的 c 方法名字
      Java_com_lxk_myapplication_MainActivity_stringFromJNI(
              JNIEnv *env,
              jobject ) {
          std::string hello = "Hello from C++";
          return env->NewStringUTF(hello.c_str());
      }
      
      
    • build.gradle :构建文件

      android {
          ...
          defaultConfig {
              ...
              externalNativeBuild {
                  cmake {
                      cppFlags ""
                  }
              }
          }
          externalNativeBuild {
              cmake {
                  path "src/main/cpp/CMakeLists.txt" //构建脚本的路径
                  version "3.10.2"//CMake的版本
              }
          }
      }
      
      

    如果刚刚运行过项目的话,点击左侧Project 窗格并选择 Project 视图,会在 app/build/intermediates/cmake/debug/armeabi-v7a/下生成一个 libnative-lib.so文件。

    CMake 使用 lib库名称.so 的规范来为库文件命名,库名称即为我们定义的 native-lib。不过我们在Java代码中加载时,还是使用我们定义的库名称 native-lib

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

    向现有项目添加 C/C++ 代码

    向现有 Android Studio 项目添加或导入原生代码,则需要按以下基本流程操作:

    • 创建新的原生源文件,并将其添加到 Android Studio 项目中,如果您已经拥有原生代码或想要导入预编译原生库,则可跳过此步骤。
    • 创建 CMake 编译脚本,告知 CMake 如何将原生源文件编译入库。如果导入和关联预编译库或平台库,您也需要此编译脚本。如果现有的原生库已有 CMakeLists.txt 编译脚本,或使用 ndk-build 并包含 Android.mk编译脚本,则可跳过此步骤。
    • 提供一个指向 CMake 或 ndk-build 脚本文件的路径,将 Gradle 关联到原生库。Gradle 使用编译脚本将源代码导入您的 Android Studio 项目并将原生库(.so文件)打包到 APK 中。
    重新创建一个 Basic Activity的工程。
    image
    创建新的原生源文件
    • 从左侧打开 Project 菜单并从下拉菜单中选择 Project 视图。

    • 右键点击选中 app/src/ 下的 main 目录,然后选择 New > Directory,为目录输入一个名称(例如 cpp)并点击 OK

    • 右键点击您刚刚创建的目录,然后选择 New > C/C++ Source File,输入一个名称,例如 hello-ndk,如果想创建一个标头文件,请勾选 Create an associated header 复选框,点击 OK

      image
    创建 CMake 构建脚本

    如果您的原生源文件还没有 CMake 构建脚本,则您需要自行创建一个并包含适当的 CMake 命令。

    必须将其命名为 CMakeLists.txt

    • 右键点击选中 app ,然后选择 New > File,输入CMakeLists.txt 作为文件名并点击 OK

    • 添加命令到 CMakeLists.txt

      cmake_minimum_required(VERSION 3.4.1)
      
      add_library( hello-ndk
                   SHARED
                   src/main/cpp/hello-ndk.cpp)
      
      
    • 使用 add_library() 向您的 CMake 构建脚本添加源文件或库时,Android Studio 还会在您同步项目后在 Project 视图下显示关联的标头文件。不过,为了确保 CMake 可以在编译时定位您的标头文件,您需要将 include_directories()命令添加到 CMake 构建脚本中并指定标头的路径:

      add_library(...)
      
      include_directories(src/main/cpp/include/)
      
      
    • 添加 NDK APIAndroid NDK 提供了一套实用的原生 API 和库。将 find_library() 命令添加到您的 CMake 构建脚本中以定位 NDK 库。以 Android 特定的日志支持库 为例,为了确保您的原生库可以在 log 库中调用函数,您需要使用 CMake 构建脚本中的 target_link_libraries()命令关联库:

      add_library(...)
      
      find_library( log-lib # 库路径的变量名
                    log ) # 对应的库名
      
      #将预构建库关联到您自己的原生库              
      target_link_libraries( hello-ndk
                             ${log-lib} )
      
      
    将 Gradle 关联到您的原生库

    要将 Gradle 关联到您的原生库,您需要提供一个指向 CMakendk-build 脚本文件的路径。在您构建应用时,Gradle 会以依赖项的形式运行 CMakendk-build,并将共享的库打包到您的 APK 中。

    • 点击Android Studio 左侧菜单 Project 并选择 Android 视图。 点击 弹出菜单的第二个选项 Link C++ Project with Gradle,如图1,点击文件夹,点击 Android Studio图标的按钮可以定位到项目根目录,然后如图2 配置 CMakeLists.txt 的路径,点击 OK

      image
    image
    • 然后 app目录下的build.gradle文件会自动添加以下代码。

      externalNativeBuild {
          cmake {
              path file('CMakeLists.txt')
          }
      }
      
      
    配置Javah命令工具

    如下图,按 Ctrl + Alt + s 进入 Setting 界面,点击 Tools → External Tools → + 配置添加外部工具。参数如下:

    Name :JavaH
    Program:$JDKPath$/bin/javah
    Parameters: -encoding UTF-8 -d ../cpp -jni $FileClass$
    Working directory: $SourcepathEntry$\..\java
    
    
    image
    编辑 MainActivity

    MainActivity 添加如下代码:

    public class MainActivity extends AppCompatActivity {
        static {
            System.loadLibrary("hello-ndk");
        }
        public native String helloNDK();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar toolbar = findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
    
            //添加下面两行代码
            TextView show = findViewById(R.id.tv_show);
            show.setText(helloNDK());
    
            ....
        }
        ...
    }
    
    
    修改 content_main.xml

    修改 content_main.xml,给TextView添加 android:id="@+id/tv_show"

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        ...>
    
        <TextView
            android:id="@+id/tv_show"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            .../>
    </android.support.constraint.ConstraintLayout>
    
    
    生成 .h 头文件

    如下图,右键点击MainActivity,选择弹出框中的 External ToolsJavaH 。就会在cpp目录下生成 com_example_myapplication_MainActivity.h文件,你的文件名可能不一样。

    image
    编辑hello-ndk.cpp

    修改hello-ndk.cpp为以下代码:

    #include <jni.h>
    //确认此处名字是否可你生成的头文件的名字一样
    #include "com_example_myapplication_MainActivity.h" 
    
    //函数名要和头文件中的名字一致
    JNIEXPORT jstring JNICALL Java_com_example_myapplication_MainActivity_helloNDK  
      (JNIEnv * env, jobject){
        return env ->NewStringUTF("Hello NDK");
    }
    
    
    运行程序

    点击顶部菜单栏 Build 中的 Rebuild Project,完了之后按 Shirt + F10 运行程序,然后界面上就会显示 Hello NDK 的字样。

    原文链接:https://www.jianshu.com/p/63b19f174bc2

    最后

    漫漫开发之路,我们只是其中的一小部分……只有不断的学习、进阶,才是我们的出路!才跟得上时代的进步!

    我从事Android开发快十年了,今年年初我花两个月的时间收录整理了一套知识体系,此外,还有面试专题、架构视频,如果有想法深入的系统化的去学习的,可以关注我,加入Android进阶技术交流 (895077617 )免费获取整理版的资料**
    ,我会把我收录整理的资料都送给大家,帮助大家更快的提升。

    重要的事说三遍,转发+转发+转发,让更多需要的朋友们都可以看到并且领到!

    相关文章

      网友评论

        本文标题:NDK开发(一) :NDK入门指南

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