標籤:android c c++ ui ndk
android的ndk學習(1) 之前學了一段時間ndk,總覺得要總結一下。ndk使得非常方便地實現java和C與C++代碼的相互溝通,合理地掌握使用ndk可以提高應用程式的執行效率,所以對於學習anndroid開發的人來說,ndk是必須掌握的工具。剛剛開始學習的時候是有點興奮,有點害怕的,興奮是因為之前學過C++語言,能將學過的東西結合在一起,感覺可以做出更好的東西,害怕的是之前聽身邊的大神說ndk在android開發中是非常難的內容之一。但是不管怎麼說我還是找了本書,看了視頻,找了一些電子資料,並且開始了學習ndk之路!
一,第一個程式Hello world 相對來說,使用ndk實現大量的原生方法並讓他們與Java類同步很容易成為一個繁瑣的任務。首先需要建立一個android項目,然後在主函數那裡聲明一個native方法,代碼如下
public class MainActivity extends Activity {public static native String test(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
然後使用命令列,開始-cmd,切換到項目的src目錄下再執行命令如下:
javah -d ../jni 包名.MainActivity
這時候重新整理項目就會發現多了一個jni檔案夾,裡面有個.h的檔案,開啟就是一個c標頭檔
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_exercise_MainActivity */#ifndef _Included_com_example_exercise_MainActivity#define _Included_com_example_exercise_MainActivity#ifdef __cplusplusextern "C" {#endif#undef com_example_exercise_MainActivity_MODE_PRIVATE#define com_example_exercise_MainActivity_MODE_PRIVATE 0L#undef com_example_exercise_MainActivity_MODE_WORLD_READABLE#define com_example_exercise_MainActivity_MODE_WORLD_READABLE 1L#undef com_example_exercise_MainActivity_MODE_WORLD_WRITEABLE#define com_example_exercise_MainActivity_MODE_WORLD_WRITEABLE 2L#undef com_example_exercise_MainActivity_MODE_APPEND#define com_example_exercise_MainActivity_MODE_APPEND 32768L#undef com_example_exercise_MainActivity_MODE_MULTI_PROCESS#define com_example_exercise_MainActivity_MODE_MULTI_PROCESS 4L#undef com_example_exercise_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING#define com_example_exercise_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L#undef com_example_exercise_MainActivity_BIND_AUTO_CREATE#define com_example_exercise_MainActivity_BIND_AUTO_CREATE 1L#undef com_example_exercise_MainActivity_BIND_DEBUG_UNBIND#define com_example_exercise_MainActivity_BIND_DEBUG_UNBIND 2L#undef com_example_exercise_MainActivity_BIND_NOT_FOREGROUND#define com_example_exercise_MainActivity_BIND_NOT_FOREGROUND 4L#undef com_example_exercise_MainActivity_BIND_ABOVE_CLIENT#define com_example_exercise_MainActivity_BIND_ABOVE_CLIENT 8L#undef com_example_exercise_MainActivity_BIND_ALLOW_OOM_MANAGEMENT#define com_example_exercise_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L#undef com_example_exercise_MainActivity_BIND_WAIVE_PRIORITY#define com_example_exercise_MainActivity_BIND_WAIVE_PRIORITY 32L#undef com_example_exercise_MainActivity_BIND_IMPORTANT#define com_example_exercise_MainActivity_BIND_IMPORTANT 64L#undef com_example_exercise_MainActivity_BIND_ADJUST_WITH_ACTIVITY#define com_example_exercise_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L#undef com_example_exercise_MainActivity_CONTEXT_INCLUDE_CODE#define com_example_exercise_MainActivity_CONTEXT_INCLUDE_CODE 1L#undef com_example_exercise_MainActivity_CONTEXT_IGNORE_SECURITY#define com_example_exercise_MainActivity_CONTEXT_IGNORE_SECURITY 2L#undef com_example_exercise_MainActivity_CONTEXT_RESTRICTED#define com_example_exercise_MainActivity_CONTEXT_RESTRICTED 4L#undef com_example_exercise_MainActivity_RESULT_CANCELED#define com_example_exercise_MainActivity_RESULT_CANCELED 0L#undef com_example_exercise_MainActivity_RESULT_OK#define com_example_exercise_MainActivity_RESULT_OK -1L#undef com_example_exercise_MainActivity_RESULT_FIRST_USER#define com_example_exercise_MainActivity_RESULT_FIRST_USER 1L#undef com_example_exercise_MainActivity_DEFAULT_KEYS_DISABLE#define com_example_exercise_MainActivity_DEFAULT_KEYS_DISABLE 0L#undef com_example_exercise_MainActivity_DEFAULT_KEYS_DIALER#define com_example_exercise_MainActivity_DEFAULT_KEYS_DIALER 1L#undef com_example_exercise_MainActivity_DEFAULT_KEYS_SHORTCUT#define com_example_exercise_MainActivity_DEFAULT_KEYS_SHORTCUT 2L#undef com_example_exercise_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL#define com_example_exercise_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L#undef com_example_exercise_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL#define com_example_exercise_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L/* * Class: com_example_exercise_MainActivity * Method: test * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_exercise_MainActivity_test (JNIEnv *, jclass);/* * Class: com_example_exercise_MainActivity * Method: updateFile * Signature: (Ljava/lang/String;)V */<pre name="code" class="java">JNICALL Java_com_example_exercise_MainActivity_updateFile (JNIEnv *, jclass, jstring)#ifdef __cplusplus}#endif#endif
代碼很長,但是我們暫時只要看
JNICALL Java_com_example_exercise_MainActivity_updateFile (JNIEnv *, jclass, jstring)
這就是根據我們一開始在mainactivity定義的那個native方法產生的一個方法。有了標頭檔,我們就可以開始寫.c檔案了,即實現檔案,建立一個檔案main.c,然後輸入代碼如下
#include<stdio.h>#include<stdlib.h>JNIEXPORT jstring JNICALL Java_com_example_exercise_MainActivity_test(JNIEnv * env, jobject obj){return (*env)->NewStringUTF(env, "Hello world !");}
返回一個字串,這就是java與c互動的代碼。但是現在還不能直接運行,還要建立一個android.mk檔案對項目進行配置,代碼如下:
LOCAL_PATH :=$(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := mainLOCAL_SRC_FILES := main.cinclude $(BUILD_SHARED_LIBRARY)
好了,然後就是在mainactivity中使用方法了,代碼如下
public class MainActivity extends Activity {public static native String test(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView t = (TextView)findViewById(R.id.jnitextview); t.setText(test()); } static {System.loadLibrary("main");} }
匯入庫是使用的
static {System.loadLibrary("main");}main是我們在android.mk中配置的一個名字,現在萬事俱備,只差編譯產生so檔案了,我們開啟cmd並且切換到項目的目錄下,執行ndk-build,中間是減號,不是底線,重新整理項目就可以看到libs中多了個檔案夾和裡面的一個libmain.so檔案,這時候就可以運行項目了!如果沒有意外就會出現helloworld在手機頻幕上。二,列印log列印log是必須掌握的只是,所以這裡介紹一下怎麼配置,首先是配置android.mk檔案,添加一行代碼LOCAL_LDLIBS += -llog
完整的android.mk代碼如下
LOCAL_PATH :=$(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := mainLOCAL_SRC_FILES := main.cLOCAL_LDLIBS += -lloginclude $(BUILD_SHARED_LIBRARY)
然後在實現檔案中添加標頭檔#include<android/log.h>並且宏定義要列印log的類型#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
在代碼中使用LOGI()或者LOGW,運行程式,然後就可以列印log了!更加詳細的可以去看java api文檔中的ndk篇。三,總結剛開始學jni,要配置這個要配置那個的非常麻煩,但是寫了一個helloworld以後感覺配置也就那樣,萬事開頭難啊!相信後面的學習會越來越難,但是也會越來越有意思,希望繼續加油!
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
android的ndk學習(1)