zoukankan      html  css  js  c++  java
  • 【Android Studio安装部署系列】二十五、Android studio使用NDK生成so文件和arr文件

    版权声明:本文为HaiyuKing原创文章,转载请注明出处!

    概述

    Android Studio使用ndk的简单步骤。

    NDK环境搭建

    下载NDK

    下载链接:https://developer.android.com/ndk/downloads/index.html

    PS:需要翻墙,建议下载r9+的版本。

    国内下载地址:

    http://www.wanandroid.com/tools/ide#NDK

    解压 NDK包【建议在未打开Android Studio的情况下】

    注:解压路径不要出现空格和中文。

    建议:将文件解压到SDK目录里,并命名为ndk-bundle。好处:启动Android Studio时,Android Studio会自动检查它并直接添加到ndk.dir中,那么在使用时,就不用配置Android Studio与NDK的关联【解压的时候需要直接解压到sdk安装目录/ndk-bundle目录中才可以实现自动关联,否则需要手动关联】

    因为我个人觉得不是每一个项目都需要用到ndk,所以就采用了手动关联的方式。

    自动关联:sdk安装目录/ndk-bundle

    手动关联:其他目录

    下载安装Cmake

    我是通过新建一个项目,根据Android Studio的提示信息进行安装的。其实也可以跳过新建项目的步骤,直接安装SDK Manager中安装。具体操作步骤见下文。

    新建项目

    新建项目

    勾选Include C++ support

    Next

    Next

    Next

    选择C++标准,一般选择默认即可

    手动关联NDK

    对于解压ndk未解压到自动关联的目录(sdk安装目录/ndk-bundle)的情况,新建项目后会出现下面的提示信息,解决方案就是手动关联ndk。

    对于解压ndk到自动关联的目录(sdk安装目录/ndk-bundle)的情况,可以跳过。因为不会出现下面的提示信息。如果万一出现了的话,那么就手动关联ndk即可。

    File——Project Structure...

    选择ndk路径

    查看项目根目录的local.properties文件,会发现多了一行代码:

    添加对旧版本的NDK支持

    在工程中gradle.properties中添加以下代码:android.useDeprecatedNdk=true

    下载安装Cmake

    第一次运行会报错,原因是未安装Cmake。

    打开SDK Manager

    方式一

    方式二:File——Settings...

    安装cmake

    运行

    新建的项目含有一个cpp文件,可以看下效果:

    将指定的.h和.cpp文件编译成so文件

    首先修改生成的so文件的名称

    打开CMakeLists.txt

    最开始的:

    # 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 )
    
    # 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
    
                           # Links the target library to the log library
                           # included in the NDK.
                           ${log-lib} )

    修改后的:

    # 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.
    # 编译出一个动态库 ndklib(名字随意命名),源文件只有 src/main/cpp/native-lib.cpp(如果含有多个的话,需要添加多行类似的代码)
    add_library( # Sets the name of the library.
                 ndklib
    
                 # Sets the library as a shared library.
                 SHARED
    
                 # Provides a relative path to your source file(s).
                 src/main/cpp/native-lib.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.
    # 找到预编译库 log_lib 并link到我们的动态库 ndklib(跟上面的保持一致)中
    target_link_libraries( # Specifies the target library.
                           ndklib
    
                           # Links the target library to the log library
                           # included in the NDK.
                           ${log-lib} )

    这样命名的话生成的so文件如下(前缀自动有个lib):

    新建一个类文件LibNDKDemo.java(名字随意),并且引用我们新建的so库

    添加以下代码:

        // Used to load the 'native-lib' library on application startup.
        static {
            System.loadLibrary("ndklib");
        }
    
        /**
         * A native method that is implemented by the 'native-lib' native library,
         * which is packaged with this application.
         */
        public static native String stringFromJNI();

    一般会有红色报错,不过不用着急。

    鼠标定位到stringFromJNI方法那里,然后点击Alt+Enter,选择第一个AS会自动帮我们生成实现:

    自动跳转到native-lib.cpp文件

    将returnValue修改成真实的数据,并删除旧数据(上方黑色边框标记的代码),修改后的代码如下:

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

    Build——Rebuild Project

    此时,生成了debug模式下的so文件。

    调用

     将MainActivity.java下面的代码删除

    修改后的代码:

    package com.why.project.ndkdemo;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            TextView tv = (TextView) findViewById(R.id.sample_text);
            tv.setText(LibNDKDemo.stringFromJNI());
        }
    }

    运行不报错,说明成功。

    生成release版本的so文件

    PS:(Debug版本和release版本,做个C++的都知道。debug版本是调试的使用的,里面包含很多的调试信息,文件体积也是比较大;release版本发布的时候使用的,会自动的去除掉里面的调试信息,文件体积比较小)。通过Gradle projects生成release版本:

    生成的release版本so文件的位置:

    将so文件结合module生成arr文件

    其实上面的so文件就可以集成到项目中使用了,不过如果想要进一步封装so文件,比如指定cpu类型的so文件,或者还有其他代码需要配合调用等。

    新建module(命名随意,包名需要跟so文件中的java文件包名一致)

    module的包名必须跟so文件中的java文件(比如上面步骤中的LibNDKDemo.java)包名一致。

    将需要用到的cpu类型的so文件(release版本)和java类文件拷贝到module中

     一般不用将所有cpu类型的so文件拷贝到module中,根据实际项目情况。我这里将常用的cpu类型的so文件复制到module中。

    将module生成arr文件

    选择边上的Gradle——选择{module}目录下的 Tasks->build->assembleRelease方法

    生成的arr文件位置:

    将arr文件集成到其他项目中

    注意:集成到的项目的编译、目标、最低SDK版本号应该大于等于生成arr文件的module中设置的版本号。

    具体步骤,参考《【Android Studio安装部署系列】十七、Android studio引用第三方库、jar、so、arr文件

    调用

    运行效果:

    遇到的问题

     如果cpp目录下含有C文件,并且别的cpp文件引用这个C文件了,那么CMakeLists.txt文件需要添加以下配置

    # 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)
    
    add_library(aes-lib STATIC src/main/cpp/aes.c)
    
    # 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.
    # 编译出一个动态库 urlpath,源文件有 src/main/cpp/native-lib.cpp等
    add_library( # Sets the name of the library.
                 urlpath
    
                 # Sets the library as a shared library.
                 SHARED
    
                 # Provides a relative path to your source file(s).
                 src/main/cpp/base64.cpp
                 src/main/cpp/url_auth.cpp
                 src/main/cpp/native-lib.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.
    #找到预编译库 log_lib 并link到我们的动态库 urlauth中
    target_link_libraries( # Specifies the target library.
                           urkpath
                           aes-lib
                           # Links the target library to the log library
                           # included in the NDK.
                           ${log-lib} )

    否则会报错:提示没有找到C文件中的方法。

    参考资料

    详解Android studio ndk配置cmake开发native C

    AndroidStudio报错: undefined reference to 'AndroidBitmap_getInfo'

    Android Studio 下安卓 jni 开发错误 undefined reference to AndroidBitmap_getInfo

    NDK SO 库开发与使用中的 ABI 构架选择

    Android Studio2.2.3使用C++生成so文件

    Android NDK开发扫盲及最新CMake的编译使用

    Android 生成.so文件

    关于Android so文件你所需要了解的

    Android Studio配置CMake开发NDK

    Android JNI作用及其详解

    AndroidStudio官方指南:向您的项目添加 C 和 C++ 代码

    Android Studio 开发JNI笔记--②

    一定能成功的Android NDK环境配置教程

    Android Studio 2.2+ NDK开发

    Android Studio NDK编程-环境搭建及Hello!

    NDK开发 从入门到放弃(七:Android Studio 2.2 CMAKE 高效NDK开发)

    Android NDK开发之从环境搭建到Demo级十步流

    Android Studio NDK环境配置及JNI使用方法

    android studio 调用c/c++工程

    android studio 编译C生成.so文件

    .arr文件的生成与使用

    android studio library生成jar包和aar的方法总结

    android studio生成aar包并在其他工程引用aar包

    Android jniLibs下目录详解(.so文件)

    Android Studio生成so文件的几种方式

    android中.aar文件与.jar文件的区别

    jar文件和aar文件的区别

    Android NDK是什么,为什么我们要用NDK?

    Android Native crash日志分析

    android 底层log分析 内存及backtrace tombstone/crash

    使用新版Android Studio检测内存泄露和性能

    C++中内存泄漏的几种情况

    c语言内存泄露示例

    C++内存泄露的检测(三)

    使用LeakTracer检测android NDK C/C++代码中的memory leak

  • 相关阅读:
    Codeforces 1009F Dominant Indices
    UOJ #35 后缀排序 哈希做法
    bzoj 3670 [Noi2014]动物园
    动态规划 笔记

    常用模块和面向对象 类
    常用模块
    包的使用和常用模块
    日志
    复习列表,模块
  • 原文地址:https://www.cnblogs.com/whycxb/p/9127867.html
Copyright © 2011-2022 走看看