Android JNI/NDK開發(fā)之基本姿勢(shì)<一>

開發(fā)環(huán)境信息

列舉下本篇文章編寫的Demo基本信息
操作系統(tǒng) Windows 10 家庭中文版
開發(fā)工具 Android Studio 2.1
SDK new
NDK new

掃盲之SDK、JDK、NDK的區(qū)別

SDK 軟件開發(fā)工具包;英語(yǔ)全稱:Software Development Kit
JDK Java語(yǔ)言的軟件開發(fā)工具包;英語(yǔ)全稱:Java Development Kit
NDK 原生軟件開發(fā)工具包;英語(yǔ)全稱:Native Development Kit;被Google稱為NDK

由此可見,其實(shí)不管什么XDK,都可以叫SDK,可能為了有很好的區(qū)分,便有了JDKNDK,所以我們有的時(shí)候常說的SDK并不是特指安卓開發(fā)工具包,而只是我們都是同行,交流的時(shí)候都知道指的是什么,其實(shí)你們會(huì)發(fā)現(xiàn),我們常常接三方平臺(tái)的時(shí)候,那些工具包也是叫SDK,但可能我們?cè)诮涣鞯臅r(shí)候就會(huì)加個(gè)前綴,比如:微信分享SDK、支付寶SDK、xxSDK。


學(xué)習(xí)目標(biāo)

1.配置NDK環(huán)境并學(xué)會(huì)合理利用Android Studio工具進(jìn)行NDK的編譯
2.點(diǎn)擊某個(gè)按鈕顯示由native方法返回的一段文本信息;java > native
3.點(diǎn)擊某個(gè)按鈕調(diào)用某個(gè)native方法,在由此native方法調(diào)用java方法;java > native > java

創(chuàng)建工程并配置NDK路徑

快速利用Android Studio創(chuàng)建一個(gè)簡(jiǎn)單的Hello Word工程,相信這個(gè)大家都已經(jīng)熟門熟路了,如果你還不知道使用Android Studio,我只能說你太不open了。

配置工程N(yùn)DK有兩種方法,和配置SDK一模一樣,這里就說說兩個(gè)SDK [1] 的配置方法吧

1.直接在local.properties文件中手動(dòng)配置

ndk.dir=E:\Android\sdk\ndk-bundle //NDK路徑
sdk.dir=E:\Android\sdk //SDK路徑

2.Open Module Settings

選中工程名,鼠標(biāo)右鍵>Open Module Settings或直接按下F4功能鍵


sdk.dir

編寫帶有Native方法的類

1.創(chuàng)建JniDemoClass文件并創(chuàng)建一個(gè)native方法public native String getHelloWordText(),用來獲取Hello Word文本

public class JniDemo {

    public native String getHelloWordText();
    
}

編譯含有Native方法的類

javac JniDemo.java

得到JniDemo.class文件后繼續(xù)用javah命令編譯JniDemo.class,格式:javah package name + class name,示例:

javah com.jay.ndkdemo.JniDemo

其中com.jay.ndkdemo是此類所在的包名,編譯成功會(huì)在當(dāng)前目錄生成一個(gè)*.h文件,這種文件類是C或C++所支持的頭文件類型。內(nèi)容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jay_ndkdemo_JniDemo */

#ifndef _Included_com_jay_ndkdemo_JniDemo
#define _Included_com_jay_ndkdemo_JniDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jay_ndkdemo_JniDemo
 * Method:    getHelloWordText
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jay_ndkdemo_JniDemo_getHelloWordText
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

本文示例生成的名稱叫:com_jay_ndkdemo_JniDemo.h,很明顯,以包名+類名生成一個(gè)文件名,我們?cè)诠こ讨袆?chuàng)建一個(gè)文件夾jni,此目錄與工程中的java目錄同級(jí),并把生成的*.h文件放置到jni文件夾中。

jni


編寫C/C++代碼并實(shí)現(xiàn)*.h中聲明的方法

創(chuàng)建*.c<C>*.cpp<C++>文件,編寫Code,本文編寫的是*.c文件,也就是采用C語(yǔ)法來實(shí)現(xiàn)

#include <com_jay_ndkdemo_JniDemo.h>

/*
 * Class:     com_jay_ndkdemo_JniDemo
 * Method:    getHelloWordText
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jay_ndkdemo_JniDemo_getHelloWordText
  (JNIEnv * env, jobject obj)
{
 return (*env)->NewStringUTF(env,"Hello Word From Jni");
}

簡(jiǎn)單說下編寫方法:
1.include 下我們前面生成的*.h文件
2.實(shí)現(xiàn)*.h中未實(shí)現(xiàn)的方法,注意方法名要與*.h中保持一致

到這里,我們的工作已經(jīng)完成了90%,剩下的只是配置與調(diào)用了


NDK編譯

這個(gè)時(shí)候我們就要發(fā)揮Android Studio工具的方便性了,怎么利用NDK編譯了?前面我們已經(jīng)配置好了NDK路徑,那么直接利用Android Studio的菜單build > Rebuild Project,執(zhí)行后發(fā)現(xiàn)失敗

ndk-build-error

錯(cuò)誤信息:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugNdk'.
> Error: NDK integration is deprecated in the current plugin.  Consider trying the new experimental plugin.  For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental.  Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

其實(shí)這個(gè)錯(cuò)誤信息中已經(jīng)告訴我們?cè)趺唇鉀Q

Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration

叫我們?cè)?code>gradle.properties文件中輸入android.useDeprecatedNdk=true,輸入后我們?cè)俅尉幾g,這次編譯成功,但發(fā)現(xiàn)一個(gè)警告:

ndk-build-warning

警告信息:

Warning: Native C/C++ source code is found, but it seems that NDK option is not configured.  Note that if you have an Android.mk, it is not used for compilation.  The recommended workaround is to remove the default jni source code directory by adding: 
 android {
    sourceSets {
        main {
            jni.srcDirs = []
        }
    }
}
to build.gradle, manually compile the code with ndk-build, and then place the resulting shared object in src/main/jniLibs.

大概意思就是我們?nèi)鄙僖粋€(gè)文件:Android.mk,但人家給了我們推薦的方法,那就是在對(duì)應(yīng)module工程中的build.gradle文件中添加如下代碼:

sourceSets {
    main {
        jni.srcDirs = []
    }
}

添加后我們?cè)俅尉幾g,這次編譯成功并沒錯(cuò)誤也沒警告,終于NDK編譯通過了,我們查看編譯結(jié)果:\NdkDemo\app\build\intermediates\ndk

ndk-build-result

我們可以看到,生成了一系列的*.so文件,是不是感覺很熟悉了?但我們發(fā)現(xiàn)*.so文件名叫libapp.so,這個(gè)文件名是怎么來的了?可以更改嗎?答案是肯定的。

先說說默認(rèn)文件名的生成格式:lib + module name.so

更改默認(rèn)文件名名稱:

android {
    ......
    defaultConfig {
        ......
        ndk {
            moduleName 'jnidemo'//自定義名稱
        }
    }
}

好,我們?cè)俅尉幾g,編譯完成后我們查看編譯路徑下,悶B了吧,沒看到ndk目錄了,有人就會(huì)說了,你這個(gè)坑貨,騙人的,友誼的小船說翻就翻。

sourceSets {
    main {
//      jni.srcDirs=[]
      jniLibs.srcDir 'src/main/jni_src'//告知jni源碼目錄
    }
}

還記得這個(gè)配置不,對(duì),就是我們之前第一次編譯的時(shí)候解決一個(gè)警告按照警告的推薦寫的配置代碼,只要改成和上面一樣,編譯后就又可以看到編譯目錄下的ndk文件夾了,查看編譯后的*.so文件,發(fā)現(xiàn)文件名已經(jīng)改了,并且生成的格式和我之前說的一樣。

為什么我們按照推薦方法會(huì)有問題了?
1.可能是bug
2.我覺得應(yīng)該是我們既然了默認(rèn)的一些參數(shù),當(dāng)然就要對(duì)其它參數(shù)做出相應(yīng)的修改


好了,看完這篇文章,我們基本實(shí)現(xiàn)了我們的學(xué)習(xí)目標(biāo)的第一點(diǎn),后面兩點(diǎn)請(qǐng)看后續(xù)系列文章


  1. 此處SDK包含NDK與安卓SDK ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,355評(píng)論 25 708
  • Android游戲開發(fā)實(shí)踐(1)之NDK與JNI開發(fā)02 承接上篇Android游戲開發(fā)實(shí)踐(1)之NDK與JNI...
    AlphaGL閱讀 3,940評(píng)論 0 24
  • 一、NDK產(chǎn)生的背景 Android平臺(tái)從誕生起,就已經(jīng)支持C、C++開發(fā)。眾所周知,Android的SDK基于J...
    Ten_Minutes閱讀 3,737評(píng)論 1 27
  • LZ-Says:半夜睡覺滾了地上了,無奈之下醒來了,想想最近幾天因?yàn)橐粋€(gè)括號(hào)導(dǎo)致JNI遲遲不能開展,心里面無奈又崩...
    靜心Study閱讀 2,267評(píng)論 0 6
  • 原本約同學(xué)周四見面的,今天接到同學(xué)電話因?yàn)榧依餇t子壞了,改在下周見面。 公司開會(huì)一天就忙活公司的事了。 晚上和客戶...
    唐豆閱讀 145評(píng)論 0 0

友情鏈接更多精彩內(nèi)容