Android中使用NativeActivity进行APP开发

来源:互联网 发布:单片机总线 编辑:程序博客网 时间:2024/06/05 21:08

自古以来,Android的主要开发语言都是以Java为主,也有很多开发者使用其他语言,当然也有混合开发的,比如Java&C or Java&C++等,一直以来,android的开发语言层出不穷

现在看来,Android的开发语言相当多,像什么C# for Android 使用C#进行Android开发,也有Qt for Android 使用Qt图形库(C++)进行Android开发(PS:这玩意空包打出来都极其笨重)等等.不过,这无疑为Android的开发者添加了更多的选择,对于开发者来说也是件好事情.


好吧,进入正题,我们使用纯C | C++来开发Android程序


实际上,Android中使用纯C来开发,其原理也并非纯C,只是将Java层封装好了,使用Jni来调用C | C++的library,不过呢,我们不需要去管那些Java层已经封装好的东西,只需要安心写C | C++代码就行了.

为了方便,我就直接使用AndroidStudio吧(自从这货支持NDK了以后,我就觉得这玩意写Native代码贼方便)


好吧,首先打开AndroidStudio->File->New->New Project...

切记,一定得吧 Include C++ Support 勾上,至于为什么,不用我多解释吧

然后继续吧,其实就相当于创建一个NDK项目只不过到最后使用的不是Java代码,而是C代码而已

接着一路Next

然后到Activity选择界面时,选择 Add No Activity ,然后继续,一直到Finish

如果中途报出 NDK not configured. 的错误,表示AndroidStudio没有检测到你的NDK路径,你需要手动选择

那么手动选择怎么操作呢?很简单的File->Project Structure...然后在弹出的窗口中对NDK的路径进行配置

选择完了就OK吧,然后等待AndroidStudio创建工程创建完成.

创建完成之后的项目结构大概就是这样的

Java文件夹内虽然有包存在,但是包内是不包含Java代码的

接下来,我们需要对一些文件进行修改

首先AndroidMainfest.xml

因为我们没有使用Java代码,所以要在AndroidMainfest.xml文件中的Application节点中添加

android:hasCode="false"

修改完成后大致就是这样的吧

然后,对着里有几点做简单的解释

android:hasCode="false" 表示该应用不包含Java代码

android.app.NativeActivity 这是固定的,前面提到程序的工作机制是使用Jni加载.so文件,而这个NativeActivity就是用Java封装的用来加载,so用的,固定写法

<meta-data 

android:name="android.app.lib_name" <!--这点表示加载lib声明-->

android:value="native-main" <!--这里表示你的代码编译过后的.so文件的名称,比如我的项目编译出来的名称为libnative-main.so,这里就填写native-main,去掉lib & .so-->

/>

然后<intent-filter>里边的东西是默认启动Activity的配置

到这里,整个项目就弄的差不多了,然后开始我们的代码编写工作

至于那个native-lib.cpp没啥用,干脆删了吧

首先,在cpp目录中添加一个.h文件,名称随意吧,比如我的叫做NativeMain.h

然后在里边导入native_activity.h并添加NativeActivity的一些生命周期函数声明

[cpp] view plain copy
 print?
  1. #ifndef _ANDROID_NATIVE_MAIN_H_  
  2. #define _ANDROID_NATIVE_MAIN_H_  
  3.   
  4. #include <android/native_activity.h>  
  5.   
  6. /* 
  7.  * 定义绑定声明周期函数 
  8.  */  
  9. void bindLifeCycle(ANativeActivity *activity);  
  10.   
  11. /* 
  12.  * 定义NativeActivity的入口函数 
  13.  */  
  14. void ANativeActivity_onCreate(ANativeActivity *activity, void *savedState, size_t savedStateSize);  
  15.   
  16. /* 
  17.  * 处理事件队列的函数 
  18.  */  
  19. void *looper(void *args);  
  20.   
  21. /** 
  22.  * 定义onStart方法,对应Java中的onStart 
  23.  */  
  24. void onStart(ANativeActivity *activity);  
  25.   
  26. /** 
  27.  * 定义onResume方法,对应Java中的onResume 
  28.  */  
  29. void onResume(ANativeActivity *activity);  
  30.   
  31. /** 
  32.  * 定义储存静态对象状态方法 
  33.  */  
  34. void *onSaveInstanceState(ANativeActivity *activity, size_t *outSize);  
  35.   
  36. /** 
  37.  * 定义onPause方法,对应Java中的onPause 
  38.  */  
  39. void onPause(ANativeActivity *activity);  
  40.   
  41. /** 
  42.  * 定义onStop方法,对应Java中的onStop 
  43.  */  
  44. void onStop(ANativeActivity *activity);  
  45.   
  46. /** 
  47.  * 定义onDestory方法,对应Java中的onDestroy 
  48.  */  
  49. void onDestroy(ANativeActivity *activity);  
  50.   
  51. /** 
  52.  * 定义窗口焦点改变方法 
  53.  */  
  54. void onWindowFocusChanged(ANativeActivity *activity, int hasFocus);  
  55.   
  56. /** 
  57.  * 定义Native窗口创建方法 
  58.  */  
  59. void onNativeWindowCreated(ANativeActivity *activity, ANativeWindow *window);  
  60.   
  61. /** 
  62.  * 定义Native窗口销毁方法 
  63.  */  
  64. void onNativeWindowDestroyed(ANativeActivity *activity, ANativeWindow *window);  
  65.   
  66. /** 
  67.  * 定义输入队列创建方法 
  68.  */  
  69. void onInputQueueCreated(ANativeActivity *activity, AInputQueue *queue);  
  70.   
  71. /** 
  72.  * 定义输入队列销毁方法 
  73.  */  
  74. void onInputQueueDestroyed(ANativeActivity *activity, AInputQueue *queue);  
  75.   
  76. /** 
  77.  * 定义配置改变方法 
  78.  */  
  79. void onConfigurationChanged(ANativeActivity *activity);  
  80.   
  81. /** 
  82.  * 定义低内存方法 
  83.  */  
  84. void onLowMemory(ANativeActivity *activity);  
  85.   
  86. #endif // !_ANDROID_NATIVE_MAIN_H_  

这些方法在native_activity.h中有引用,所以我们要自行设置方法回调,但是在这之前,我们需要先进行方法的实现

我们在创建一个cpp文件,用来编写方法的实现名称随意,比如我的叫做NativeMain.cpp

在这里边对刚才在NativeMain.h里边声明的方法进行实现和绑定回调

[cpp] view plain copy
 print?
  1. #include <android/log.h>  
  2.   
  3. #include "NativeMain.h"  
  4.   
  5. #define LOG_TAG "NATIVE_MAIN_CPP"  
  6. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR ,LOG_TAG ,__VA_ARGS__)  
  7.   
  8. void onStart(ANativeActivity *activity) {  
  9.   
  10. }  
  11.   
  12. void onResume(ANativeActivity *activity) {  
  13.   
  14. }  
  15.   
  16. void *onSaveInstanceState(ANativeActivity *activity, size_t *outSize) {  
  17.   
  18. }  
  19.   
  20. void onPause(ANativeActivity *activity) {  
  21.   
  22. }  
  23.   
  24. void onStop(ANativeActivity *activity) {  
  25.   
  26. }  
  27.   
  28. void onDestroy(ANativeActivity *activity) {  
  29.   
  30. }  
  31.   
  32. void onWindowFocusChanged(ANativeActivity *activity, int hasFocus) {  
  33.   
  34. }  
  35.   
  36. void onNativeWindowCreated(ANativeActivity *activity, ANativeWindow *window) {  
  37.   
  38. }  
  39.   
  40. void onNativeWindowDestroyed(ANativeActivity *activity, ANativeWindow *window) {  
  41.   
  42. }  
  43.   
  44. void onInputQueueCreated(ANativeActivity *activity, AInputQueue *queue) {  
  45.       
  46. }  
  47.   
  48. void onInputQueueDestroyed(ANativeActivity *activity, AInputQueue *queue) {  
  49.   
  50. }  
  51.   
  52. void onConfigurationChanged(ANativeActivity *activity) {  
  53.   
  54. }  
  55.   
  56. void onLowMemory(ANativeActivity *activity) {  
  57.   
  58. }  
  59.   
  60. void ANativeActivity_onCreate(ANativeActivity *activity, void *savedState, size_t savedStateSize) {  
  61.   
  62. }  

接着,我们要对声明周期函数绑定回调


实现bindLifeCycle(ANativeActivity *activity);方法,并在里边设置回调

[cpp] view plain copy
 print?
  1. void bindLifeCycle(ANativeActivity *activity) {  
  2.     activity->callbacks->onStart = onStart;  
  3.     activity->callbacks->onResume = onResume;  
  4.     activity->callbacks->onSaveInstanceState = onSaveInstanceState;  
  5.     activity->callbacks->onPause = onPause;  
  6.     activity->callbacks->onStop = onStop;  
  7.     activity->callbacks->onDestroy = onDestroy;  
  8.     activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;  
  9.     activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;  
  10.     activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;  
  11.     activity->callbacks->onInputQueueCreated = onInputQueueCreated;  
  12.     activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;  
  13.     activity->callbacks->onConfigurationChanged = onConfigurationChanged;  
  14.     activity->callbacks->onLowMemory = onLowMemory;  
  15. }  

