Android 编译SDL
Android 使用cmake 编译SDL2
如这里解压得到 SDL2-2.0.12:
几个重要的目录与文件说明
android-project: Android 项目的模板项目
docs:说明文档
include:SDL2的头文件
src:SDL2的源文件
Android.mk: makefile的构建脚本,编译动态库和静态库
CmakeLists.txt: CMake的构建脚本,编译动态库和静态库
123456
1、搭建项目
使用android-project 作为一个模板搭建一个项目,必须包名一致(SDLActivity 里声明了native方法,如果包名不一致,本地方法与jni层的映射的方法对应不上,会报错,可以修改,不过先别管这么多,先跑起来再说)
1、新建一个项目,包名取org.libsdl.app
2、把模板项目android-project 下的文件复制过来,org.libsdl.app 下的所有文件,AndroidManifest.xml, app的build.gradle,复制后如下:
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion "30.0.0"
defaultConfig {
applicationId "org.libsdl.app"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
// ndkBuild {
// arguments "APP_PLATFORM=android-21"
// abiFilters 'armeabi-v7a'
// }
cmake {
arguments "-DANDROID_APP_PLATFORM=android-21", "-DANDROID_STL=c++_static"
cppFlags ""
abiFilters 'armeabi-v7a'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
sourceSets.main {
jniLibs.srcDir 'libs'
}
externalNativeBuild {
// ndkBuild {
// path 'src/main/jni/Android.mk'
// }
cmake {
//这里需要指定到 jni/CMakeLists.txt 文件
path "src/main/jni/CMakeLists.txt"
version "3.10.2"
}
}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
(想用cmake 编译就打开cmake,想用makefile 方式就打开ndkBuild,这里使用了cmake方式)
AndroidManifest.xml 文件不贴了,原样照搬
3、
- 新建jni 文件夹,在jni 文件中新建SDL文件夹,把解压文件(SDL2-2.0.12)中的cmake、include、src文件夹直接复制到SDL文件夹中
- 把解压文件夹(SDL2-2.0.12) 中的所有 .in 结尾的文件和Android.mk、CMakeLists.txt也复制到SDL 文件中
- 在把模板项目中SDL2-2.0.12\android-project\app\jni 下的所有文件复制到jni 文件夹下
完成后项目结构如下:
(这里也把.mk 文件放进来,如果只是想用cmake 方式也不复制过来)
4、新建SDL2Android.c文件放到 jni/SDL/src 中
这里SDL2Android.c 文件作用是绘制一张图片,内容如下:SDL详细使用
文件中使用了zx.bmp图片,建一个assets文件,随便把一张图片放进去就行
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "SDL.h"
typedef struct Sprite
{
SDL_Texture* texture;
Uint16 w;
Uint16 h;
} Sprite;
/* Adapted from SDL's testspriteminimal.c */
Sprite LoadSprite(const char* file, SDL_Renderer* renderer)
{
Sprite result;
result.texture = NULL;
result.w = 0;
result.h = 0;
SDL_Surface* temp;
/* Load the sprite image */
temp = SDL_LoadBMP(file);
if (temp == NULL)
{
fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
return result;
}
result.w = temp->w;
result.h = temp->h;
/* Create texture from the image */
result.texture = SDL_CreateTextureFromSurface(renderer, temp);
if (!result.texture) {
fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
SDL_FreeSurface(temp);
return result;
}
SDL_FreeSurface(temp);
return result;
}
void draw(SDL_Window* window, SDL_Renderer* renderer, const Sprite sprite)
{
int w, h;
SDL_GetWindowSize(window, &w, &h);
SDL_Rect destRect = {w/2 - sprite.w/2, h/2 - sprite.h/2, sprite.w, sprite.h};
/* Blit the sprite onto the screen */
SDL_RenderCopy(renderer, sprite.texture, NULL, &destRect);
}
/**
* 图片绘制,一定是个main方法
* SDL 会自动调用这个方法,完成图片绘制与显示
* @param argc
* @param argv
* @return
*/
int main(int argc, char *argv[])
{
SDL_Window *window;
SDL_Renderer *renderer;
if(SDL_CreateWindowAndRenderer(0, 0, 0, &window, &renderer) < 0)
exit(2);
Sprite sprite = LoadSprite("zx.bmp", renderer);
if(sprite.texture == NULL)
exit(2);
/* Main render loop */
Uint8 done = 0;
SDL_Event event;
while(!done)
{
/* Check for events */
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT || event.type == SDL_KEYDOWN || event.type == SDL_FINGERDOWN)
{
//done = 1;
}
}
/* Draw a gray background */
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
SDL_RenderClear(renderer);
draw(window, renderer, sprite);
/* Update the screen! */
SDL_RenderPresent(renderer);
SDL_Delay(10);
}
exit(0);
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
5、修改 jni/src/CMakeLists.txt 文件,修改后如下,注释已经说明了
cmake_minimum_required(VERSION 3.4.1)
project(MY_APP)
#这里添加了头文件查找目录
include_directories(${CMAKE_SOURCE_DIR}/SDL/include)
#生成main.so 需要引用SDL2.so库 (SDL2.so是脚本文件jni/SDL/CMakeLists.txt 生成的)
find_library(SDL2 SDL2)
add_library(main SHARED)
#添加这个main.so 的原文件,把 SDL2Android.c 放到这个so库中(SDL_android_main.c 是自带的一个空文件,其他也可以直接使用这个文件)
target_sources(main PRIVATE ${CMAKE_SOURCE_DIR}/SDL/src/main/android/SDL_android_main.c
${CMAKE_SOURCE_DIR}/SDL/src/SDL2Android.c)
#把SDL2.so 加入main.so 中
target_link_libraries(main SDL2)
12345678910111213141516171819
6、jni/CMakeLists.txt 文件内容
cmake_minimum_required(VERSION 3.4.1)
project(GAME)
#编译 SDL 目录下的cmake文件
add_subdirectory(SDL)
#编译 src 目录下的cmake文件
add_subdirectory(src)
123456789
7、记得把app 中build.gradle 中cmake 指定到 jni/CMakeLists.txt 文件
8、编译项目,会在build/intermediates/cmake/debug/obj/armeabi-v7a 下生成想要的动态库与静态库(这里只编译了armv7a的)
9、运行项目: