C/C++在Android开发中的应用
JNI開發系列閱讀
JNI與底層調用1:http://blog.csdn.net/axi295309066/article/details/60758515
JNI與底層調用2:http://blog.csdn.net/axi295309066/article/details/60778076
C/C++在Android開發中的應用:http://blog.csdn.net/axi295309066/article/details/60954771
1. 前言
1.1 Android SDK介紹
Android是基于Linux內核的一個手機操作系統,谷歌提供了開發包(Android SDK),程序員可以通過開發包開發Android App(應用程序)。Android SDK提供Java語言接口,因此Android應用是使用Java開發的。
1.2 使用純Java開發App的缺點
在某些場合下,使用純Java開發Android應用程序不完美,比如:
- 有高性能算法,Java語言無法滿足
- 有跨平臺需求,希望將App移植到iOS
- 已有代碼的重用
1.3 引入NDK
早在Android 1.6(2009年)時,google就提供了NDK(native development kit),NDK包括了一套Android的交叉編譯環境和開發庫,利用它可以編寫C/C++程序,并編譯成Android環境下使用的動態庫,Java代碼通過Jni規范,調用C/C++寫的動態庫。
目前最新的Android Studio 2.2中,集成了C/C++開發環境,開發人員在使用C/C++更加簡單了。
2. 課程內容
NDK中文官方開發技術文檔地址
下載配置NDK
NDK下載地址
配置NDK
如果不配置NDK路徑,會報NDK沒有配置錯誤
JNI開發HelloWorld
把 Include C++ support的勾打上
選擇C++11和Toolchain Default均可,C++11有更多的新特性和功能
點擊Finish后,進入工程目錄,如圖所示,除了java文件夾外多了一個cpp文件夾,cpp就是存放c和c++代碼的文件夾
配置NDK開發環境中遇到的坑
Failed to find CMake
什么,CMake是什么鬼,原來,在Android Studio 2.2 后,NDK開發更加人性化了,使用了CMake,一款外部構建工具,可與 Gradle 搭配使用來構建原生庫。如果您只計劃使用 ndk-build,則不需要此組件。還有LLDB,一種調試程序,Android Studio 使用它來調試原生代碼。
點擊Install CMake and sync project,提示如下錯誤
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在中國開了發布會后,Google的鏈接可以使用了,Android開發官網也可以上了,而且翻譯了大量的技術文檔,方便了英語不太好的同學
打開 SDK Manager,安裝上CMake和LLDB
更多更詳細的NDK開發文檔,請看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");// 把參數用到的字符串轉化成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.Jnijavap用于生成java函數的簽名,比如
javap -s Jni總結
以上是生活随笔為你收集整理的C/C++在Android开发中的应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android应用开发:网络编程-2
- 下一篇: Google VR全景图片与视频功能开发