版權聲明:本文為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
Android Studio2.2.3使用C++生成so文件
AndroidStudio官方指南:向您的項目添加 C 和 C++ 代碼
Android Studio NDK編程-環境搭建及Hello!
NDK開發 從入門到放棄(七:Android Studio 2.2 CMAKE 高效NDK開發)
Android Studio NDK環境配置及JNI使用方法
android studio library生成jar包和aar的方法總結
android studio生成aar包並在其他工程引用aar包
android 底層log分析 內存及backtrace tombstone/crash
使用LeakTracer檢測android NDK C/C++代碼中的memory leak