C/C++在Android開發(fā)中的應用

JNI開發(fā)系列閱讀

1. 前言

1.1 Android SDK介紹

Android是基于Linux內核的一個手機操作系統(tǒng)歹河,谷歌提供了開發(fā)包(Android SDK)衣屏,程序員可以通過開發(fā)包開發(fā)Android App(應用程序)室抽。Android SDK提供Java語言接口览祖,因此Android應用是使用Java開發(fā)的。

1.2 使用純Java開發(fā)App的缺點

在某些場合下扭仁,使用純Java開發(fā)Android應用程序不完美垮衷,比如:

  • 有高性能算法,Java語言無法滿足
  • 有跨平臺需求乖坠,希望將App移植到iOS
  • 已有代碼的重用

1.3 引入NDK

早在Android 1.6(2009年)時搀突,google就提供了NDK(native development kit),NDK包括了一套Android的交叉編譯環(huán)境和開發(fā)庫熊泵,利用它可以編寫C/C++程序仰迁,并編譯成Android環(huán)境下使用的動態(tài)庫,Java代碼通過Jni規(guī)范戈次,調用C/C++寫的動態(tài)庫轩勘。

目前最新的Android Studio 2.2中,集成了C/C++開發(fā)環(huán)境怯邪,開發(fā)人員在使用C/C++更加簡單了绊寻。

2. 課程內容

NDK中文官方開發(fā)技術文檔地址

ndk

下載配置NDK

NDK下載地址

ndk

配置NDK

ndk
ndk

如果不配置NDK路徑,會報NDK沒有配置錯誤

ndk

JNI開發(fā)HelloWorld

把 Include C++ support的勾打上

Include C++ support

選擇C++11和Toolchain Default均可悬秉,C++11有更多的新特性和功能

jni

點擊Finish后澄步,進入工程目錄,如圖所示和泌,除了java文件夾外多了一個cpp文件夾村缸,cpp就是存放c和c++代碼的文件夾

jni

配置NDK開發(fā)環(huán)境中遇到的坑

Failed to find CMake

jni

什么,CMake是什么鬼武氓,原來梯皿,在Android Studio 2.2 后,NDK開發(fā)更加人性化了县恕,使用了CMake东羹,一款外部構建工具吨述,可與 Gradle 搭配使用來構建原生庫钾菊。如果您只計劃使用 ndk-build桩盲,則不需要此組件苇羡。還有LLDB,一種調試程序罩锐,Android Studio 使用它來調試原生代碼侦高。

點擊Install CMake and sync project停巷,提示如下錯誤

jni
Gradle sync failed: Failed to find CMake.
Install from Android Studio under File/Settings/Appearance & Behavior/System Settings/Android SDK/SDK Tools/CMake.
Expected CMake executable at D:\android-sdk\cmake\bin\cmake.exe.
Consult IDE log for more details (Help | Show Log)

原來是我使用了代理,因為之前Google的鏈接需要翻墻才能夠使用恕酸,所以配置了某代理堪滨,但是該代理不管用,在設置中把代理去掉即可尸疆。在Google在中國開了發(fā)布會后椿猎,Google的鏈接可以使用了惶岭,Android開發(fā)官網也可以上了寿弱,而且翻譯了大量的技術文檔,方便了英語不太好的同學

jni

打開 SDK Manager按灶,安裝上CMake和LLDB

jni開發(fā)
jni開發(fā)
jni開發(fā)

更多更詳細的NDK開發(fā)文檔症革,請看Android官方中文文檔向您的項目添加 C 和 C++ 代碼

2.3 Android Java代碼調用C++代碼

Java部分代碼

public class Jni {
    static  {
        System.loadLibrary("bc-lib"); // libbc-lib.so
    }
 
    private static Jni obj = new Jni();
    private Jni(){}
 
    public static Jni instance(){
        return obj;
    }
 
    // native接口
    public native boolean Login(String username, String password, String type);
    public native boolean Reg(String username, String password, String mobile, String email, String id);
    public native boolean LocationChange(double lng, double lat);
    public native boolean StartOrder(double lng1, double lat1, double lng2, double lat2);
}

C++部分代碼

JNIEXPORT jboolean JNICALL Java_cn_xueguoliang_hc_Jni_Login
        (JNIEnv *env, jobject /* Jni object */, jstring jUsername, jstring jPassword, jstring type)
{
    return (jboolean)User::instance()->Login(j2c(env, jUsername), j2c(env, jPassword),
    j2c(env, type));
}
 
JNIEXPORT jboolean JNICALL Java_cn_xueguoliang_hc_Jni_Reg
        (JNIEnv *env, jobject /* Jni object */,
         jstring jUsername, jstring jPassword, jstring mobile, jstring email, jstring id)
{
    return (jboolean)User::instance()->Reg(
            j2c(env, jUsername),
            j2c(env, jPassword),
            j2c(env, mobile),
            j2c(env, email),
            j2c(env, id));
}
 
JNIEXPORT jboolean JNICALL Java_cn_xueguoliang_hc_Jni_LocationChange
        (JNIEnv *, jobject, jdouble lng, jdouble lat)
{
    User::instance()->LocationChange(lng, lat);
    return (jboolean)true;
}
 
 
JNIEXPORT jboolean JNICALL Java_cn_xueguoliang_hc_Jni_StartOrder
        (JNIEnv *, jobject, jdouble lng1, jdouble lat1, jdouble lng2, jdouble lat2)
{
    return (jboolean)Order::instance()->start(lng1, lat1, lng2, lat2);
}

