AndroidStudio NDK環境3種搭建方式


AndroidStudio NDK環境3種搭建方式

轉載。 https://blog.csdn.net/zhang_jun_ling/article/details/85621427

一、前言

如今Android開發IDE都是使用的AndroidStudio,之前我寫過一篇文章介紹的是如何在Eclipse中搭建NDK環境 Android NDK --初始android NDK
這邊博客介紹下在AndroidStudio中搭建NDK環境的三種方式。

二、知識點概述

本片我們將從以下幾點初步認識、創建Android NDK:
1.Java加載/調用NDK端的代碼;
2.本地 c++代碼的編寫;
3.編寫構建系統文件(android.mkapplication.mk
4.通過構建系統編譯c++代碼
4.1、通過Gradle搭建NDK環境;
4.2、通過NDKBuild搭建NDK環境(重點介紹);
4.3、通過CMake搭建NDK環境;

三、知識點詳解

(1)Java加載/調用NDK端的代碼

1、Java端代碼:

public class MainActivity extends AppCompatActivity {

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

    private TextView mDataView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    private void initView() {
        mDataView = (TextView) this.findViewById(R.id.tv_data);
        mDataView.setText(getStrFromNative());
    }

    private native String getStrFromNative();
}

2、在AndroidStudio打開命令行界面,cd app/src/main/java 運行

javah com.zhangjunling.ndk_environment_gradle.MainActivity
  • 1

這時會自動在目錄下生成一個com_zhangjunling_ndk_environment_gradle_MainActivity.h文件,把文件拷貝到 main/jni 目錄中。

(2) 本地 c++代碼的編寫

由於本編只是介紹NDK環境的搭建問題,所以代碼越簡單越容易把所有的精力都放在環境搭建上,所以c++代碼只是簡單的 HelloWrold程序;

helloworld.cpp

#include "com_zhangjunling_ndk_environment_gradle_MainActivity.h"

JNIEXPORT jstring JNICALL Java_com_zhangjunling_ndk_1environment_1gradle_MainActivity_getStrFromNative
  (JNIEnv *env, jobject obj){
      return env->NewStringUTF("Hello. I'm form native");
}

(3)編寫構建系統文件

在jni目錄下創建Android.mk、Application.mk文件內容如下:
Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := helloworld
LOCAL_SRC_FILES := helloworld.cpp

include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_STL := gnustl_static
APP_ABI := armeabi

關於構建系統里面的鍵值對的含義,現在先不關心,下篇文章我會詳細介紹;

(4)通過構建系統編譯c++代碼

通過Gradle搭建NDK環境

Gradle是androidstudio上的編譯工具,我們可以通過從項目下的local.properties獲取ndk.dir=xxxxxxxx,獲取ndk-build路徑,然后執行ndk-build便可以編譯出需要的動態庫文件;gradle的語法這里不在進行講解,感興趣的可以從網絡上獲取資料學習;
build.gradle代碼如下:

import org.apache.tools.ant.taskdefs.condition.Os

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.zhangjunling.ndk_environment_gradle"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets {
        main {
            jniLibs.srcDir 'src/main/libs'
            jni.srcDirs = []
        }
    }
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn ndkBuild
}

String getNdkBuildPath() {
    Properties properties = new Properties()
    properties.load(project.rootProject.file('local.properties').newDataInputStream())
    def ndkBuildingDir = properties.getProperty("ndk.dir")
    def ndkBuildPath = ndkBuildingDir
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        ndkBuildPath = ndkBuildingDir + '/ndk-build.cmd'
    } else {
        ndkBuildPath = ndkBuildingDir + '/ndk-build'
    }
    return ndkBuildPath
}

task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') {
    println('executing ndkBuild')
    def ndkBuildPath = getNdkBuildPath();
    commandLine ndkBuildPath, '-j8', '-C', file('src/main').absolutePath
}

task ndkClean(type: Exec, description: 'clean JNI libraries') {
    println('executing ndkBuild clean')
    def ndkBuildPath = getNdkBuildPath();
    commandLine ndkBuildPath, 'clean', '-C', file('src/main').absolutePath
}
clean.dependsOn 'ndkClean'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
  • 1過工具欄 Build/ReBuild Project,觀察到libs目錄、obj目錄自動產生,沒有報錯。這可以說明我們的配置沒有什么問題;可以運行項目看到:
Hello. I'm form native
通過NDKBuild搭建NDK環境(重點介紹)

通過ndk-build交叉編譯c++本地代碼是我們重點學習的,后面我會重點介紹通過ndk-build交叉編譯出我們需要的動態庫。本篇只介紹環境的搭建。
Android.mk構建好了之后,ndk-build環境就比較簡單了,步驟:

項目右鍵->Link C++ Project With Gradle 
路徑選擇Android.mk 就OK 了。
通過CMake搭建NDK環境

CMake搭建NDK環境有兩種方式:
1、與ndk-build相同

項目右鍵->Link C++ Project With Gradle 
路徑選擇CMakeList.txt 就OK 了。

2、在Create Android Project的時候底部勾選Include C++ support,項目創建好了之后,自動創建好了NDK環境。我們可以在此基礎上開發NDK。

項目路徑:AndroidStudio環境搭建源碼

 
三種方法 app/build.gradle文件內容如下:
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.myapplication"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        ndk {
            moduleName "Test"
            ldLibs "log"
//          abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種abi體系結構下的so庫,目前可有可無
        }


        // 使用Cmake工具-way1
//start way1
//        externalNativeBuild {
//            cmake {
//                cppFlags ""
//                abiFilters 'arm64-v8a','armeabi-v7a','x86','x86_64'
//            }
//        }
    }

//    // 配置CMakeLists.txt路徑-way1
//    externalNativeBuild {
//        cmake {
//            path "CMakeLists.txt"   // 設置所要編寫的c源碼位置,以及編譯后so文件的名字
//        }
// end way2

// 設置按android.mk 進行編譯-way2
//start way2
    externalNativeBuild {
        ndkBuild {
            path "src/main/jni/Android.mk"
        }
    }
//end way2
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

        }
    }

//    sourceSets.main {
//        jni.srcDirs = ['src/main/jni', 'src/main/jni/']
//        jniLibs.srcDirs "src/main/libs"
//    }
    sourceSets {
        main {
            jniLibs.srcDir 'src/main/libs'
            jni.srcDirs = []
        }
    }
    compileOptions {
        sourceCompatibility = '1.8'
        targetCompatibility = '1.8'
    }
    buildToolsVersion = '28.0.3'

}
/*
//begin -- way3
tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn ndkBuild
}

String getNdkBuildPath() {
    Properties properties = new Properties()
    properties.load(project.rootProject.file('local.properties').newDataInputStream())
    def ndkBuildingDir = properties.getProperty("ndk.dir")
    def ndkBuildPath = ndkBuildingDir
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        ndkBuildPath = ndkBuildingDir + '/ndk-build.cmd'
    } else {
        ndkBuildPath = ndkBuildingDir + '/ndk-build'
    }
    return ndkBuildPath
}

task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') {
    println('executing ndkBuild')
    def ndkBuildPath = getNdkBuildPath();
    commandLine ndkBuildPath, '-j8', '-C', file('src/main').absolutePath
}

task ndkClean(type: Exec, description: 'clean JNI libraries') {
    println('executing ndkBuild clean')
    def ndkBuildPath = getNdkBuildPath();
    commandLine ndkBuildPath, 'clean', '-C', file('src/main').absolutePath
}
clean.dependsOn 'ndkClean'
//end-way3
*/
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:2.0.0-alpha4'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

 在app/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.
#CMakeLists.txt
#指定需要CMake的最小版本
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.
            # 設置so文件名稱.
             Test

             # Sets the library as a shared library.
             SHARED
             # 設置這個so文件為共享.

             # Provides a relative path to your source file(s).
             # 設置這個so文件的源碼文件.
             src/main/jni/Test.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.
                       # 制定目標庫.
                       Test

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

 在jni目錄下的Android.mk內容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Test
LOCAL_SRC_FILES := Test.cpp

LOCAL_LDLIBS :=  -llog

include $(BUILD_SHARED_LIBRARY)

在jni目錄下的Application.mk內容如下:

APP_MODULES := Test
APP_PLATFORM := android-16
APP_ABI := all

 

 


免責聲明!

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



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