回调设置完了,但是需要在ANativeActivity_onCreate()方法中调用,这个方法则相当于Java中的onCreate()方法,就是程序的入口点

void ANativeActivity_onCreate(ANativeActivity *activity, void *savedState, size_t savedStateSize) {    bindLifeCycle(activity);}
然后编译成.so我们需要在CMakeLists.txt中添加我们的源码文件

为了方便查看,我就将这里边的注释全部去掉了

[cpp] view plain copy
 print?
  1. cmake_minimum_required(VERSION 3.4.1)  
  2.   
  3. add_library( native-main SHARED  
  4.              src/main/cpp/NativeMain.cpp  
  5.              )  
  6.   
  7. find_library( log-lib log )  
  8.   
  9. target_link_libraries( native-main ${log-lib} )  

添加完了之后,就可以编译运行了

如果你需要在APP里边进行事件的处理,那就需要自己写looper

[cpp] view plain copy
 print?
  1. static bool isLoop = false;  
  2. static pthread_t loopID;  

[cpp] view plain copy
 print?
  1. void *looper(void *args) {  
  2.     ANativeActivity *activity = (ANativeActivity *) args;  
  3.     AInputQueue *queue = (AInputQueue *) activity->instance;  
  4.     AInputEvent *event = NULL;  
  5.     while (isLoop) {  
  6.         if (!AInputQueue_hasEvents(queue)) {  
  7.             continue;  
  8.         }  
  9.         AInputQueue_getEvent(queue, &event);  
  10.         float mx = AMotionEvent_getX(event, 0);  
  11.         float my = AMotionEvent_getY(event, 0);  
  12.         switch (AInputEvent_getType(event)) {  
  13.             case AINPUT_EVENT_TYPE_MOTION: {  
  14.                 switch (AMotionEvent_getAction(event)) {  
  15.                     case AMOTION_EVENT_ACTION_DOWN: {  
  16.             LOGE("Touch Scerrn Down");  
  17.                         break;  
  18.                     }  
  19.                     case AMOTION_EVENT_ACTION_UP: {  
  20.             LOGE("Touch Scerrn UP");  
  21.  break; } defaultbreak; } break; } case AINPUT_EVENT_TYPE_KEY: { switch (AKeyEvent_getAction(event)) { case AKEY_EVENT_ACTION_DOWN: { LOGE("key down"); switch (AKeyEvent_getKeyCode(event)) { case AKEYCODE_BACK: {  
  22.                 LOGE("BACK down");  
  23.                                 ANativeActivity_finish(activity);  
  24.                                 break;  
  25.                             }  
  26.                             default:  
  27.                                 break;  
  28.                         }  
  29.                         break;  
  30.                     }  
  31.                     case AKEY_EVENT_ACTION_UP: {  
  32.                         LOGE("key up");  
  33.                         break;  
  34.                     }  
  35.                     default:  
  36.                         break;  
  37.                 }  
  38.             }  
  39.             default:  
  40.                 break;  
  41.         }  
  42.         AInputQueue_finishEvent(queue, event, 1);  
  43.     }  
  44.     return args;  
  45. }  

消息处理写好了,还需要在onInputQueueCreated()方法中进行启动,在onInputQueueDestroyed();方法中停止,消息处理其实是启动一条线程来进行消息处理,所以别忘了在顶部导入pthread.h

void onInputQueueCreated(ANativeActivity *activity, AInputQueue *queue) {    isLoop = true;    activity->instance = (void *) queue;    pthread_create(&loopID, NULL, looper, activity);}void onInputQueueDestroyed(ANativeActivity *activity, AInputQueue *queue) {    isLoop = false;}

至此,这个项目就差不多了,剩下的界面啥的,用EGL & GLES来画吧,这里我就不多写了,因为OpenGL ES & EGL 我也一窍不通,没办法写了

最后,贴出整个NativeMain.cpp的代码

[cpp] view plain copy
 print?
  1. #include <android/log.h>  
  2. #include <pthread.h>  
  3.   
  4. #include "NativeMain.h"  
  5.   
  6. #define LOG_TAG "MAIN_CPP"  
  7. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR ,LOG_TAG ,__VA_ARGS__)  
  8.   
  9. static bool isLoop = false;  
  10. static pthread_t loopID;  
  11.   
  12. void onStart(ANativeActivity *activity) {  
  13.     LOGE("Application is start");  
  14. }  
  15.   
  16. void onResume(ANativeActivity *activity) {  
  17.   
  18. }  
  19.   
  20. void *onSaveInstanceState(ANativeActivity *activity, size_t *outSize) {  
  21.   
  22. }  
  23.   
  24. void onPause(ANativeActivity *activity) {  
  25.   
  26. }  
  27.   
  28. void onStop(ANativeActivity *activity) {  
  29.   
  30. }  
  31.   
  32. void onDestroy(ANativeActivity *activity) {  
  33.   
  34. }  
  35.   
  36. void onWindowFocusChanged(ANativeActivity *activity, int hasFocus) {  
  37.   
  38. }  
  39.   
  40. void onNativeWindowCreated(ANativeActivity *activity, ANativeWindow *window) {  
  41.       
  42. }  
  43.   
  44. void onNativeWindowDestroyed(ANativeActivity *activity, ANativeWindow *window) {  
  45.   
  46. }  
  47.   
  48. void onInputQueueCreated(ANativeActivity *activity, AInputQueue *queue) {  
  49.     isLoop = true;  
  50.     activity->instance = (void *) queue;  
  51.     pthread_create(&loopID, NULL, looper, activity);  
  52. }  
  53.   
  54. void onInputQueueDestroyed(ANativeActivity *activity, AInputQueue *queue) {  
  55.     isLoop = false;  
  56. }  
  57.   
  58. void onConfigurationChanged(ANativeActivity *activity) {  
  59.   
  60. }  
  61.   
  62. void onLowMemory(ANativeActivity *activity) {  
  63.   
  64. }  
  65.   
  66. void bindLifeCycle(ANativeActivity *activity) {  
  67.     activity->callbacks->onStart = onStart;  
  68.     activity->callbacks->onResume = onResume;  
  69.     activity->callbacks->onSaveInstanceState = onSaveInstanceState;  
  70.     activity->callbacks->onPause = onPause;  
  71.     activity->callbacks->onStop = onStop;  
  72.     activity->callbacks->onDestroy = onDestroy;  
  73.     activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;  
  74.     activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;  
  75.     activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;  
  76.     activity->callbacks->onInputQueueCreated = onInputQueueCreated;  
  77.     activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;  
  78.     activity->callbacks->onConfigurationChanged = onConfigurationChanged;  
  79.     activity->callbacks->onLowMemory = onLowMemory;  
  80. }  
  81.   
  82. void *looper(void *args) {  
  83.     ANativeActivity *activity = (ANativeActivity *) args;  
  84.     AInputQueue *queue = (AInputQueue *) activity->instance;  
  85.     AInputEvent *event = NULL;  
  86.     while (isLoop) {  
  87.         if (!AInputQueue_hasEvents(queue)) {  
  88.             continue;  
  89.         }  
  90.         AInputQueue_getEvent(queue, &event);  
  91.         float mx = AMotionEvent_getX(event, 0);  
  92.         float my = AMotionEvent_getY(event, 0);  
  93.         switch (AInputEvent_getType(event)) {  
  94.             case AINPUT_EVENT_TYPE_MOTION: {  
  95.                 switch (AMotionEvent_getAction(event)) {  
  96.                     case AMOTION_EVENT_ACTION_DOWN: {  
  97.             LOGE("Touch Screen Down");  
  98.                         break;  
  99.                     }  
  100.                     case AMOTION_EVENT_ACTION_UP: {  
  101.             LOGE("Touch Screen UP");  
  102.                         break;  
  103.                     }  
  104.                     default:  
  105.                         break;  
  106.                 }  
  107.                 break;  
  108.             }  
  109.             case AINPUT_EVENT_TYPE_KEY: {  
  110.                 switch (AKeyEvent_getAction(event)) {  
  111.                     case AKEY_EVENT_ACTION_DOWN: {  
  112.             LOGE("key down");  
  113.                         switch (AKeyEvent_getKeyCode(event)) {  
  114.                             case AKEYCODE_BACK: {  
  115.                 LOGE("BACK down");  
  116.                                 ANativeActivity_finish(activity);  
  117.                                 break;  
  118.                             }  
  119.                             default:  
  120.                                 break;  
  121.                         }  
  122.                         break;  
  123.                     }  
  124.                     case AKEY_EVENT_ACTION_UP: {  
  125.             LOGE("key up");  
  126.                         break;  
  127.                     }  
  128.                     default:  
  129.                         break;  
  130.                 }  
  131.             }  
  132.             default:  
  133.                 break;  
  134.         }  
  135.         AInputQueue_finishEvent(queue, event, 1);  
  136.     }  
  137.     return args;  
  138. }  
  139.   
  140. void ANativeActivity_onCreate(ANativeActivity *activity, void *savedState, size_t savedStateSize) {  
  141.     LOGE("init LifeCycle");  
  142.     bindLifeCycle(activity);  
  143. }  
阅读全文
0 0
原创粉丝点击