[原]零基礎學習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 := armeabi
APP_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 screen
const 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 := main

SDL_PATH := ../SDL

LOCAL_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.c

LOCAL_SHARED_LIBRARIES := SDL2

LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog

include $(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: */

 

最后,上一張運行的截圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM