summaryrefslogtreecommitdiff
path: root/src/contrib/SDL-2.30.2/docs/README-android.md
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2024-05-04 16:51:29 -0700
committer3gg <3gg@shellblade.net>2024-05-04 16:51:29 -0700
commit8222bfe56d4dabe8d92fc4b25ea1b0163b16f3e1 (patch)
tree763389e42276035ac134d94eb1dc32293b88d807 /src/contrib/SDL-2.30.2/docs/README-android.md
Initial commit.
Diffstat (limited to 'src/contrib/SDL-2.30.2/docs/README-android.md')
-rw-r--r--src/contrib/SDL-2.30.2/docs/README-android.md483
1 files changed, 483 insertions, 0 deletions
diff --git a/src/contrib/SDL-2.30.2/docs/README-android.md b/src/contrib/SDL-2.30.2/docs/README-android.md
new file mode 100644
index 0000000..b886f06
--- /dev/null
+++ b/src/contrib/SDL-2.30.2/docs/README-android.md
@@ -0,0 +1,483 @@
1Android
2================================================================================
3
4Matt Styles wrote a tutorial on building SDL for Android with Visual Studio:
5http://trederia.blogspot.de/2017/03/building-sdl2-for-android-with-visual.html
6
7The rest of this README covers the Android gradle style build process.
8
9If you are using the older ant build process, it is no longer officially
10supported, but you can use the "android-project-ant" directory as a template.
11
12
13Requirements
14================================================================================
15
16Android SDK (version 34 or later)
17https://developer.android.com/sdk/index.html
18
19Android NDK r15c or later
20https://developer.android.com/tools/sdk/ndk/index.html
21
22Minimum API level supported by SDL: 19 (Android 4.4)
23
24
25How the port works
26================================================================================
27
28- Android applications are Java-based, optionally with parts written in C
29- As SDL apps are C-based, we use a small Java shim that uses JNI to talk to
30 the SDL library
31- This means that your application C code must be placed inside an Android
32 Java project, along with some C support code that communicates with Java
33- This eventually produces a standard Android .apk package
34
35The Android Java code implements an "Activity" and can be found in:
36android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
37
38The Java code loads your game code, the SDL shared library, and
39dispatches to native functions implemented in the SDL library:
40src/core/android/SDL_android.c
41
42
43Building an app
44================================================================================
45
46For simple projects you can use the script located at build-scripts/androidbuild.sh
47
48There's two ways of using it:
49
50 androidbuild.sh com.yourcompany.yourapp < sources.list
51 androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c
52
53sources.list should be a text file with a source file name in each line
54Filenames should be specified relative to the current directory, for example if
55you are in the build-scripts directory and want to create the testgles.c test, you'll
56run:
57
58 ./androidbuild.sh org.libsdl.testgles ../test/testgles.c
59
60One limitation of this script is that all sources provided will be aggregated into
61a single directory, thus all your source files should have a unique name.
62
63Once the project is complete the script will tell you where the debug APK is located.
64If you want to create a signed release APK, you can use the project created by this
65utility to generate it.
66
67Finally, a word of caution: re running androidbuild.sh wipes any changes you may have
68done in the build directory for the app!
69
70
71
72For more complex projects, follow these instructions:
73
741. Get the source code for SDL and copy the 'android-project' directory located at SDL/android-project to a suitable location. Also make sure to rename it to your project name (In these examples: YOURPROJECT).
75
76 (The 'android-project' directory can basically be seen as a sort of starting point for the android-port of your project. It contains the glue code between the Android Java 'frontend' and the SDL code 'backend'. It also contains some standard behaviour, like how events should be handled, which you will be able to change.)
77
782. Move or [symlink](https://en.wikipedia.org/wiki/Symbolic_link) the SDL directory into the "YOURPROJECT/app/jni" directory
79
80(This is needed as the source of SDL has to be compiled by the Android compiler)
81
823. Edit "YOURPROJECT/app/jni/src/Android.mk" to include your source files.
83
84(They should be separated by spaces after the "LOCAL_SRC_FILES := " declaration)
85
864a. If you want to use Android Studio, simply open your 'YOURPROJECT' directory and start building.
87
884b. If you want to build manually, run './gradlew installDebug' in the project directory. This compiles the .java, creates an .apk with the native code embedded, and installs it on any connected Android device
89
90
91If you already have a project that uses CMake, the instructions change somewhat:
92
931. Do points 1 and 2 from the instruction above.
942. Edit "YOURPROJECT/app/build.gradle" to comment out or remove sections containing ndk-build
95 and uncomment the cmake sections. Add arguments to the CMake invocation as needed.
963. Edit "YOURPROJECT/app/jni/CMakeLists.txt" to include your project (it defaults to
97 adding the "src" subdirectory). Note that you'll have SDL2, SDL2main and SDL2-static
98 as targets in your project, so you should have "target_link_libraries(yourgame SDL2 SDL2main)"
99 in your CMakeLists.txt file. Also be aware that you should use add_library() instead of
100 add_executable() for the target containing your "main" function.
101
102If you wish to use Android Studio, you can skip the last step.
103
1044. Run './gradlew installDebug' or './gradlew installRelease' in the project directory. It will build and install your .apk on any
105 connected Android device
106
107Here's an explanation of the files in the Android project, so you can customize them:
108
109 android-project/app
110 build.gradle - build info including the application version and SDK
111 src/main/AndroidManifest.xml - package manifest. Among others, it contains the class name of the main Activity and the package name of the application.
112 jni/ - directory holding native code
113 jni/Application.mk - Application JNI settings, including target platform and STL library
114 jni/Android.mk - Android makefile that can call recursively the Android.mk files in all subdirectories
115 jni/CMakeLists.txt - Top-level CMake project that adds SDL as a subproject
116 jni/SDL/ - (symlink to) directory holding the SDL library files
117 jni/SDL/Android.mk - Android makefile for creating the SDL shared library
118 jni/src/ - directory holding your C/C++ source
119 jni/src/Android.mk - Android makefile that you should customize to include your source code and any library references
120 jni/src/CMakeLists.txt - CMake file that you may customize to include your source code and any library references
121 src/main/assets/ - directory holding asset files for your application
122 src/main/res/ - directory holding resources for your application
123 src/main/res/mipmap-* - directories holding icons for different phone hardware
124 src/main/res/values/strings.xml - strings used in your application, including the application name
125 src/main/java/org/libsdl/app/SDLActivity.java - the Java class handling the initialization and binding to SDL. Be very careful changing this, as the SDL library relies on this implementation. You should instead subclass this for your application.
126
127
128Customizing your application name
129================================================================================
130
131To customize your application name, edit AndroidManifest.xml and replace
132"org.libsdl.app" with an identifier for your product package.
133
134Then create a Java class extending SDLActivity and place it in a directory
135under src matching your package, e.g.
136
137 src/com/gamemaker/game/MyGame.java
138
139Here's an example of a minimal class file:
140
141 --- MyGame.java --------------------------
142 package com.gamemaker.game;
143
144 import org.libsdl.app.SDLActivity;
145
146 /**
147 * A sample wrapper class that just calls SDLActivity
148 */
149
150 public class MyGame extends SDLActivity { }
151
152 ------------------------------------------
153
154Then replace "SDLActivity" in AndroidManifest.xml with the name of your
155class, .e.g. "MyGame"
156
157
158Customizing your application icon
159================================================================================
160
161Conceptually changing your icon is just replacing the "ic_launcher.png" files in
162the drawable directories under the res directory. There are several directories
163for different screen sizes.
164
165
166Loading assets
167================================================================================
168
169Any files you put in the "app/src/main/assets" directory of your project
170directory will get bundled into the application package and you can load
171them using the standard functions in SDL_rwops.h.
172
173There are also a few Android specific functions that allow you to get other
174useful paths for saving and loading data:
175* SDL_AndroidGetInternalStoragePath()
176* SDL_AndroidGetExternalStorageState()
177* SDL_AndroidGetExternalStoragePath()
178
179See SDL_system.h for more details on these functions.
180
181The asset packaging system will, by default, compress certain file extensions.
182SDL includes two asset file access mechanisms, the preferred one is the so
183called "File Descriptor" method, which is faster and doesn't involve the Dalvik
184GC, but given this method does not work on compressed assets, there is also the
185"Input Stream" method, which is automatically used as a fall back by SDL. You
186may want to keep this fact in mind when building your APK, specially when large
187files are involved.
188For more information on which extensions get compressed by default and how to
189disable this behaviour, see for example:
190
191http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/
192
193
194Pause / Resume behaviour
195================================================================================
196
197If SDL_HINT_ANDROID_BLOCK_ON_PAUSE hint is set (the default),
198the event loop will block itself when the app is paused (ie, when the user
199returns to the main Android dashboard). Blocking is better in terms of battery
200use, and it allows your app to spring back to life instantaneously after resume
201(versus polling for a resume message).
202
203Upon resume, SDL will attempt to restore the GL context automatically.
204In modern devices (Android 3.0 and up) this will most likely succeed and your
205app can continue to operate as it was.
206
207However, there's a chance (on older hardware, or on systems under heavy load),
208where the GL context can not be restored. In that case you have to listen for
209a specific message (SDL_RENDER_DEVICE_RESET) and restore your textures
210manually or quit the app.
211
212You should not use the SDL renderer API while the app going in background:
213- SDL_APP_WILLENTERBACKGROUND:
214 after you read this message, GL context gets backed-up and you should not
215 use the SDL renderer API.
216
217 When this event is received, you have to set the render target to NULL, if you're using it.
218 (eg call SDL_SetRenderTarget(renderer, NULL))
219
220- SDL_APP_DIDENTERFOREGROUND:
221 GL context is restored, and the SDL renderer API is available (unless you
222 receive SDL_RENDER_DEVICE_RESET).
223
224Mouse / Touch events
225================================================================================
226
227In some case, SDL generates synthetic mouse (resp. touch) events for touch
228(resp. mouse) devices.
229To enable/disable this behavior, see SDL_hints.h:
230- SDL_HINT_TOUCH_MOUSE_EVENTS
231- SDL_HINT_MOUSE_TOUCH_EVENTS
232
233Misc
234================================================================================
235
236For some device, it appears to works better setting explicitly GL attributes
237before creating a window:
238 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
239 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
240 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
241
242Threads and the Java VM
243================================================================================
244
245For a quick tour on how Linux native threads interoperate with the Java VM, take
246a look here: https://developer.android.com/guide/practices/jni.html
247
248If you want to use threads in your SDL app, it's strongly recommended that you
249do so by creating them using SDL functions. This way, the required attach/detach
250handling is managed by SDL automagically. If you have threads created by other
251means and they make calls to SDL functions, make sure that you call
252Android_JNI_SetupThread() before doing anything else otherwise SDL will attach
253your thread automatically anyway (when you make an SDL call), but it'll never
254detach it.
255
256
257If you ever want to use JNI in a native thread (created by "SDL_CreateThread()"),
258it won't be able to find your java class and method because of the java class loader
259which is different for native threads, than for java threads (eg your "main()").
260
261the work-around is to find class/method, in you "main()" thread, and to use them
262in your native thread.
263
264see:
265https://developer.android.com/training/articles/perf-jni#faq:-why-didnt-findclass-find-my-class
266
267Using STL
268================================================================================
269
270You can use STL in your project by creating an Application.mk file in the jni
271folder and adding the following line:
272
273 APP_STL := c++_shared
274
275For more information go here:
276 https://developer.android.com/ndk/guides/cpp-support
277
278
279Using the emulator
280================================================================================
281
282There are some good tips and tricks for getting the most out of the
283emulator here: https://developer.android.com/tools/devices/emulator.html
284
285Especially useful is the info on setting up OpenGL ES 2.0 emulation.
286
287Notice that this software emulator is incredibly slow and needs a lot of disk space.
288Using a real device works better.
289
290
291Troubleshooting
292================================================================================
293
294You can see if adb can see any devices with the following command:
295
296 adb devices
297
298You can see the output of log messages on the default device with:
299
300 adb logcat
301
302You can push files to the device with:
303
304 adb push local_file remote_path_and_file
305
306You can push files to the SD Card at /sdcard, for example:
307
308 adb push moose.dat /sdcard/moose.dat
309
310You can see the files on the SD card with a shell command:
311
312 adb shell ls /sdcard/
313
314You can start a command shell on the default device with:
315
316 adb shell
317
318You can remove the library files of your project (and not the SDL lib files) with:
319
320 ndk-build clean
321
322You can do a build with the following command:
323
324 ndk-build
325
326You can see the complete command line that ndk-build is using by passing V=1 on the command line:
327
328 ndk-build V=1
329
330If your application crashes in native code, you can use ndk-stack to get a symbolic stack trace:
331 https://developer.android.com/ndk/guides/ndk-stack
332
333If you want to go through the process manually, you can use addr2line to convert the
334addresses in the stack trace to lines in your code.
335
336For example, if your crash looks like this:
337
338 I/DEBUG ( 31): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 400085d0
339 I/DEBUG ( 31): r0 00000000 r1 00001000 r2 00000003 r3 400085d4
340 I/DEBUG ( 31): r4 400085d0 r5 40008000 r6 afd41504 r7 436c6a7c
341 I/DEBUG ( 31): r8 436c6b30 r9 435c6fb0 10 435c6f9c fp 4168d82c
342 I/DEBUG ( 31): ip 8346aff0 sp 436c6a60 lr afd1c8ff pc afd1c902 cpsr 60000030
343 I/DEBUG ( 31): #00 pc 0001c902 /system/lib/libc.so
344 I/DEBUG ( 31): #01 pc 0001ccf6 /system/lib/libc.so
345 I/DEBUG ( 31): #02 pc 000014bc /data/data/org.libsdl.app/lib/libmain.so
346 I/DEBUG ( 31): #03 pc 00001506 /data/data/org.libsdl.app/lib/libmain.so
347
348You can see that there's a crash in the C library being called from the main code.
349I run addr2line with the debug version of my code:
350
351 arm-eabi-addr2line -C -f -e obj/local/armeabi/libmain.so
352
353and then paste in the number after "pc" in the call stack, from the line that I care about:
354000014bc
355
356I get output from addr2line showing that it's in the quit function, in testspriteminimal.c, on line 23.
357
358You can add logging to your code to help show what's happening:
359
360 #include <android/log.h>
361
362 __android_log_print(ANDROID_LOG_INFO, "foo", "Something happened! x = %d", x);
363
364If you need to build without optimization turned on, you can create a file called
365"Application.mk" in the jni directory, with the following line in it:
366
367 APP_OPTIM := debug
368
369
370Memory debugging
371================================================================================
372
373The best (and slowest) way to debug memory issues on Android is valgrind.
374Valgrind has support for Android out of the box, just grab code using:
375
376 svn co svn://svn.valgrind.org/valgrind/trunk valgrind
377
378... and follow the instructions in the file README.android to build it.
379
380One thing I needed to do on Mac OS X was change the path to the toolchain,
381and add ranlib to the environment variables:
382export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-ranlib
383
384Once valgrind is built, you can create a wrapper script to launch your
385application with it, changing org.libsdl.app to your package identifier:
386
387 --- start_valgrind_app -------------------
388 #!/system/bin/sh
389 export TMPDIR=/data/data/org.libsdl.app
390 exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $*
391 ------------------------------------------
392
393Then push it to the device:
394
395 adb push start_valgrind_app /data/local
396
397and make it executable:
398
399 adb shell chmod 755 /data/local/start_valgrind_app
400
401and tell Android to use the script to launch your application:
402
403 adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app"
404
405If the setprop command says "could not set property", it's likely that
406your package name is too long and you should make it shorter by changing
407AndroidManifest.xml and the path to your class file in android-project/src
408
409You can then launch your application normally and waaaaaaaiiittt for it.
410You can monitor the startup process with the logcat command above, and
411when it's done (or even while it's running) you can grab the valgrind
412output file:
413
414 adb pull /sdcard/valgrind.log
415
416When you're done instrumenting with valgrind, you can disable the wrapper:
417
418 adb shell setprop wrap.org.libsdl.app ""
419
420
421Graphics debugging
422================================================================================
423
424If you are developing on a compatible Tegra-based tablet, NVidia provides
425Tegra Graphics Debugger at their website. Because SDL2 dynamically loads EGL
426and GLES libraries, you must follow their instructions for installing the
427interposer library on a rooted device. The non-rooted instructions are not
428compatible with applications that use SDL2 for video.
429
430The Tegra Graphics Debugger is available from NVidia here:
431https://developer.nvidia.com/tegra-graphics-debugger
432
433
434Why is API level 19 the minimum required?
435================================================================================
436
437The latest NDK toolchain doesn't support targeting earlier than API level 19.
438As of this writing, according to https://www.composables.com/tools/distribution-chart
439about 99.7% of the Android devices accessing Google Play support API level 19 or
440higher (August 2023).
441
442
443A note regarding the use of the "dirty rectangles" rendering technique
444================================================================================
445
446If your app uses a variation of the "dirty rectangles" rendering technique,
447where you only update a portion of the screen on each frame, you may notice a
448variety of visual glitches on Android, that are not present on other platforms.
449This is caused by SDL's use of EGL as the support system to handle OpenGL ES/ES2
450contexts, in particular the use of the eglSwapBuffers function. As stated in the
451documentation for the function "The contents of ancillary buffers are always
452undefined after calling eglSwapBuffers".
453Setting the EGL_SWAP_BEHAVIOR attribute of the surface to EGL_BUFFER_PRESERVED
454is not possible for SDL as it requires EGL 1.4, available only on the API level
45517+, so the only workaround available on this platform is to redraw the entire
456screen each frame.
457
458Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html
459
460
461Ending your application
462================================================================================
463
464Two legitimate ways:
465
466- return from your main() function. Java side will automatically terminate the
467Activity by calling Activity.finish().
468
469- Android OS can decide to terminate your application by calling onDestroy()
470(see Activity life cycle). Your application will receive a SDL_QUIT event you
471can handle to save things and quit.
472
473Don't call exit() as it stops the activity badly.
474
475NB: "Back button" can be handled as a SDL_KEYDOWN/UP events, with Keycode
476SDLK_AC_BACK, for any purpose.
477
478Known issues
479================================================================================
480
481- The number of buttons reported for each joystick is hardcoded to be 36, which
482is the current maximum number of buttons Android can report.
483