首页 > 代码库 > [原]零基础学习SDL开发之在Android使用SDL2.0显示BMP图

[原]零基础学习SDL开发之在Android使用SDL2.0显示BMP图

关于如何移植SDL2.0到安卓上面来参考我的上一篇文章:[原]零基础学习SDL开发之移植SDL2.0到Android 

在一篇文章我们主要使用SDL2.0来加载一张BMP图来渲染显示。

博主的开发环境:Ubuntu 14.04 64位,Eclipse + CDT + ADT+NDK

博主曾经自己使用NDK编译出了libSDL2.so,然后使用共享库的方式来调用libSDL2中的函数,结果发现SDL\src\core\android\SDL_android.c 这个jni函数写的实在是不够自己另外做移植用,与org.libsdl.app.SDLActivity耦合太紧密了。如果想使用共享库的方式去调用SDL中的函数,最好自己去写JNI注册与调用函数实现。

一、导入SDL源码

还是把SDL源码中的android-project工程导入到Eclipse中来,进入jni文件夹,新建一个SDL文件,将SDL2-2.0.3\src 、SDL2-2.0.3\include、SDL2-2.0.3\Android.mk文件拷贝到android-project\jni\SDL\中。

在android-project中新建Android.mk,内容如下:

include $(call all-subdir-makefiles)

在android-project中新建Application.mk,内容如下:

APP_ABI := armeabiAPP_PLATFORM := android-9

 

二、新建功能模块

在jni下新建一文件夹src,新建SDL_logger.h,用来使用android中的log来打印日志,内容如下:

/* * log.h * *  Created on: Aug 8, 2014 *      Author: clarck */#ifndef LOG_H_#define LOG_H_#include <android/log.h>#define APPNAME "SDL_Lesson"#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, __VA_ARGS__)#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , APPNAME, __VA_ARGS__)#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , APPNAME, __VA_ARGS__)#define LOGW(...) __android_log_print(ANDROID_LOG_WARN , APPNAME, __VA_ARGS__)#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , APPNAME, __VA_ARGS__)#endif /* LOG_H_ */

新建SDL_lesson.c,用来使用SDL window的创建,加载bmp,渲染图片的功能,具体内容:

/* * SDL_lesson.c * *  Created on: Aug 8, 2014 *      Author: clarck */#ifdef __ANDROID__#include <jni.h>#include "SDL.h"#include "SDL_log.h"#include "SDL_main.h"//The attributes of the screenconst int SCREEN_WIDTH = 640;const int SCREEN_HEIGHT = 480;const int SCREEN_BPP = 32;struct SDL_Window *window = NULL;struct SDL_Renderer *render = NULL;struct SDL_Surface *bmp = NULL;struct SDL_Texture *texture = NULL;int main(int argc, char *argv[]) {    char *filepath = argv[1];    LOGI("natvie_SDL %s", filepath);    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) == -1) {        LOGE("SDL_Init failed %s", SDL_GetError());    }    LOGI("SDL_CreateWindow");    window = SDL_CreateWindow("Hello World!", 100, 100, 640, 480,            SDL_WINDOW_SHOWN);    if (window == NULL) {        LOGE("SDL_CreateWindow failed  %s", SDL_GetError());    }    LOGI("SDL_CreateRenderer");    render = SDL_CreateRenderer(window, -1,            SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);    if (render == NULL) {        LOGE("SDL_CreateRenderer failed  %s", SDL_GetError());    }    bmp = SDL_LoadBMP(filepath);    if (bmp == NULL) {        LOGE("SDL_LoadBMP failed: %s", SDL_GetError());    }    texture = SDL_CreateTextureFromSurface(render, bmp);    SDL_FreeSurface(bmp);    SDL_RenderClear(render);    SDL_RenderCopy(render, texture, NULL, NULL);    SDL_RenderPresent(render);    SDL_Delay(2000);    SDL_DestroyTexture(texture);    SDL_DestroyRenderer(render);    SDL_DestroyWindow(window);    //Quit SDL    SDL_Quit();    return 0;}#endif /* __ANDROID__ */

在src下编写Android.mk,用来编译SDL_lesson.c,内容如下:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := mainSDL_PATH := ../SDLLOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include# Add your application source files here...LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c     SDL_Lesson.cLOCAL_SHARED_LIBRARIES := SDL2LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -lloginclude $(BUILD_SHARED_LIBRARY)

三、修改SDLActivity、SDL\src\main\SDL_android_main.c以便接受传入的参数:

修改SDLActivity中的 SDLMain类,修改内容如下:

/**    Simple nativeInit() runnable*/class SDLMain implements Runnable {    @Override    public void run() {        // Runs SDL_main()        String sdcard = Environment.getExternalStorageDirectory().getAbsolutePath();        SDLActivity.nativeInit(sdcard + File.separator + "hello.bmp");        //Log.v("SDL", "SDL thread terminated");    }}

 

修改SDL\src\main\SDL_android_main.c,修改如下:

/*    SDL_android_main.c, placed in the public domain by Sam Lantinga  3/13/14*/#include "../../SDL_internal.h"#ifdef __ANDROID__/* Include the SDL main definition header */#include "SDL_main.h"/*******************************************************************************                 Functions called by JNI*******************************************************************************/#include <jni.h>/* Called before SDL_main() to initialize JNI bindings in SDL library */extern void SDL_Android_Init(JNIEnv* env, jclass cls);char* jstringTostr(JNIEnv* env, jstring jstr) {    char* pStr = NULL;    jclass jstrObj = (*env)->FindClass(env, "java/lang/String");    jstring encode = (*env)->NewStringUTF(env, "utf-8");    jmethodID methodId = (*env)->GetMethodID(env, jstrObj, "getBytes",            "(Ljava/lang/String;)[B");    jbyteArray byteArray = (jbyteArray) (*env)->CallObjectMethod(env, jstr,            methodId, encode);    jsize strLen = (*env)->GetArrayLength(env, byteArray);    jbyte *jBuf = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);    if (jBuf > 0) {        pStr = (char*) malloc(strLen + 1);        if (!pStr) {            return NULL ;        }        memcpy(pStr, jBuf, strLen);        pStr[strLen] = 0;    }    (*env)->ReleaseByteArrayElements(env, byteArray, jBuf, 0);    return pStr;}/* Start up the SDL app */void Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj){    /* This interface could expand with ABI negotiation, calbacks, etc. */    SDL_Android_Init(env, cls);    SDL_SetMainReady();    char *filePath = jstringTostr(env, obj);    /* Run the application code! */    int status;    char *argv[2];    argv[0] = SDL_strdup("SDL_app");    argv[1] = filePath;    status = SDL_main(1, argv);    /* Do not issue an exit or the whole application will terminate instead of just the SDL thread */    /* exit(status); */}#endif /* __ANDROID__ *//* vi: set ts=4 sw=4 expandtab: */

 

最后,上一张运行的截图: