docs/README-android.md
author Sam Lantinga <slouken@libsdl.org>
Mon, 23 Oct 2017 23:23:47 -0700
changeset 11649 fe6769530709
parent 11647 5816b27073a4
child 11659 b2fd0f264cd3
permissions -rw-r--r--
Updated Android build tools version, which bumped minimum deployment target to API 14
Also added native code to the Android gradle project, which allows using gradle or Android Studio to build the entire SDL application without a separate ndk-build step.
slouken@10486
     1
Android
gabomdq@9023
     2
================================================================================
gabomdq@9023
     3
slouken@11328
     4
Matt Styles wrote a tutorial on building SDL for Android with Visual Studio:
slouken@11328
     5
http://trederia.blogspot.de/2017/03/building-sdl2-for-android-with-visual.html
slouken@11328
     6
slouken@11647
     7
The rest of this README covers the traditional style build process.
slouken@11647
     8
slouken@11328
     9
slouken@11328
    10
================================================================================
slouken@11328
    11
 Requirements
slouken@11328
    12
================================================================================
gabomdq@9023
    13
slouken@11432
    14
Android SDK (version 16 or later)
icculus@10891
    15
https://developer.android.com/sdk/index.html
gabomdq@9023
    16
slouken@11649
    17
Android NDK r10e or later
icculus@10891
    18
https://developer.android.com/tools/sdk/ndk/index.html
gabomdq@9023
    19
slouken@11649
    20
Minimum API level supported by SDL: 14 (Android 4.0.1)
gabomdq@9023
    21
slouken@11647
    22
gabomdq@9023
    23
================================================================================
gabomdq@9023
    24
 How the port works
gabomdq@9023
    25
================================================================================
gabomdq@9023
    26
gabomdq@9023
    27
- Android applications are Java-based, optionally with parts written in C
gabomdq@9023
    28
- As SDL apps are C-based, we use a small Java shim that uses JNI to talk to 
philipp@9066
    29
  the SDL library
gabomdq@9023
    30
- This means that your application C code must be placed inside an Android 
philipp@9066
    31
  Java project, along with some C support code that communicates with Java
gabomdq@9023
    32
- This eventually produces a standard Android .apk package
gabomdq@9023
    33
gabomdq@9023
    34
The Android Java code implements an "Activity" and can be found in:
slouken@11647
    35
android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
gabomdq@9023
    36
gabomdq@9023
    37
The Java code loads your game code, the SDL shared library, and
gabomdq@9023
    38
dispatches to native functions implemented in the SDL library:
gabomdq@9023
    39
src/core/android/SDL_android.c
gabomdq@9023
    40
gabomdq@9023
    41
gabomdq@9023
    42
================================================================================
gabomdq@9023
    43
 Building an app
gabomdq@9023
    44
================================================================================
gabomdq@9023
    45
gabomdq@9023
    46
For simple projects you can use the script located at build-scripts/androidbuild.sh
gabomdq@9023
    47
gabomdq@9023
    48
There's two ways of using it:
gabomdq@9023
    49
philipp@9066
    50
    androidbuild.sh com.yourcompany.yourapp < sources.list
philipp@9066
    51
    androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c
gabomdq@9023
    52
gabomdq@9023
    53
sources.list should be a text file with a source file name in each line
gabomdq@9023
    54
Filenames should be specified relative to the current directory, for example if
gabomdq@9023
    55
you are in the build-scripts directory and want to create the testgles.c test, you'll
gabomdq@9023
    56
run:
philipp@9066
    57
philipp@9066
    58
    ./androidbuild.sh org.libsdl.testgles ../test/testgles.c
gabomdq@9023
    59
gabomdq@9023
    60
One limitation of this script is that all sources provided will be aggregated into
gabomdq@9023
    61
a single directory, thus all your source files should have a unique name.
gabomdq@9023
    62
gabomdq@9023
    63
Once the project is complete the script will tell you where the debug APK is located.
gabomdq@9023
    64
If you want to create a signed release APK, you can use the project created by this
gabomdq@9023
    65
utility to generate it.
gabomdq@9023
    66
gabomdq@9023
    67
Finally, a word of caution: re running androidbuild.sh wipes any changes you may have
gabomdq@9023
    68
done in the build directory for the app!
gabomdq@9023
    69
gabomdq@9023
    70
gabomdq@9023
    71
For more complex projects, follow these instructions:
gabomdq@9023
    72
    
gabomdq@9023
    73
1. Copy the android-project directory wherever you want to keep your projects
gabomdq@9023
    74
   and rename it to the name of your project.
slouken@11647
    75
2. Move or symlink this SDL directory into the "<project>/app/jni" directory
slouken@11647
    76
3. Edit "<project>/app/jni/src/Android.mk" to include your source files
gabomdq@9023
    77
4. Run 'ndk-build' (a script provided by the NDK). This compiles the C source
gabomdq@9023
    78
slouken@11647
    79
If you want to use Android Studio (recommended), skip to the Android Studio section below.
gabomdq@9023
    80
slouken@11647
    81
5. 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
gabomdq@9023
    82
gabomdq@9023
    83
Here's an explanation of the files in the Android project, so you can customize them:
gabomdq@9023
    84
slouken@11647
    85
    android-project/app
slouken@11647
    86
        build.gradle            - build info including the application version and SDK
slouken@11647
    87
        src/main/AndroidManifest.xml	- package manifest. Among others, it contains the class name
philipp@9055
    88
        			  of the main Activity and the package name of the application.
philipp@9055
    89
        jni/			- directory holding native code
slouken@11647
    90
        jni/Application.mk	- Application JNI settings, including target platform and STL library
slouken@11647
    91
        jni/Android.mk		- Android makefile that can call recursively the Android.mk files in all subdirectories
philipp@9055
    92
        jni/SDL/		- (symlink to) directory holding the SDL library files
philipp@9055
    93
        jni/SDL/Android.mk	- Android makefile for creating the SDL shared library
philipp@9055
    94
        jni/src/		- directory holding your C/C++ source
slouken@11647
    95
        jni/src/Android.mk	- Android makefile that you should customize to include your source code and any library references
slouken@11647
    96
        src/main/assets/	- directory holding asset files for your application
slouken@11647
    97
        src/main/res/		- directory holding resources for your application
slouken@11647
    98
        src/main/res/mipmap-*	- directories holding icons for different phone hardware
slouken@11647
    99
        src/main/res/values/strings.xml	- strings used in your application, including the application name
slouken@11647
   100
        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.
gabomdq@9023
   101
gabomdq@9023
   102
gabomdq@9023
   103
================================================================================
gabomdq@9023
   104
 Customizing your application name
gabomdq@9023
   105
================================================================================
gabomdq@9023
   106
gabomdq@9023
   107
To customize your application name, edit AndroidManifest.xml and replace
gabomdq@9023
   108
"org.libsdl.app" with an identifier for your product package.
gabomdq@9023
   109
gabomdq@9023
   110
Then create a Java class extending SDLActivity and place it in a directory
gabomdq@9023
   111
under src matching your package, e.g.
philipp@9055
   112
philipp@9066
   113
    src/com/gamemaker/game/MyGame.java
gabomdq@9023
   114
gabomdq@9023
   115
Here's an example of a minimal class file:
gabomdq@9023
   116
philipp@9050
   117
    --- MyGame.java --------------------------
philipp@9050
   118
    package com.gamemaker.game;
philipp@9050
   119
    
philipp@9050
   120
    import org.libsdl.app.SDLActivity; 
philipp@9050
   121
    
philipp@9065
   122
    /**
philipp@9050
   123
     * A sample wrapper class that just calls SDLActivity 
philipp@9050
   124
     */ 
philipp@9050
   125
    
philipp@9050
   126
    public class MyGame extends SDLActivity { }
philipp@9050
   127
    
philipp@9050
   128
    ------------------------------------------
gabomdq@9023
   129
gabomdq@9023
   130
Then replace "SDLActivity" in AndroidManifest.xml with the name of your
gabomdq@9023
   131
class, .e.g. "MyGame"
gabomdq@9023
   132
slouken@11647
   133
gabomdq@9023
   134
================================================================================
gabomdq@9023
   135
 Customizing your application icon
gabomdq@9023
   136
================================================================================
gabomdq@9023
   137
gabomdq@9023
   138
Conceptually changing your icon is just replacing the "ic_launcher.png" files in
slouken@11647
   139
the drawable directories under the res directory. There are several directories
slouken@11647
   140
for different screen sizes.
gabomdq@9023
   141
gabomdq@9023
   142
gabomdq@9023
   143
================================================================================
gabomdq@9023
   144
 Loading assets
gabomdq@9023
   145
================================================================================
gabomdq@9023
   146
slouken@11647
   147
Any files you put in the "app/src/main/assets" directory of your project
slouken@11647
   148
directory will get bundled into the application package and you can load
slouken@11647
   149
them using the standard functions in SDL_rwops.h.
gabomdq@9023
   150
gabomdq@9023
   151
There are also a few Android specific functions that allow you to get other
gabomdq@9023
   152
useful paths for saving and loading data:
philipp@9066
   153
* SDL_AndroidGetInternalStoragePath()
philipp@9066
   154
* SDL_AndroidGetExternalStorageState()
philipp@9066
   155
* SDL_AndroidGetExternalStoragePath()
gabomdq@9023
   156
gabomdq@9023
   157
See SDL_system.h for more details on these functions.
gabomdq@9023
   158
gabomdq@9023
   159
The asset packaging system will, by default, compress certain file extensions.
gabomdq@9023
   160
SDL includes two asset file access mechanisms, the preferred one is the so
gabomdq@9023
   161
called "File Descriptor" method, which is faster and doesn't involve the Dalvik
gabomdq@9023
   162
GC, but given this method does not work on compressed assets, there is also the
gabomdq@9023
   163
"Input Stream" method, which is automatically used as a fall back by SDL. You
gabomdq@9023
   164
may want to keep this fact in mind when building your APK, specially when large
gabomdq@9023
   165
files are involved.
gabomdq@9023
   166
For more information on which extensions get compressed by default and how to
gabomdq@9023
   167
disable this behaviour, see for example:
gabomdq@9023
   168
    
gabomdq@9023
   169
http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/
gabomdq@9023
   170
slouken@11647
   171
gabomdq@9023
   172
================================================================================
gabomdq@9023
   173
 Pause / Resume behaviour
gabomdq@9023
   174
================================================================================
gabomdq@9023
   175
gabomdq@9023
   176
If SDL is compiled with SDL_ANDROID_BLOCK_ON_PAUSE defined (the default),
gabomdq@9023
   177
the event loop will block itself when the app is paused (ie, when the user
gabomdq@9023
   178
returns to the main Android dashboard). Blocking is better in terms of battery
gabomdq@9023
   179
use, and it allows your app to spring back to life instantaneously after resume
gabomdq@9023
   180
(versus polling for a resume message).
gabomdq@9023
   181
gabomdq@9023
   182
Upon resume, SDL will attempt to restore the GL context automatically.
gabomdq@9023
   183
In modern devices (Android 3.0 and up) this will most likely succeed and your
gabomdq@9023
   184
app can continue to operate as it was.
gabomdq@9023
   185
gabomdq@9023
   186
However, there's a chance (on older hardware, or on systems under heavy load),
gabomdq@9023
   187
where the GL context can not be restored. In that case you have to listen for
gabomdq@9023
   188
a specific message, (which is not yet implemented!) and restore your textures
gabomdq@9023
   189
manually or quit the app (which is actually the kind of behaviour you'll see
gabomdq@9023
   190
under iOS, if the OS can not restore your GL context it will just kill your app)
gabomdq@9023
   191
slouken@11647
   192
gabomdq@9023
   193
================================================================================
gabomdq@9023
   194
 Threads and the Java VM
gabomdq@9023
   195
================================================================================
gabomdq@9023
   196
gabomdq@9023
   197
For a quick tour on how Linux native threads interoperate with the Java VM, take
icculus@10891
   198
a look here: https://developer.android.com/guide/practices/jni.html
philipp@9066
   199
gabomdq@9023
   200
If you want to use threads in your SDL app, it's strongly recommended that you
gabomdq@9023
   201
do so by creating them using SDL functions. This way, the required attach/detach
gabomdq@9023
   202
handling is managed by SDL automagically. If you have threads created by other
gabomdq@9023
   203
means and they make calls to SDL functions, make sure that you call
philipp@9065
   204
Android_JNI_SetupThread() before doing anything else otherwise SDL will attach
gabomdq@9023
   205
your thread automatically anyway (when you make an SDL call), but it'll never
gabomdq@9023
   206
detach it.
gabomdq@9023
   207
slouken@11647
   208
gabomdq@9023
   209
================================================================================
gabomdq@9023
   210
 Using STL
gabomdq@9023
   211
================================================================================
gabomdq@9023
   212
gabomdq@9023
   213
You can use STL in your project by creating an Application.mk file in the jni
gabomdq@9023
   214
folder and adding the following line:
philipp@9066
   215
philipp@9066
   216
    APP_STL := stlport_static
gabomdq@9023
   217
gabomdq@9023
   218
For more information check out CPLUSPLUS-SUPPORT.html in the NDK documentation.
gabomdq@9023
   219
slouken@11647
   220
gabomdq@9023
   221
================================================================================
gabomdq@9023
   222
 Additional documentation
gabomdq@9023
   223
================================================================================
gabomdq@9023
   224
gabomdq@9023
   225
The documentation in the NDK docs directory is very helpful in understanding the
gabomdq@9023
   226
build process and how to work with native code on the Android platform.
gabomdq@9023
   227
gabomdq@9023
   228
The best place to start is with docs/OVERVIEW.TXT
gabomdq@9023
   229
gabomdq@9023
   230
gabomdq@9023
   231
================================================================================
slouken@11647
   232
 Using Android Studio
gabomdq@9023
   233
================================================================================
gabomdq@9023
   234
slouken@11647
   235
You can open your project directory with Android Studio and run it normally.
gabomdq@9023
   236
gabomdq@9023
   237
gabomdq@9023
   238
================================================================================
gabomdq@9023
   239
 Using the emulator
gabomdq@9023
   240
================================================================================
gabomdq@9023
   241
gabomdq@9023
   242
There are some good tips and tricks for getting the most out of the
icculus@10891
   243
emulator here: https://developer.android.com/tools/devices/emulator.html
gabomdq@9023
   244
gabomdq@9023
   245
Especially useful is the info on setting up OpenGL ES 2.0 emulation.
gabomdq@9023
   246
gabomdq@9023
   247
Notice that this software emulator is incredibly slow and needs a lot of disk space.
gabomdq@9023
   248
Using a real device works better.
gabomdq@9023
   249
slouken@11647
   250
gabomdq@9023
   251
================================================================================
gabomdq@9023
   252
 Troubleshooting
gabomdq@9023
   253
================================================================================
gabomdq@9023
   254
gabomdq@9023
   255
You can see if adb can see any devices with the following command:
philipp@9055
   256
philipp@9066
   257
    adb devices
gabomdq@9023
   258
gabomdq@9023
   259
You can see the output of log messages on the default device with:
philipp@9055
   260
philipp@9066
   261
    adb logcat
gabomdq@9023
   262
gabomdq@9023
   263
You can push files to the device with:
philipp@9055
   264
philipp@9066
   265
    adb push local_file remote_path_and_file
gabomdq@9023
   266
gabomdq@9023
   267
You can push files to the SD Card at /sdcard, for example:
philipp@9055
   268
philipp@9066
   269
    adb push moose.dat /sdcard/moose.dat
gabomdq@9023
   270
gabomdq@9023
   271
You can see the files on the SD card with a shell command:
philipp@9055
   272
philipp@9066
   273
    adb shell ls /sdcard/
gabomdq@9023
   274
gabomdq@9023
   275
You can start a command shell on the default device with:
philipp@9055
   276
philipp@9066
   277
    adb shell
gabomdq@9023
   278
gabomdq@9023
   279
You can remove the library files of your project (and not the SDL lib files) with:
philipp@9055
   280
philipp@9066
   281
    ndk-build clean
gabomdq@9023
   282
gabomdq@9023
   283
You can do a build with the following command:
philipp@9055
   284
philipp@9066
   285
    ndk-build
gabomdq@9023
   286
gabomdq@9023
   287
You can see the complete command line that ndk-build is using by passing V=1 on the command line:
philipp@9055
   288
philipp@9066
   289
    ndk-build V=1
gabomdq@9023
   290
gabomdq@9023
   291
If your application crashes in native code, you can use addr2line to convert the
gabomdq@9023
   292
addresses in the stack trace to lines in your code.
gabomdq@9023
   293
gabomdq@9023
   294
For example, if your crash looks like this:
philipp@9050
   295
philipp@9050
   296
    I/DEBUG   (   31): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 400085d0
philipp@9050
   297
    I/DEBUG   (   31):  r0 00000000  r1 00001000  r2 00000003  r3 400085d4
philipp@9050
   298
    I/DEBUG   (   31):  r4 400085d0  r5 40008000  r6 afd41504  r7 436c6a7c
philipp@9050
   299
    I/DEBUG   (   31):  r8 436c6b30  r9 435c6fb0  10 435c6f9c  fp 4168d82c
philipp@9050
   300
    I/DEBUG   (   31):  ip 8346aff0  sp 436c6a60  lr afd1c8ff  pc afd1c902  cpsr 60000030
philipp@9050
   301
    I/DEBUG   (   31):          #00  pc 0001c902  /system/lib/libc.so
philipp@9050
   302
    I/DEBUG   (   31):          #01  pc 0001ccf6  /system/lib/libc.so
philipp@9050
   303
    I/DEBUG   (   31):          #02  pc 000014bc  /data/data/org.libsdl.app/lib/libmain.so
philipp@9050
   304
    I/DEBUG   (   31):          #03  pc 00001506  /data/data/org.libsdl.app/lib/libmain.so
gabomdq@9023
   305
gabomdq@9023
   306
You can see that there's a crash in the C library being called from the main code.
gabomdq@9023
   307
I run addr2line with the debug version of my code:
philipp@9055
   308
philipp@9066
   309
    arm-eabi-addr2line -C -f -e obj/local/armeabi/libmain.so
philipp@9055
   310
gabomdq@9023
   311
and then paste in the number after "pc" in the call stack, from the line that I care about:
gabomdq@9023
   312
000014bc
gabomdq@9023
   313
gabomdq@9023
   314
I get output from addr2line showing that it's in the quit function, in testspriteminimal.c, on line 23.
gabomdq@9023
   315
gabomdq@9023
   316
You can add logging to your code to help show what's happening:
gabomdq@9023
   317
philipp@9055
   318
    #include <android/log.h>
philipp@9055
   319
    
philipp@9055
   320
    __android_log_print(ANDROID_LOG_INFO, "foo", "Something happened! x = %d", x);
gabomdq@9023
   321
gabomdq@9023
   322
If you need to build without optimization turned on, you can create a file called
gabomdq@9023
   323
"Application.mk" in the jni directory, with the following line in it:
philipp@9066
   324
philipp@9066
   325
    APP_OPTIM := debug
gabomdq@9023
   326
gabomdq@9023
   327
gabomdq@9023
   328
================================================================================
gabomdq@9023
   329
 Memory debugging
gabomdq@9023
   330
================================================================================
gabomdq@9023
   331
gabomdq@9023
   332
The best (and slowest) way to debug memory issues on Android is valgrind.
gabomdq@9023
   333
Valgrind has support for Android out of the box, just grab code using:
philipp@9055
   334
philipp@9066
   335
    svn co svn://svn.valgrind.org/valgrind/trunk valgrind
philipp@9055
   336
gabomdq@9023
   337
... and follow the instructions in the file README.android to build it.
gabomdq@9023
   338
gabomdq@9023
   339
One thing I needed to do on Mac OS X was change the path to the toolchain,
gabomdq@9023
   340
and add ranlib to the environment variables:
gabomdq@9023
   341
export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-ranlib
gabomdq@9023
   342
gabomdq@9023
   343
Once valgrind is built, you can create a wrapper script to launch your
gabomdq@9023
   344
application with it, changing org.libsdl.app to your package identifier:
philipp@9050
   345
philipp@9050
   346
    --- start_valgrind_app -------------------
philipp@9050
   347
    #!/system/bin/sh
philipp@9050
   348
    export TMPDIR=/data/data/org.libsdl.app
philipp@9050
   349
    exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $*
philipp@9050
   350
    ------------------------------------------
gabomdq@9023
   351
gabomdq@9023
   352
Then push it to the device:
philipp@9055
   353
philipp@9066
   354
    adb push start_valgrind_app /data/local
gabomdq@9023
   355
gabomdq@9023
   356
and make it executable:
philipp@9055
   357
philipp@9066
   358
    adb shell chmod 755 /data/local/start_valgrind_app
gabomdq@9023
   359
gabomdq@9023
   360
and tell Android to use the script to launch your application:
philipp@9055
   361
philipp@9066
   362
    adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app"
gabomdq@9023
   363
gabomdq@9023
   364
If the setprop command says "could not set property", it's likely that
gabomdq@9023
   365
your package name is too long and you should make it shorter by changing
gabomdq@9023
   366
AndroidManifest.xml and the path to your class file in android-project/src
gabomdq@9023
   367
gabomdq@9023
   368
You can then launch your application normally and waaaaaaaiiittt for it.
gabomdq@9023
   369
You can monitor the startup process with the logcat command above, and
gabomdq@9023
   370
when it's done (or even while it's running) you can grab the valgrind
gabomdq@9023
   371
output file:
philipp@9055
   372
philipp@9066
   373
    adb pull /sdcard/valgrind.log
gabomdq@9023
   374
gabomdq@9023
   375
When you're done instrumenting with valgrind, you can disable the wrapper:
philipp@9055
   376
philipp@9066
   377
    adb shell setprop wrap.org.libsdl.app ""
gabomdq@9023
   378
slouken@11647
   379
gabomdq@9023
   380
================================================================================
slouken@10487
   381
 Graphics debugging
slouken@10487
   382
================================================================================
slouken@10487
   383
philipp@10543
   384
If you are developing on a compatible Tegra-based tablet, NVidia provides
slouken@11647
   385
Tegra Graphics Debugger at their website. Because SDL2 dynamically loads EGL
philipp@10543
   386
and GLES libraries, you must follow their instructions for installing the
slouken@11647
   387
interposer library on a rooted device. The non-rooted instructions are not
philipp@10543
   388
compatible with applications that use SDL2 for video.
slouken@10487
   389
slouken@10487
   390
The Tegra Graphics Debugger is available from NVidia here:
slouken@10487
   391
https://developer.nvidia.com/tegra-graphics-debugger
slouken@10487
   392
slouken@11647
   393
slouken@10487
   394
================================================================================
slouken@11649
   395
 Why is API level 14 the minimum required?
gabomdq@9023
   396
================================================================================
gabomdq@9023
   397
slouken@11649
   398
The latest NDK toolchain doesn't support targeting earlier than API level 14.
icculus@10891
   399
As of this writing, according to https://developer.android.com/about/dashboards/index.html
slouken@11649
   400
about 99% of the Android devices accessing Google Play support API level 14 or
slouken@11649
   401
higher (October 2017).
gabomdq@9023
   402
slouken@11647
   403
gabomdq@9023
   404
================================================================================
gabomdq@9023
   405
 A note regarding the use of the "dirty rectangles" rendering technique
gabomdq@9023
   406
================================================================================
gabomdq@9023
   407
gabomdq@9023
   408
If your app uses a variation of the "dirty rectangles" rendering technique,
gabomdq@9023
   409
where you only update a portion of the screen on each frame, you may notice a
gabomdq@9023
   410
variety of visual glitches on Android, that are not present on other platforms.
gabomdq@9023
   411
This is caused by SDL's use of EGL as the support system to handle OpenGL ES/ES2
gabomdq@9023
   412
contexts, in particular the use of the eglSwapBuffers function. As stated in the
gabomdq@9023
   413
documentation for the function "The contents of ancillary buffers are always 
gabomdq@9023
   414
undefined after calling eglSwapBuffers".
gabomdq@9023
   415
Setting the EGL_SWAP_BEHAVIOR attribute of the surface to EGL_BUFFER_PRESERVED
gabomdq@9023
   416
is not possible for SDL as it requires EGL 1.4, available only on the API level
gabomdq@9023
   417
17+, so the only workaround available on this platform is to redraw the entire
gabomdq@9023
   418
screen each frame.
gabomdq@9023
   419
gabomdq@9023
   420
Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html
gabomdq@9023
   421
slouken@11647
   422
gabomdq@9023
   423
================================================================================
gabomdq@9023
   424
 Known issues
gabomdq@9023
   425
================================================================================
gabomdq@9023
   426
gabomdq@9023
   427
- The number of buttons reported for each joystick is hardcoded to be 36, which
gabomdq@9023
   428
is the current maximum number of buttons Android can report.
gabomdq@9023
   429