使用Android Studio 進行NDK開發和調試

儘管Android Studio已經愈來愈流行了,但不少人仍是習慣於Eclipse或源碼環境下開發JNI應用。我的認爲使用Android Studio做NDK開發是必然趨勢,因此本文將簡單介紹如何在Android Studio上實現NDK開發。html

簡介

JNI

JNI 是Java Native Inteface的縮寫,是Java中定義的一種用於鏈接Java和C/C++接口的一種實現方式。java

NDK

NDK 是 Native Developmentit的縮寫,是Google在Android開發中提供的一套用於快速建立native工程的一個工具。
使用這個工具能夠很方便的編寫和調試JNI的代碼。android

NDK可從官網AndroidDevTools(我的網站)下載。git

Gradle

Gradle 是一個基於Apache Ant和Apache Maven概念的項目自動化建構工具。它使用一種基於Groovy的特定領域語言(DSL)來聲明項目設置。github

以往Android NDK開發須要在Eclipse或源碼環境下,創建並配置Android.mk和Application.mk,且還要經過java命令生成.h頭文件,才能編譯生成so庫。但在Android Studio中這些步驟都不須要,由於Gradle足夠強大,只需配置Gradle便可編譯生成so庫。api

gradle-experimental插件

在2015年5月的Google I/O大會上, Google宣佈Android Studio開始支持NDK開發,經過和JetBrains的合做,將Clion整合進了Android Studio 1.3,並免費支持NDK C++開發。app

同年7月,在Android Studio 1.3版本上添加了gradle-experimental插件,該插件支持NDK開發和調試,且帶有代碼不全和重構等高級功能。工具

CAVEAT: Note that this plugin is a preview of the plugin for feedback on performance and NDK integration. The Gradle API for the new component model is not final, which means each plugin will only work with a specific version of Gradle.
Additionally, the DSL may also change.gradle

目前這個插件是預覽插件,並非正式的。意味着插件只能運行在特定的Gradle版本上。而且DSL(領域特定語言)也要改變。網站

使用Experimental插件進行NDK開發

使用Experimental插件的必要條件

一、Gradle-2.5或更高版本
二、Android Studio 1.3 RC1或更高版本
三、Android NDK r10e 或更高版本
四、Build Tools 19.0.0 或更高版本

每一個版本的experimental插件須要特定的Gradle版本

Plugin Version Gradle Version
0.1.0 2.5
0.2.0 2.5
0.3.0-alpha3 2.6
0.4.0 2.8
0.6.0-alpha1 2.8
0.6.0-alpha5 2.10
0.7.0-alpha1 2.10

NDK開發步驟

一、新建一個Android標準工程

二、按F4打開工程配置

三、使用experimental插件須要對如下三個文件作修改:

./build.gradle
./app/build.gradle
./gradle/wrapper/gradle-wrapper.properties
./gradle/wrapper/gradle-wrapper.properties

將distributionUrl改用gradle-2.10版本

distributionUrl=https\\://services.gradle.org/distributions/gradle-2.10-all.zip
./build.gradle

使用com.android.tools.build:gradle-experimental代替 com.android.tools.build:gradle

buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            //classpath 'com.android.tools.build:gradle:2.0.0'
            classpath "com.android.tools.build:gradle-experimental:0.7.0-alpha4"

            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
./app/build.gradle

這部分改動比較大,修改及註釋以下:

// 用com.android.model.application 代替 com.android.application
    apply plugin: 'com.android.model.application'

    // 將原來的配置用 model{}包起來
    model {
        android {
            // 取值必須使用 「=」 形式
            // 不然會報 「Error:Cause: org.gradle.api.internal.ExtensibleDynamicObject」 錯誤
            compileSdkVersion = 23
            buildToolsVersion = '23.0.2'

            defaultConfig {
                // 取值必須使用 「=」 形式
                applicationId = "com.connorlin.jnitest"
                //這裏要注意是 xxSdkVersion.apiLevel
                // 不然會報 「Unable to load class com.android.build.gradle.managed.ProductFlavor_Impl」錯誤
                minSdkVersion.apiLevel = 15 
                targetSdkVersion.apiLevel = 23
                versionCode =  1
                versionName = "1.0"
            }

            // 配置NDK
            ndk {
                // 生成so的名字,是必須的
                moduleName ="JNITest"
                toolchain = 'clang'
                CFlags.add('-std=c99')
                // 添加依賴庫
                ldLibs.addAll(['android','OpenSLES', 'log'])
                // 生成不一樣abi體系的so庫
                abiFilters.addAll(['armeabi', 'armeabi-v7a', 'arm64-v8a',
                                   'x86', 'x86_64',
                                   'mips', 'mips64'])
            }

            buildTypes {
                release {
                    minifyEnabled = false
                    // 這裏注意:使用proguardFiles.add()方法
                    proguardFiles.add(file('proguard-rules.txt'))
                }
            }
        }
    }

