自古以来,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"
android.app.NativeActivity
<meta-data
android:name="android.app.lib_name"
android:value="native-main"
/>
然后<intent-filter>里边的东西是默认启动Activity的配置
到这里,整个项目就弄的差不多了,然后开始我们的代码编写工作
至于那个native-lib.cpp没啥用,干脆删了吧
首先,在cpp目录中添加一个.h文件,名称随意吧,比如我的叫做NativeMain.h
然后在里边导入native_activity.h并添加NativeActivity的一些生命周期函数声明
#ifndef _ANDROID_NATIVE_MAIN_H_
#define _ANDROID_NATIVE_MAIN_H_
#include <android/native_activity.h>
/*
* 定义绑定声明周期函数
*/
void bindLifeCycle(ANativeActivity *activity);
/*
* 定义NativeActivity的入口函数
*/
void ANativeActivity_onCreate(ANativeActivity *activity, void *savedState, size_t savedStateSize);
/*
* 处理事件队列的函数
*/
void *looper(void *args);
/**
* 定义onStart方法,对应Java中的onStart
*/
void onStart(ANativeActivity *activity);
/**
* 定义onResume方法,对应Java中的onResume
*/
void onResume(ANativeActivity *activity);
/**
* 定义储存静态对象状态方法
*/
void *onSaveInstanceState(ANativeActivity *activity, size_t *outSize);
/**
* 定义onPause方法,对应Java中的onPause
*/
void onPause(ANativeActivity *activity);
/**
* 定义onStop方法,对应Java中的onStop
*/
void onStop(ANativeActivity *activity);
/**
* 定义onDestory方法,对应Java中的onDestroy
*/
void onDestroy(ANativeActivity *activity);
/**
* 定义窗口焦点改变方法
*/
void onWindowFocusChanged(ANativeActivity *activity, int hasFocus);
/**
* 定义Native窗口创建方法
*/
void onNativeWindowCreated(ANativeActivity *activity, ANativeWindow *window);
/**
* 定义Native窗口销毁方法
*/
void onNativeWindowDestroyed(ANativeActivity *activity, ANativeWindow *window);
/**
* 定义输入队列创建方法
*/
void onInputQueueCreated(ANativeActivity *activity, AInputQueue *queue);
/**
* 定义输入队列销毁方法
*/
void onInputQueueDestroyed(ANativeActivity *activity, AInputQueue *queue);
/**
* 定义配置改变方法
*/
void onConfigurationChanged(ANativeActivity *activity);
/**
* 定义低内存方法
*/
void onLowMemory(ANativeActivity *activity);
#endif // !_ANDROID_NATIVE_MAIN_H_
这些方法在native_activity.h中有引用,所以我们要自行设置方法回调,但是在这之前,我们需要先进行方法的实现
我们在创建一个cpp文件,用来编写方法的实现名称随意,比如我的叫做NativeMain.cpp
在这里边对刚才在NativeMain.h里边声明的方法进行实现和绑定回调
#include <android/log.h>
#include "NativeMain.h"
#define LOG_TAG "NATIVE_MAIN_CPP"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR ,LOG_TAG ,__VA_ARGS__)
void onStart(ANativeActivity *activity) {
}
void onResume(ANativeActivity *activity) {
}
void *onSaveInstanceState(ANativeActivity *activity, size_t *outSize) {
}
void onPause(ANativeActivity *activity) {
}
void onStop(ANativeActivity *activity) {
}
void onDestroy(ANativeActivity *activity) {
}
void onWindowFocusChanged(ANativeActivity *activity, int hasFocus) {
}
void onNativeWindowCreated(ANativeActivity *activity, ANativeWindow *window) {
}
void onNativeWindowDestroyed(ANativeActivity *activity, ANativeWindow *window) {
}
void onInputQueueCreated(ANativeActivity *activity, AInputQueue *queue) {
}
void onInputQueueDestroyed(ANativeActivity *activity, AInputQueue *queue) {
}
void onConfigurationChanged(ANativeActivity *activity) {
}
void onLowMemory(ANativeActivity *activity) {
}
void ANativeActivity_onCreate(ANativeActivity *activity, void *savedState, size_t savedStateSize) {
}
接着,我们要对声明周期函数绑定回调
实现bindLifeCycle(ANativeActivity *activity);方法,并在里边设置回调
void bindLifeCycle(ANativeActivity *activity) {
activity->callbacks->onStart = onStart;
activity->callbacks->onResume = onResume;
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
activity->callbacks->onPause = onPause;
activity->callbacks->onStop = onStop;
activity->callbacks->onDestroy = onDestroy;
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
activity->callbacks->onLowMemory = onLowMemory;
}
回调设置完了,但是需要在ANativeActivity_onCreate()方法中调用,这个方法则相当于Java中的onCreate()方法,就是程序的入口点
void ANativeActivity_onCreate(ANativeActivity *activity, void *savedState, size_t savedStateSize) {
bindLifeCycle(activity);
}
然后编译成.so我们需要在CMakeLists.txt中添加我们的源码文件
为了方便查看,我就将这里边的注释全部去掉了
cmake_minimum_required(VERSION 3.4.1)
add_library( native-main SHARED
src/main/cpp/NativeMain.cpp
)
find_library( log-lib log )
target_link_libraries( native-main ${log-lib} )
添加完了之后,就可以编译运行了
如果你需要在APP里边进行事件的处理,那就需要自己写looper
static bool isLoop = false;
static pthread_t loopID;
void *looper(void *args) {
ANativeActivity *activity = (ANativeActivity *) args;
AInputQueue *queue = (AInputQueue *) activity->instance;
AInputEvent *event = NULL;
while (isLoop) {
if (!AInputQueue_hasEvents(queue)) {
continue;
}
AInputQueue_getEvent(queue, &event);
float mx = AMotionEvent_getX(event, 0);
float my = AMotionEvent_getY(event, 0);
switch (AInputEvent_getType(event)) {
case AINPUT_EVENT_TYPE_MOTION: {
switch (AMotionEvent_getAction(event)) {
case AMOTION_EVENT_ACTION_DOWN: {
LOGE("Touch Scerrn Down");
break;
}
case AMOTION_EVENT_ACTION_UP: {
LOGE("Touch Scerrn UP");
break; } default: break; } 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: {
LOGE("BACK down");
ANativeActivity_finish(activity);
break;
}
default:
break;
}
break;
}
case AKEY_EVENT_ACTION_UP: {
LOGE("key up");
break;
}
default:
break;
}
}
default:
break;
}
AInputQueue_finishEvent(queue, event, 1);
}
return args;
}
消息处理写好了,还需要在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的代码
#include <android/log.h>
#include <pthread.h>
#include "NativeMain.h"
#define LOG_TAG "MAIN_CPP"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR ,LOG_TAG ,__VA_ARGS__)
static bool isLoop = false;
static pthread_t loopID;
void onStart(ANativeActivity *activity) {
LOGE("Application is start");
}
void onResume(ANativeActivity *activity) {
}
void *onSaveInstanceState(ANativeActivity *activity, size_t *outSize) {
}
void onPause(ANativeActivity *activity) {
}
void onStop(ANativeActivity *activity) {
}
void onDestroy(ANativeActivity *activity) {
}
void onWindowFocusChanged(ANativeActivity *activity, int hasFocus) {
}
void onNativeWindowCreated(ANativeActivity *activity, ANativeWindow *window) {
}
void onNativeWindowDestroyed(ANativeActivity *activity, ANativeWindow *window) {
}
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;
}
void onConfigurationChanged(ANativeActivity *activity) {
}
void onLowMemory(ANativeActivity *activity) {
}
void bindLifeCycle(ANativeActivity *activity) {
activity->callbacks->onStart = onStart;
activity->callbacks->onResume = onResume;
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
activity->callbacks->onPause = onPause;
activity->callbacks->onStop = onStop;
activity->callbacks->onDestroy = onDestroy;
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
activity->callbacks->onLowMemory = onLowMemory;
}
void *looper(void *args) {
ANativeActivity *activity = (ANativeActivity *) args;
AInputQueue *queue = (AInputQueue *) activity->instance;
AInputEvent *event = NULL;
while (isLoop) {
if (!AInputQueue_hasEvents(queue)) {
continue;
}
AInputQueue_getEvent(queue, &event);
float mx = AMotionEvent_getX(event, 0);
float my = AMotionEvent_getY(event, 0);
switch (AInputEvent_getType(event)) {
case AINPUT_EVENT_TYPE_MOTION: {
switch (AMotionEvent_getAction(event)) {
case AMOTION_EVENT_ACTION_DOWN: {
LOGE("Touch Screen Down");
break;
}
case AMOTION_EVENT_ACTION_UP: {
LOGE("Touch Screen UP");
break;
}
default:
break;
}
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: {
LOGE("BACK down");
ANativeActivity_finish(activity);
break;
}
default:
break;
}
break;
}
case AKEY_EVENT_ACTION_UP: {
LOGE("key up");
break;
}
default:
break;
}
}
default:
break;
}
AInputQueue_finishEvent(queue, event, 1);
}
return args;
}
void ANativeActivity_onCreate(ANativeActivity *activity, void *savedState, size_t savedStateSize) {
LOGE("init LifeCycle");
bindLifeCycle(activity);
}
然后..............研究 OpenGL ES 去了.