SDL&android
1.通过jni编译SDL
解压下载的SDL文件
将目录下的include,src文件夹以及Android.mk文件分别移动到jni目录下,执行ndk-build
我用的版本是2.0.5,编译会出现如下错误:
[armeabi] Compile thumb : SDL2 <= SDL_render_gles.c
[armeabi] Compile thumb : SDL2 <= SDL_render_gles2.c
D:/project/AndroidSDL/app/src/main/jni/src/render/opengles2/SDL_gles2funcs.h: In function 'GLES2_LoadFunctions':
D:/project/AndroidSDL/app/src/main/jni/src/render/opengles2/SDL_render_gles2.c:294:45: warning: assignment from incompatible pointer type [enabled by default]
#define SDL_PROC(ret,func,params) data->func=func;
^
D:/project/AndroidSDL/app/src/main/jni/src/render/opengles2/SDL_gles2funcs.h:56:1: note: in expansion of macro 'SDL_PROC'
SDL_PROC(void, glShaderSource, (GLuint, GLsizei, const GLchar* const*, const GLint *))
^
具体原因没有分析,但是改用2.0.3后,编译通过(历史下载列表)。
编译出so文件后,又将目录下的AndroidProject中的Activity移动到了项目下(路径名也要一致,因为在c中有映射,改那个太麻烦),运行工程,再次出错
JNI DETECTED ERROR IN APPLICATION: JNI GetStaticMethodID called with pending exception 'java.lang.NoSuchMethodError' thrown in int org.libsdl.app.SDLActivity.nativeInit(java.lang.Object):-2
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] in call to GetStaticMethodID
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] from int org.libsdl.app.SDLActivity.nativeInit(java.lang.Object)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] "SDLThread" prio=5 tid=19 Runnable
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] | group="main" sCount=0 dsCount=0 obj=0x12d884c0 self=0xab66f138
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] | sysTid=22530 nice=0 cgrp=default sched=0/0 handle=0xab66f768
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] | state=R schedstat=( 823907 204323 7 ) utm=0 stm=0 core=6 HZ=100
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] | stack=0xe4a25000-0xe4a27000 stackSize=1036KB
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] | held mutexes= "mutator lock"(shared held)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #00 pc 000049f4 /system/lib/libbacktrace_libc++.so (_ZN13UnwindCurrent6UnwindEjP8ucontext+23)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #01 pc 000030cd /system/lib/libbacktrace_libc++.so (_ZN9Backtrace6UnwindEjP8ucontext+8)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #02 pc 002481c5 /system/lib/libart.so (_ZN3art15DumpNativeStackERNSt3__113basic_ostreamIcNS0_11char_traitsIcEEEEiPKcPNS_6mirror9ArtMethodE+68)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #03 pc 0022bf1d /system/lib/libart.so (_ZNK3art6Thread4DumpERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEE+144)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #04 pc 000b0c53 /system/lib/libart.so (_ZN3artL8JniAbortEPKcS1_+582)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #05 pc 000b1389 /system/lib/libart.so (_ZN3art9JniAbortFEPKcS1_z+60)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #06 pc 000b44cb /system/lib/libart.so (_ZN3art11ScopedCheckC2EP7_JNIEnviPKc+1286)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #07 pc 000b6793 /system/lib/libart.so (_ZN3art8CheckJNI17GetStaticMethodIDEP7_JNIEnvP7_jclassPKcS6_+26)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #08 pc 00042707 /data/app/ketr.com.androidsdl-1/lib/arm/libSDL2.so (SDL_Android_Init+106)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #09 pc 0000116f /data/app/ketr.com.androidsdl-1/lib/arm/libSDL2main.so (Java_org_libsdl_app_SDLActivity_nativeInit+2)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] native: #10 pc 0002d319 /data/data/ketr.com.androidsdl/cache/slice-slice_5-classes.dex (Java_org_libsdl_app_SDLActivity_nativeInit__Ljava_lang_Object_2+100)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] at org.libsdl.app.SDLActivity.nativeInit(Native method)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] at org.libsdl.app.SDLMain.run(SDLActivity.java:1028)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65] at java.lang.Thread.run(Thread.java:818)
11-08 13:52:18.681 22508-22530/? A/art: art/runtime/check_jni.cc:65]
11-08 13:52:18.701 22508-22530/? A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x1d in tid 22530 (SDLThread)
这个问题是由于jni对java的调用找不到方法导致的,c函数调用Java时,在core/android里面的实现出了问题,里面的函数还用了一些define别名,以及extern C_LINKAGE 来引用一些函数,最后发现调用流程是:
- SDLActivity里面调用init的本地方法;
- init方法的实现是在main/Android文件夹里SDL_Android_main.c里;
- init方法里面调用了core/android里面的方法初始化了,这个初始化的方法调用的是Android的Java代码;
- 接着又调用了SDL_main方法,这个方式是main方法的别名define定义的;
- 这个main方法就是自己写的主函数
也就是说,SDL最终还是调用的Android里面的方法,就变成了这样:
Android播放器实现(java)——>调用SDL本地方法——>调用java方法——>调用本地引擎方法
有点拐弯抹角,实现起来并不经济,SDL只是为了跨平台而实现的一层框架,并且里面对于Android中Java方法的相互调用,方法名写的比较死,耦合太大,随着版本的升级也要不断改动,如果不需要跨平台,就完全没用。
PS:通过javah生成头文件
app\build\intermediates\classes\debug>javah -jni org.libsdl.app.SDLActivity
错误: 无法访问android.app.Activity
找不到android.app.Activity的类文件
将目录切换到源文件src目录下执行,能正常生成头文件