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

时间:2022-12-26 13:32:28

关于如何移植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: */

 

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

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