Android JNI之靜態(tài)注冊(android studio)

起源

說到JNI,起初是滿臉頭痛。公司業(yè)務(wù),呵呵,opengl,當初是java來寫的,后邊說是c++效率高,對此,我笑一笑從容。任務(wù)到手,沒辦法,就是干。什么某狗,什么36啊,什么某毒,嗖嗖嗖,嘿嘿,一個Hello JNI告訴我這個JNI還是很友好的。描述一下當時我所接受的第一個JNI程序。

一。創(chuàng)建JNI Floder, 將c++代碼放入其中,然后查看頭文件

這個地方要注意,是要生成JNI Floder類型的文件夾,如果隨便創(chuàng)建一個文件夾叫jni,那么不好意思,我大as是不認識的。一個溫馨的提示,讓人愛得沉醉。

make.exe: *** No rule to make target .  Stop.
jni目錄代碼展示圖

頭文件代碼展示圖

二。根據(jù)c++頭文件編寫java端接口,并使用javah命令生成jni頭文件

這個呢,沒什么好說的。java要跟c++進行交流,需要一個橋梁,橋的這頭是java,那頭是c++,中間的是jni,你不搞點事情是不行的。就這樣,普通話出現(xiàn)了,你懂我懂大家懂,才能展開深入交流,嘿嘿嘿。回歸正題,看代碼,看命令:

package net.mapout.jni;

/**
 * Created by Tower on 2017/5/25.
 * java jni 接口申明
 */
public class JNILoader {
    static {
        /**
         * JniDemo 為build的so文件名
         */
        System.loadLibrary("JniDemo");
    }

    public static native String sayHello();
}
打開Terminal,進入/app/src/main/java目錄下
D:\Study_Code\JniDemo>   cd app/src/main/java

執(zhí)行javah命令,生成頭文件net_mapout_jni_JNILoader.h到j(luò)ni目錄下
D:\Study_Code\JniDemo\app\src\main\java>  javah -d ../jni net.mapout.jni.JNILoader

三。實現(xiàn)jni頭文件net_mapout_jni_JNILoader.h,并調(diào)用別人家寫的c++代碼。

這個實現(xiàn)文件可以瞎命名,但必須是.c/.c++為后綴,實現(xiàn)文件嘛,嗯?嗯。

#include "net_mapout_jni_JNILoader.h"
#include "hello.h"
#include <string>

/**
 * std::string 轉(zhuǎn)  jstring
 */
jstring str2jstring(JNIEnv* env, std::string str)
{
    const char* pStr = str.c_str();
    int        strLen    = strlen(pStr);
    jclass     jstrObj   = env->FindClass("java/lang/String");
    jmethodID  methodId  = env->GetMethodID(jstrObj, "<init>", "([BLjava/lang/String;)V");
    jbyteArray byteArray = env->NewByteArray(strLen);
    jstring    encode    = env->NewStringUTF("UTF-8");
    env->SetByteArrayRegion(byteArray, 0, strLen, (jbyte*)pStr);
    return (jstring)env->NewObject(jstrObj, methodId, byteArray, encode);
}

/**
 * 實現(xiàn)頭文件
 */
JNIEXPORT jstring JNICALL Java_net_mapout_jni_JNILoader_sayHello
  (JNIEnv *env, jclass jclass){
    return str2jstring( env, sayHello() );
}
項目文件結(jié)構(gòu)圖

四。到此,準備工作已經(jīng)完成。等等,還有配置。配置嘛,一般一般。

首先,在項目的gradle.properties中配置一句:

android.useDeprecatedNdk=true

看字面意思,過時,沒錯,就是過時了,為啥還要配置呢,怪我咯。時代在進步,從當年的時代在召喚到如今的...今天天氣不錯,涼風(fēng)有幸,秋月無邊,雖然我不是玉樹臨風(fēng)...在打怪升級的路上,免不了有新的boss出現(xiàn),cmake的火爆,這只是個意外,美麗的意外,這個暫且不提。有了首先,當然還需要然后撐腰。在當前 module 下的 build.gradle 中加入使用ndk,配置如下:

android {
    defaultConfig {
        ndk {
            moduleName "JniDemo"
            abiFilters "armeabi", "armeabi-v7a", "x86"  //輸出指定三種abi體系結(jié)構(gòu)下的so庫。可有可無。
            cFlags "-std=c++11" //c++版本
            stl "gnustl_static" //支持 stl 標準庫
        }
    }
}

ndk,最后,還需要設(shè)置ndk環(huán)境。這個就是一個F4,千萬別手殘多按了一個ALT(如果一起按了,那么恭喜你,再接再厲,下次更精彩),進入項目配置界面SDK Location->Android NDK location,設(shè)置NDK目錄即可。當然也可以通過手動在項目的 local.properties 中添加,舉栗如下:

ndk.dir=E\:\\adt-bundle-windows-x86_64-20140321\\android-ndk-r10

激動。想一下,還有什么需要配置?搞事情。忘了就忘了吧,忘一忘,十年笑。

五。收工。

biu biu biu,build apk,見證奇跡的時刻到了,這一刻屬于你們,也屬于我。缺陷不能不提,比如說jni頭文件名稱超長。當初java,c++,c三分天下,誰也不服誰。互聯(lián)網(wǎng)的格局,瞬息萬變。合作,隨之而來。java要跟c/c++交流,無縫對接,請了一個臭皮匠過來,趕時間。然后這位臭皮匠,啰里啰唆、老生常談的做法。一個有效的交流,嗨,我來自xx省xx市,祖籍xx。說完這些,恭喜你,接下來,你可以聊天了。吐槽,歸吐槽。技術(shù),總是在革新。這種方式,稱之為靜態(tài)注冊。那么,相反呢。
附送一張機票,帶你領(lǐng)略世界的浩瀚

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容