起源
說到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.
二。根據(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() );
}
四。到此,準備工作已經(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)略世界的浩瀚