2.4 C++代碼調用Java代碼

Java代碼

public class Jni {
    static {
        System.loadLibrary("native-lib");
    }
 
    private static Jni obj = new Jni();
    public static Jni instance()
    {
        return obj;
    }
 
    public native void HelloWorld();
 
    void callByCpp()
    {
        Log.e("JniCallback", "hello java");
    }
}

C++代碼

extern "C"
void
Java_com_example_xueguoliang_test_Jni_HelloWorld(
        JNIEnv* env,
        jobject  This ) {
    std::string hello = "Hello from C++";
 
    jclass jniClass = env->FindClass("com/example/xueguoliang/test/Jni");
    jmethodID jmethodID1 = env->GetMethodID(jniClass, "callByCpp", "()V");
    env->CallVoidMethod(This, jmethodID1);
 
    return;
}

2.5 Java和C++字符串轉換

jstring c2j(JNIEnv* env, string cstr)
{
    return env->NewStringUTF(cstr.c_str());
}
 
string j2c(JNIEnv* env, jstring jstr)
{
    string ret;
    jclass stringClass = env->FindClass("java/lang/String");
    jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
 
    // 把參數(shù)用到的字符串轉化成java的字符
    jstring arg = c2j(env, "utf-8");
 
    jbyteArray jbytes = (jbyteArray)env->CallObjectMethod(jstr, getBytes, arg);
 
    // 從jbytes中,提取UTF8格式的內容
    jsize byteLen = env->GetArrayLength(jbytes);
    jbyte* JBuffer = env->GetByteArrayElements(jbytes, JNI_FALSE);
 
    // 將內容拷貝到C++內存中
    if(byteLen > 0)
    {
        char* buf = (char*)JBuffer;
        std::copy(buf, buf+byteLen, back_inserter(ret));
    }
 
    // 釋放
    env->ReleaseByteArrayElements(jbytes, JBuffer, 0);
    return ret;
}

2.6 javah和javap

javah用于生成native接口定義鸯旁,比如

javah -d ../cpp/ com.example.xueguoliang.test.Jni

javap用于生成java函數(shù)的簽名噪矛,比如

javap -s Jni
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市铺罢,隨后出現(xiàn)的幾起案子艇挨,更是在濱河造成了極大的恐慌,老刑警劉巖韭赘,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缩滨,死亡現(xiàn)場離奇詭異,居然都是意外死亡泉瞻,警方通過查閱死者的電腦和手機脉漏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袖牙,“玉大人侧巨,你說我怎么就攤上這事”薮铮” “怎么了司忱?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長畴蹭。 經常有香客問我坦仍,道長,這世上最難降的妖魔是什么撮胧? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任桨踪,我火速辦了婚禮,結果婚禮上芹啥,老公的妹妹穿的比我還像新娘锻离。我一直安慰自己铺峭,他們只是感情好,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布汽纠。 她就那樣靜靜地躺著卫键,像睡著了一般。 火紅的嫁衣襯著肌膚如雪虱朵。 梳的紋絲不亂的頭發(fā)上莉炉,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音碴犬,去河邊找鬼絮宁。 笑死,一個胖子當著我的面吹牛服协,可吹牛的內容都是我干的绍昂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼偿荷,長吁一口氣:“原來是場噩夢啊……” “哼窘游!你這毒婦竟也來了?” 一聲冷哼從身側響起跳纳,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤忍饰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后寺庄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艾蓝,經...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年铣揉,在試婚紗的時候發(fā)現(xiàn)自己被綠了饶深。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡逛拱,死狀恐怖敌厘,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情朽合,我是刑警寧澤俱两,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站曹步,受9級特大地震影響宪彩,放射性物質發(fā)生泄漏。R本人自食惡果不足惜讲婚,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一尿孔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦活合、人聲如沸雏婶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽留晚。三九已至,卻和暖如春告嘲,著一層夾襖步出監(jiān)牢的瞬間错维,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工橄唬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赋焕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓轧坎,卻偏偏與公主長得像宏邮,于是被迫代替她去往敵國和親泽示。 傳聞我的和親對象是個殘疾皇子缸血,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評論 25 707
  • 文章摘要1捎泻、 c、c++項目的創(chuàng)建2埋哟、添加C笆豁、C++項目依賴庫4、配置Gradle赤赊,編譯lib so庫 英文文獻 ...
    Android那些事兒閱讀 12,662評論 0 54
  • 一闯狱、NDK產生的背景 Android平臺從誕生起,就已經支持C抛计、C++開發(fā)哄孤。眾所周知,Android的SDK基于J...
    Ten_Minutes閱讀 3,502評論 1 27
  • 1吹截、產品定位 信息聚合性工具 官方描述:基于興趣的極簡信息推送工具“只看你想看的 ” 2瘦陈、用戶描述 對于信息篩選有...
    沉默的羔洋閱讀 530評論 0 1
  • 我又要開始講故事了。 故事源于生活波俄,就像有些電視劇的情節(jié)晨逝,你覺得狗血、太湊巧懦铺,可生活中真的每時每刻都在發(fā)生著捉貌。 小...
    一縷仙兒氣閱讀 353評論 0 1