起源
說(shuō)到JNI,起初是滿臉頭痛仑濒。公司業(yè)務(wù)偷遗,呵呵,opengl喉酌,當(dāng)初是java來(lái)寫的泵喘,后邊說(shuō)是c++效率高纪铺,對(duì)此,我笑一笑從容霹陡。任務(wù)到手烹棉,沒(méi)辦法怯疤,就是干。什么某狗伏社,什么36啊,什么某毒摘昌,嗖嗖嗖,嘿嘿罕容,一個(gè)Hello JNI告訴我這個(gè)JNI還是很友好的稿饰。描述一下當(dāng)時(shí)我所接受的第一個(gè)JNI程序。
一旅择。創(chuàng)建JNI Floder侣姆, 將c++代碼放入其中,然后查看頭文件
這個(gè)地方要注意汇歹,是要生成JNI Floder類型的文件夾偿凭,如果隨便創(chuàng)建一個(gè)文件夾叫jni,那么不好意思痰哨,我大as是不認(rèn)識(shí)的匾嘱。一個(gè)溫馨的提示,讓人愛得沉醉霎烙。
make.exe: *** No rule to make target . Stop.
二悬垃。根據(jù)c++頭文件編寫java端接口尝蠕,并使用javah命令生成jni頭文件
這個(gè)呢,沒(méi)什么好說(shuō)的看彼。java要跟c++進(jìn)行交流囚聚,需要一個(gè)橋梁标锄,橋的這頭是java,那頭是c++料皇,中間的是jni,你不搞點(diǎn)事情是不行的毒返。就這樣舷手,普通話出現(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锄贼,進(jìn)入/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
三。實(shí)現(xiàn)jni頭文件net_mapout_jni_JNILoader.h冯键,并調(diào)用別人家寫的c++代碼的榛。
這個(gè)實(shí)現(xiàn)文件可以瞎命名逻锐,但必須是.c/.c++為后綴雕薪,實(shí)現(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);
}
/**
* 實(shí)現(xiàn)頭文件
*/
JNIEXPORT jstring JNICALL Java_net_mapout_jni_JNILoader_sayHello
(JNIEnv *env, jclass jclass){
return str2jstring( env, sayHello() );
}
四。到此畅涂,準(zhǔn)備工作已經(jīng)完成。等等立宜,還有配置臊岸。配置嘛,一般一般灯帮。
首先逻住,在項(xiàng)目的gradle.properties中配置一句:
android.useDeprecatedNdk=true
看字面意思,過(guò)時(shí)瞪醋,沒(méi)錯(cuò)装诡,就是過(guò)時(shí)了,為啥還要配置呢鸦采,怪我咯渔伯。時(shí)代在進(jìn)步,從當(dāng)年的時(shí)代在召喚到如今的...今天天氣不錯(cuò),涼風(fēng)有幸蓝厌,秋月無(wú)邊古徒,雖然我不是玉樹臨風(fēng)...在打怪升級(jí)的路上,免不了有新的boss出現(xiàn)代态,cmake的火爆疹吃,這只是個(gè)意外,美麗的意外必尼,這個(gè)暫且不提篡撵。有了首先,當(dāng)然還需要然后撐腰券盅。在當(dāng)前 module 下的 build.gradle 中加入使用ndk膛檀,配置如下:
android {
defaultConfig {
ndk {
moduleName "JniDemo"
abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種abi體系結(jié)構(gòu)下的so庫(kù)∮韭可有可無(wú)嚎杨。
cFlags "-std=c++11" //c++版本
stl "gnustl_static" //支持 stl 標(biāo)準(zhǔn)庫(kù)
}
}
}
ndk,最后刨肃,還需要設(shè)置ndk環(huán)境箩帚。這個(gè)就是一個(gè)F4,千萬(wàn)別手殘多按了一個(gè)ALT(如果一起按了盔然,那么恭喜你,再接再厲挺尾,下次更精彩)刻帚,進(jìn)入項(xiàng)目配置界面SDK Location->Android NDK location涩嚣,設(shè)置NDK目錄即可。當(dāng)然也可以通過(guò)手動(dòng)在項(xiàng)目的 local.properties 中添加顷歌,舉栗如下:
ndk.dir=E\:\\adt-bundle-windows-x86_64-20140321\\android-ndk-r10
激動(dòng)幔睬。想一下,還有什么需要配置赦抖?搞事情辅肾。忘了就忘了吧,忘一忘要尔,十年笑新娜。
五。收工还惠。
biu biu biu私杜,build apk,見證奇跡的時(shí)刻到了嚎幸,這一刻屬于你們寄猩,也屬于我。缺陷不能不提替废,比如說(shuō)jni頭文件名稱超長(zhǎng)。當(dāng)初java诈火,c++状答,c三分天下,誰(shuí)也不服誰(shuí)拍摇」萁兀互聯(lián)網(wǎng)的格局,瞬息萬(wàn)變混卵。合作窖张,隨之而來(lái)。java要跟c/c++交流合陵,無(wú)縫對(duì)接澄阳,請(qǐng)了一個(gè)臭皮匠過(guò)來(lái),趕時(shí)間低剔。然后這位臭皮匠肮塞,啰里啰唆、老生常談的做法猜欺。一個(gè)有效的交流拷窜,嗨涧黄,我來(lái)自xx省xx市笋妥,祖籍xx窄潭。說(shuō)完這些,恭喜你月帝,接下來(lái)均抽,你可以聊天了其掂。吐槽,歸吐槽深寥。技術(shù)贤牛,總是在革新殉簸。這種方式,稱之為靜態(tài)注冊(cè)般卑。那么蝠检,相反呢。
附送一張機(jī)票饲梭,帶你領(lǐng)略世界的浩瀚