四、在Java文件(這裏以JNIActivity爲例)中添加代碼

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

    public native String testJni();

此時,native方法標紅,提示以下:

testJni()方法上按快捷鍵Alt + Enter,出現以下提示

按回車,會自動在main目錄下生成jni文件夾,內含JniDemo.c:

#include <jni.h>

    JNIEXPORT jstring JNICALL
    Java_com_connorlin_jnitest_MainActivity_testJni(JNIEnv *env, jobject instance) {
        // TODO
        return (*env)->NewStringUTF(env, "returnValue");
    }

你會發現,Android Studio已經爲咱們自動生成JNI方法了,你只須要再寫實現就能夠了。

至此,最簡單的NDK開發配置完畢。

其餘配置,請參考官方文檔,Demo能夠參考官方Demo

換種方式進行NDK開發

既然預覽版com.android.tools.build:gradle-experimental支持NDK,
那麼正式版com.android.tools.build:gradle 是否也能夠實現NDK開發呢?

通過實驗,答案是能夠的!

步驟

一、新建一個Android標準工程,並在工程設置中配置NDK路徑。

二、打開 app level 的 build.gradle, 配置NDK

ndk {
        moduleName "NdkJniDemo"          //生成的so名字
        abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種abi體系結構下的so庫,可忽略
    }

而後點擊右上角Sync Now, 會有以下錯誤提示:

按提示,在 gradl.properties 文件里加上android.useDeprecatedNdk=true便可。

三、在Java文件(這裏以JNIActivity爲例)中添加代碼

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

    public native String testJni();

接着在testJni()方法上按快捷鍵Alt + Enter並回車,

一樣,會自動在main目錄下生成jni文件夾,內含JniDemo.c:

#include <jni.h>

可是,你會發現並不會自動生成JNI方法,這是由於使用experimental插件纔會自動生成代碼。

那自動生成代碼該如何實現呢?

方法依然是使用gradle-experimental插件,可是不一樣的是,在app level的build.gradle中添加com.android.tools.build:gradle-experimental依賴。

四、在./app/build.gradle中添加gradle-experimental依賴

dependencies {
        compile 'com.android.tools.build:gradle-experimental:0.7.0'
    }

再次在testJni()方法上按快捷鍵Alt + Enter並回車

#include <jni.h>

    JNIEXPORT jstring JNICALL
    Java_com_connorlin_jnitest_MainActivity_testJni(JNIEnv *env, jobject instance) {
        // TODO
        return (*env)->NewStringUTF(env, "returnValue");
    }

你會發現成功自動生成JNI方法了。

反作用

這種方式有個反作用是 Run app 時可能會報錯:

此時,只要將gradle-experimental依賴註釋掉便可正常運行,同時會保持自動生成代碼的功能,直到關閉工程。
這樣咱們在須要自動生成代碼的時候,將gradle-experimental依賴再次打開便可。

NDK調試

默認狀況下是不支持NDK調試的,但要支持NDK調試也很簡單,只要作些簡單配置便可。

一、打開JNI調試

二、配置Android Native - Debugger

三、下載LLDB 2.0

首次底部會報錯

點擊 Fix,提示下載LLDB 2.0,照作,下載安裝便可。

四、完成NDK調試配置,能夠正常調試了。


 

文/ConnorLin(簡書做者) 原文連接:http://www.jianshu.com/p/2690c9964110 著做權歸做者全部,轉載請聯繫做者得到受權,並標註「簡書做者」。

相關文章
相關標籤/搜索