【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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM