您的位置:首页 > 编程语言 > C语言/C++

最新首发Eclipse+CDT+android-ndk写纯c++安卓应用(附openGL Es)

2015-02-04 14:05 591 查看
首先下载eclipse和cdt,我的版本号依次是:Version: Indigo Service Release 2和Version: 1.0.0.201202111925,再下载windows的ndk,我使用的是android-ndk-r9d

什么cygwin这等东西,太恶心了,下载慢,大的要命!复杂,今天给一个最爽的编译教程。

前面的cdt插件怎么这里pass,网上教程很多的。直接配置。。。

启动eclipse,然后点Windows-Prefrences-C/C++-Build-Envionment,添加以下路径



然后创建一个android工程,把代码全部删除,资源全部删除,AndroidManifest.xml内容如下

[html] view
plaincopy

<?xml version="1.0" encoding="utf-8"?>  

<manifest xmlns:android="http://schemas.android.com/apk/res/android"  

    xmlns:tools="http://schemas.android.com/tools"  

    package="com.example.native_activity"  

    android:versionCode="1"  

    android:versionName="1.0" >  

  

    <uses-sdk  

        android:minSdkVersion="9"  

        tools:ignore="UsesMinSdkAttributes" />  

  

    <application  

        android:hasCode="false"  

        android:label="纯CPP应用"  

        tools:ignore="AllowBackup,MissingApplicationIcon" >  

        <activity  

            android:name="android.app.NativeActivity"  

            android:configChanges="orientation|keyboardHidden" >  

  

            <!-- Tell NativeActivity the name of or .so -->  

            <meta-data  

                android:name="android.app.lib_name"  

                android:value="native-activity" />  

  

            <intent-filter>  

                <action android:name="android.intent.action.MAIN" />  

  

                <category android:name="android.intent.category.LAUNCHER" />  

            </intent-filter>  

        </activity>  

    </application>  

  

</manifest>   

然后创建jni目录,里面放三个文件,依次是Android.mk

[plain] view
plaincopy

LOCAL_PATH := $(call my-dir)  

  

include $(CLEAR_VARS)  

  

LOCAL_MODULE    := native-activity  

LOCAL_SRC_FILES := main.cpp  

LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM  

LOCAL_STATIC_LIBRARIES := android_native_app_glue  

  

include $(BUILD_SHARED_LIBRARY)  

  

$(call import-module,android/native_app_glue)  

Application.mk

[plain] view
plaincopy

APP_PLATFORM := android-14  

main.cpp

[cpp] view
plaincopy

#include <jni.h>  

#include <errno.h>  

#include <EGL/egl.h>  

#include <GLES/gl.h>  

#include <string.h>  

#include <android/sensor.h>  

#include <android/log.h>  

#include <android_native_app_glue.h>  

  

#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__))  

  

/** 

 * Our saved state data. 

 */  

struct saved_state {  

    float angle;  

    int32_t x;  

    int32_t y;  

};  

  

/** 

 * Shared state for our app. 

 */  

struct engine {  

    struct android_app* app;  

  

    ASensorManager* sensorManager;  

    const ASensor* accelerometerSensor;  

    ASensorEventQueue* sensorEventQueue;  

  

    int animating;  

    EGLDisplay display;  

    EGLSurface surface;  

    EGLContext context;  

    int32_t width;  

    int32_t height;  

    struct saved_state state;  

};  

  

/** 

 * Initialize an EGL context for the current display. 

 */  

static int engine_init_display(struct engine* engine) {  

    // initialize OpenGL ES and EGL  

  

    /* 

     * Here specify the attributes of the desired configuration. 

     * Below, we select an EGLConfig with at least 8 bits per color 

     * component compatible with on-screen windows 

     */  

    const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE,  

            8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE };  

    EGLint w, h, dummy, format;  

    EGLint numConfigs;  

    EGLConfig config;  

    EGLSurface surface;  

    EGLContext context;  

  

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);  

  

    eglInitialize(display, 0, 0);  

  

    /* Here, the application chooses the configuration it desires. In this 

     * sample, we have a very simplified selection process, where we pick 

     * the first EGLConfig that matches our criteria */  

    eglChooseConfig(display, attribs, &config, 1, &numConfigs);  

  

    /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is 

     * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). 

     * As soon as we picked a EGLConfig, we can safely reconfigure the 

     * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */  

    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);  

  

    ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);  

  

    surface = eglCreateWindowSurface(display, config, engine->app->window,  

            NULL);  

    context = eglCreateContext(display, config, NULL, NULL);  

  

    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {  

        LOGW("Unable to eglMakeCurrent");  

        return -1;  

    }  

  

    eglQuerySurface(display, surface, EGL_WIDTH, &w);  

    eglQuerySurface(display, surface, EGL_HEIGHT, &h);  

  

    engine->display = display;  

    engine->context = context;  

    engine->surface = surface;  

    engine->width = w;  

    engine->height = h;  

    engine->state.angle = 0;  

  

    // Initialize GL state.  

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);  

    glEnable(GL_CULL_FACE);  

    glShadeModel(GL_SMOOTH);  

    glDisable(GL_DEPTH_TEST);  

  

    return 0;  

}  

  

/** 

 * Just the current frame in the display. 

 */  

static void engine_draw_frame(struct engine* engine) {  

    if (engine->display == NULL) {  

        // No display.  

        return;  

    }  

  

    // Just fill the screen with a color.  

    glClearColor(((float) engine->state.x) / engine->width, engine->state.angle,  

            ((float) engine->state.y) / engine->height, 1);  

    glClear(GL_COLOR_BUFFER_BIT);  

  

    eglSwapBuffers(engine->display, engine->surface);  

}  

  

/** 

 * Tear down the EGL context currently associated with the display. 

 */  

static void engine_term_display(struct engine* engine) {  

    if (engine->display != EGL_NO_DISPLAY) {  

        eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE,  

                EGL_NO_CONTEXT);  

        if (engine->context != EGL_NO_CONTEXT) {  

            eglDestroyContext(engine->display, engine->context);  

        }  

        if (engine->surface != EGL_NO_SURFACE) {  

            eglDestroySurface(engine->display, engine->surface);  

        }  

        eglTerminate(engine->display);  

    }  

    engine->animating = 0;  

    engine->display = EGL_NO_DISPLAY;  

    engine->context = EGL_NO_CONTEXT;  

    engine->surface = EGL_NO_SURFACE;  

}  

  

/** 

 * Process the next input event. 

 */  

static int32_t engine_handle_input(struct android_app* app,  

        AInputEvent* event) {  

    struct engine* engine = (struct engine*) app->userData;  

    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {  

        engine->animating = 1;  

        engine->state.x = AMotionEvent_getX(event, 0);  

        engine->state.y = AMotionEvent_getY(event, 0);  

        return 1;  

    }  

    return 0;  

}  

  

/** 

 * Process the next main command. 

 */  

static void engine_handle_cmd(struct android_app* app, int32_t cmd) {  

    struct engine* engine = (struct engine*) app->userData;  

    switch (cmd) {  

    case APP_CMD_SAVE_STATE:  

        // The system has asked us to save our current state.  Do so.  

        engine->app->savedState = malloc((size_t)sizeof(struct saved_state));  

        *((struct saved_state*) engine->app->savedState) = engine->state;  

        engine->app->savedStateSize = sizeof(struct saved_state);  

        break;  

    case APP_CMD_INIT_WINDOW:  

        // The window is being shown, get it ready.  

        if (engine->app->window != NULL) {  

            engine_init_display(engine);  

            engine_draw_frame(engine);  

        }  

        break;  

    case APP_CMD_TERM_WINDOW:  

        // The window is being hidden or closed, clean it up.  

        engine_term_display(engine);  

        break;  

    case APP_CMD_GAINED_FOCUS:  

        // When our app gains focus, we start monitoring the accelerometer.  

        if (engine->accelerometerSensor != NULL) {  

            ASensorEventQueue_enableSensor(engine->sensorEventQueue,  

                    engine->accelerometerSensor);  

            // We'd like to get 60 events per second (in us).  

            ASensorEventQueue_setEventRate(engine->sensorEventQueue,  

                    engine->accelerometerSensor, (1000L / 60) * 1000);  

        }  

        break;  

    case APP_CMD_LOST_FOCUS:  

        // When our app loses focus, we stop monitoring the accelerometer.  

        // This is to avoid consuming battery while not being used.  

        if (engine->accelerometerSensor != NULL) {  

            ASensorEventQueue_disableSensor(engine->sensorEventQueue,  

                    engine->accelerometerSensor);  

        }  

        // Also stop animating.  

        engine->animating = 0;  

        engine_draw_frame(engine);  

        break;  

    }  

}  

  

/** 

 * This is the main entry point of a native application that is using 

 * android_native_app_glue.  It runs in its own thread, with its own 

 * event loop for receiving input events and doing other things. 

 */  

void android_main(struct android_app* state) {  

    struct engine engine = {0};  

    // Make sure glue isn't stripped.  

    app_dummy();  

    state->userData = &engine;  

    state->onAppCmd = engine_handle_cmd;  

    state->onInputEvent = engine_handle_input;  

    engine.app = state;  

  

    // Prepare to monitor accelerometer  

    engine.sensorManager = ASensorManager_getInstance();  

    engine.accelerometerSensor = ASensorManager_getDefaultSensor(  

            engine.sensorManager, ASENSOR_TYPE_ACCELEROMETER);  

    engine.sensorEventQueue = ASensorManager_createEventQueue(  

            engine.sensorManager, state->looper, LOOPER_ID_USER, NULL, NULL);  

  

    if (state->savedState != NULL) {  

        // We are starting with a previous saved state; restore from it.  

        engine.state = *(struct saved_state*) state->savedState;  

    }  

  

    // loop waiting for stuff to do.  

  

    while (true) {  

        // Read all pending events.  

        int ident;  

        int events;  

        struct android_poll_source* source;  

  

        // If not animating, we will block forever waiting for events.  

        // If animating, we loop until all events are read, then continue  

        // to draw the next frame of animation.  

        while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL,  

                &events, (void**) &source)) >= 0) {  

  

            // Process this event.  

            if (source != NULL) {  

                source->process(state, source);  

            }  

  

            // If a sensor has data, process it now.  

            if (ident == LOOPER_ID_USER) {  

                if (engine.accelerometerSensor != NULL) {  

                    ASensorEvent event;  

                    while (ASensorEventQueue_getEvents(engine.sensorEventQueue,  

                            &event, 1) > 0) {  

                        LOGI("accelerometer: x=%f y=%f z=%f", event.acceleration.x, event.acceleration.y, event.acceleration.z);  

                    }  

                }  

            }  

  

            // Check if we are exiting.  

            if (state->destroyRequested != 0) {  

                engine_term_display(&engine);  

                return;  

            }  

        }  

  

        if (engine.animating) {  

            // Done with events; draw next animation frame.  

            engine.state.angle += .01f;  

            if (engine.state.angle > 1) {  

                engine.state.angle = 0;  

            }  

            engine_draw_frame(&engine);  

        }  

    }  

}  

创建完成收工,然后创建另外一个工程。路径必须是刚才创建工程的jni目录,名字随便,重点看图



好了点完成,然后打开main.cpp发现N多错误,直接下设置一下环境变量,右键工程,属性(是刚创建的C++工程)



接下来看图,把所有的库加进去。



最后加一个Symbol,其实就是定义一个宏,告诉编译器我现在的平台是Android,add



最后点OK,所有的函数都能正常识别,提示功能也可以用了。开发效率高多了。编译直接点锤子就行了。



然后在原来的工程运行安装就行了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: