• [原]零基础学习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中的函数,结果发现SDLsrccoreandroidSDL_android.c 这个jni函数写的实在是不够自己另外做移植用,与org.libsdl.app.SDLActivity耦合太紧密了。如果想使用共享库的方式去调用SDL中的函数,最好自己去写JNI注册与调用函数实现。

    一、导入SDL源码

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

    在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、SDLsrcmainSDL_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");
        }
    }

    修改SDLsrcmainSDL_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: */

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

  • 相关阅读:
    Linux驱动之内核自带的S3C2440的LCD驱动分析
    【双11狂欢的背后】微服务注册中心如何承载大型系统的千万级访问? Eureka 注册中心
    java GC算法 垃圾收集器
    Java嵌入式数据库H2学习总结(三)——在Web应用中嵌入H2数据库
    Java嵌入式数据库H2学习总结(二)——在Web应用程序中使用H2数据库
    Java嵌入式数据库H2学习总结(一)——H2数据库入门
    Java Master-Worker模式实现
    RSA公钥格式PKCS#1,PKCS#8互转(微信获取RSA加密公钥)
    自定义注解完成数据库切库(读写分离)
    Linux下CPU飘高定位
  • 原文地址:https://www.cnblogs.com/tanlon/p/3923405.html
Copyright © 2020-2023  润新知