Android Studio 3.0 利用cmake搭建jni環境(很詳細哦)

我用的Android Studio是3.0的版本,然後想搭建一下jni的環境。這裏把自己遇到的問題和注意點都記錄下。
首先是需要在android studio裏面安裝最基本的環境。
打開Default Preference裏面查看SDK Tool選項。
這裏寫圖片描述
CMake、LLDB、NDK這三個勾選上去,然後安裝。
安裝好了以後,在File-》Project Structure的SDK Location裏面應該可以看到Android NDK Location的地址。
如下圖所示。
這裏寫圖片描述
新建一個Android Studio項目,注意到我這裏新建項目的時候並沒有什麼include C++ 的勾選項目,as也不會在項目生成後幫忙生成cmakelist.txt, 我以爲這個as版本的問題,後面也能夠順利搭建就行了。
這裏寫圖片描述
首先新建一個JNITest類,代碼如下:

package jnifive.preqel.com.jnifive;
public class JNITest {

    static {
        System.loadLibrary("jnilib");
    }

    public native String getString();
}

這裏的jnilib代表的就是你的jni庫名。這時候編譯器會提示有錯誤,不用管。
然後根據javah工具來生成c語言頭文件。
首先配置好你的jdk環境變量,即在termianla終端裏面可以正常使用javac和javah。
到JNITest同級目錄下面用javac 生成class文件。
具體操作:用終端進入到JNITest.java所在目錄,執行 javac JNITest.java
如果成功會在同目錄下生成JNITest.java,這個應該沒什麼問題。
然後在終端裏面用命令行退到java文件目錄下面,用javah生成c++頭文件。
終端輸入:javah -jni jni.example.com.testjni6.JNITest
注意:請用cd命令退到工程文件目錄的java同級目錄下面執行,否則會提示找不到文件
成功後會生成
這裏寫圖片描述

然後
右擊app目錄,新建Folder-》Jni Folder 建立jni目錄
這裏寫圖片描述

點擊下一步後看見android studio在工程下面幫我們生成了一個cpp的文件夾,並沒有看到所謂的jni文件夾。暈了?沒關係,其實是一樣的,把Android studio的視圖轉化爲Project,找到app目錄,然後在main下面找到jni目錄。如圖所示
這裏寫圖片描述

然後把剛纔的jni_example_com_testjni6_JNITest.h文件拷貝進來。
在這個jni目錄下面創建一個新的c/c++ source file。
名字就叫main.cpp好了。裏面代碼如下:

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

注意這裏的包名都要對應上。
這時候build一下工程你會發現
這裏寫圖片描述

這時候不用配什麼android.useDeprecatedNdk=true ,這個東西在3.0以後好像是被取消了,配了只會走錯路。(表示折騰了很久。。。)
正確的做法是直接用cmakelist.txt配置環境。在工程app/java/目錄(並非一定要這個地方,但是最後在build.gradle裏面應正確關聯)下面直接新建一個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.
             jnilib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             ../jni/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.
                       jnilib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

帶#號全是註釋,所以這裏有幾個重要的屬性要配的。
add_library 下面首先指明庫的名稱,這裏是jnilib,Provides a relative path to your source file(s),這裏要用相對路徑指到cpp文件所在的路徑。cmakelist的配置,這個配置一定要配對,否則會抱什麼
CMake Error: CMake can not determine linker language for target: 的錯誤。

然後在app的build.gradle下面新增一些語句。
在defaultConfig下面新增

   ndk {
            abiFilters 'armeabi', 'armeabi-v7a','x86'
        }

    externalNativeBuild {
            cmake {
                cppFlags ""
                //生成多個版本的so文件
                abiFilters 'arm64-v8a','armeabi-v7a','x86','x86_64'
            }
        }

這裏表示支持的abi版本,如果設備的abi版本不在這個列表中是安裝不了apk的。
然後在同一文件的android下面加入下面的代碼

    externalNativeBuild {
        cmake {
            path "src/main/java/CMakeLists.txt"  // 設置所要編寫的c源碼位置,以及編譯後so文件的名字
        }
    }

path 就是CMakeLists.txt的相對路徑。
好了。
最後在MainActivity裏面調用一下這個JNITest的getString()函數就行了,關鍵代碼如下:

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv = (TextView) findViewById(R.id.textview);
        JNITest ndkTest = new JNITest();
        try {
            tv.setText(ndkTest.getString());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

這裏寫圖片描述
如有需要,請點擊下面鏈接:
項目github源碼地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章