README-android.txt
changeset 7222 2435b221d77d
parent 7166 8d17ec58f019
child 7241 28602f5ca96d
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/README-android.txt	Sun May 26 11:06:17 2013 -0700
     1.3 @@ -0,0 +1,384 @@
     1.4 +================================================================================
     1.5 +Simple DirectMedia Layer for Android
     1.6 +================================================================================
     1.7 +
     1.8 +Requirements:
     1.9 +
    1.10 +Android SDK (version 10 or later)
    1.11 +http://developer.android.com/sdk/index.html
    1.12 +
    1.13 +Android NDK r7 or later
    1.14 +http://developer.android.com/sdk/ndk/index.html
    1.15 +
    1.16 +inimum API level supported by SDL: 10 (Android 2.3.3)
    1.17 +
    1.18 +================================================================================
    1.19 + How the port works
    1.20 +================================================================================
    1.21 +
    1.22 +- Android applications are Java-based, optionally with parts written in C
    1.23 +- As SDL apps are C-based, we use a small Java shim that uses JNI to talk to 
    1.24 +the SDL library
    1.25 +- This means that your application C code must be placed inside an Android 
    1.26 +Java project, along with some C support code that communicates with Java
    1.27 +- This eventually produces a standard Android .apk package
    1.28 +
    1.29 +The Android Java code implements an "Activity" and can be found in:
    1.30 +android-project/src/org/libsdl/app/SDLActivity.java
    1.31 +
    1.32 +The Java code loads your game code, the SDL shared library, and
    1.33 +dispatches to native functions implemented in the SDL library:
    1.34 +src/SDL_android.cpp
    1.35 +
    1.36 +Your project must include some glue code that starts your main() routine:
    1.37 +src/main/android/SDL_android_main.cpp
    1.38 +
    1.39 +
    1.40 +================================================================================
    1.41 + Building an app
    1.42 +================================================================================
    1.43 +
    1.44 +Instructions:
    1.45 +1. Copy the android-project directory wherever you want to keep your projects
    1.46 +   and rename it to the name of your project.
    1.47 +2. Move or symlink this SDL directory into the <project>/jni directory
    1.48 +3. Edit <project>/jni/src/Android.mk to include your source files
    1.49 +4. Run 'ndk-build' (a script provided by the NDK). This compiles the C source
    1.50 +
    1.51 +If you want to use the Eclipse IDE, skip to the Eclipse section below.
    1.52 +
    1.53 +5. Create <project>/local.properties and use that to point to the Android SDK directory, by writing a line with the following form:
    1.54 +sdk.dir=PATH_TO_ANDROID_SDK
    1.55 +6. Run 'ant debug' in android/project. This compiles the .java and eventually 
    1.56 +   creates a .apk with the native code embedded
    1.57 +7. 'ant debug install' will push the apk to the device or emulator (if connected)
    1.58 +
    1.59 +Here's an explanation of the files in the Android project, so you can customize them:
    1.60 +
    1.61 +android-project/
    1.62 +	AndroidManifest.xml	- package manifest. Among others, it contains the class name
    1.63 +				  of the main Activity and the package name of the application.
    1.64 +	build.properties	- empty
    1.65 +	build.xml		- build description file, used by ant. The actual application name
    1.66 +				  is specified here.
    1.67 +	default.properties	- holds the target ABI for the application, android-10 and up
    1.68 +	project.properties	- holds the target ABI for the application, android-10 and up
    1.69 +	local.properties	- holds the SDK path, you should change this to the path to your SDK
    1.70 +	jni/			- directory holding native code
    1.71 +	jni/Android.mk		- Android makefile that can call recursively the Android.mk files
    1.72 +				  in all subdirectories
    1.73 +	jni/SDL/		- (symlink to) directory holding the SDL library files
    1.74 +	jni/SDL/Android.mk	- Android makefile for creating the SDL shared library
    1.75 +	jni/src/		- directory holding your C/C++ source
    1.76 +	jni/src/Android.mk	- Android makefile that you should customize to include your 
    1.77 +                                  source code and any library references
    1.78 +	res/			- directory holding resources for your application
    1.79 +	res/drawable-*		- directories holding icons for different phone hardware. Could be
    1.80 +				  one dir called "drawable".
    1.81 +	res/layout/main.xml	- Usually contains a file main.xml, which declares the screen layout.
    1.82 +				  We don't need it because we use the SDL video output.
    1.83 +	res/values/strings.xml	- strings used in your application, including the application name
    1.84 +				  shown on the phone.
    1.85 +	src/org/libsdl/app/SDLActivity.java - the Java class handling the initialization and binding
    1.86 +				  to SDL.  Be very careful changing this, as the SDL library relies
    1.87 +				  on this implementation.
    1.88 +
    1.89 +
    1.90 +================================================================================
    1.91 + Customizing your application name
    1.92 +================================================================================
    1.93 +
    1.94 +To customize your application name, edit AndroidManifest.xml and replace
    1.95 +"org.libsdl.app" with an identifier for your product package.
    1.96 +
    1.97 +Then create a Java class extending SDLActivity and place it in a directory
    1.98 +under src matching your package, e.g.
    1.99 +	src/com/gamemaker/game/MyGame.java
   1.100 +
   1.101 +Here's an example of a minimal class file:
   1.102 +--- MyGame.java --------------------------
   1.103 +package com.gamemaker.game;
   1.104 +
   1.105 +import org.libsdl.app.SDLActivity; 
   1.106 +
   1.107 +/* 
   1.108 + * A sample wrapper class that just calls SDLActivity 
   1.109 + */ 
   1.110 +
   1.111 +public class MyGame extends SDLActivity { }
   1.112 +
   1.113 +------------------------------------------
   1.114 +
   1.115 +Then replace "SDLActivity" in AndroidManifest.xml with the name of your
   1.116 +class, .e.g. "MyGame"
   1.117 +
   1.118 +================================================================================
   1.119 + Customizing your application icon
   1.120 +================================================================================
   1.121 +
   1.122 +Conceptually changing your icon is just replacing the "ic_launcher.png" files in
   1.123 +the drawable directories under the res directory. There are four directories for
   1.124 +different screen sizes. These can be replaced with one dir called "drawable",
   1.125 +containing an icon file "ic_launcher.png" with dimensions 48x48 or 72x72.
   1.126 +
   1.127 +You may need to change the name of your icon in AndroidManifest.xml to match
   1.128 +this icon filename.
   1.129 +
   1.130 +================================================================================
   1.131 + Loading assets
   1.132 +================================================================================
   1.133 +
   1.134 +Any files you put in the "assets" directory of your android-project directory
   1.135 +will get bundled into the application package and you can load them using the
   1.136 +standard functions in SDL_rwops.h.
   1.137 +
   1.138 +There are also a few Android specific functions that allow you to get other
   1.139 +useful paths for saving and loading data:
   1.140 +SDL_AndroidGetInternalStoragePath()
   1.141 +SDL_AndroidGetExternalStorageState()
   1.142 +SDL_AndroidGetExternalStoragePath()
   1.143 +
   1.144 +See SDL_system.h for more details on these functions.
   1.145 +
   1.146 +The asset packaging system will, by default, compress certain file extensions.
   1.147 +SDL includes two asset file access mechanisms, the preferred one is the so
   1.148 +called "File Descriptor" method, which is faster and doesn't involve the Dalvik
   1.149 +GC, but given this method does not work on compressed assets, there is also the
   1.150 +"Input Stream" method, which is automatically used as a fall back by SDL. You
   1.151 +may want to keep this fact in mind when building your APK, specially when large
   1.152 +files are involved.
   1.153 +For more information on which extensions get compressed by default and how to
   1.154 +disable this behaviour, see for example:
   1.155 +    
   1.156 +http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/
   1.157 +
   1.158 +================================================================================
   1.159 + Pause / Resume behaviour
   1.160 +================================================================================
   1.161 +
   1.162 +If SDL is compiled with SDL_ANDROID_BLOCK_ON_PAUSE defined (the default),
   1.163 +the event loop will block itself when the app is paused (ie, when the user
   1.164 +returns to the main Android dashboard). Blocking is better in terms of battery
   1.165 +use, and it allows your app to spring back to life instantaneously after resume
   1.166 +(versus polling for a resume message).
   1.167 +
   1.168 +Upon resume, SDL will attempt to restore the GL context automatically.
   1.169 +In modern devices (Android 3.0 and up) this will most likely succeed and your
   1.170 +app can continue to operate as it was.
   1.171 +
   1.172 +However, there's a chance (on older hardware, or on systems under heavy load),
   1.173 +where the GL context can not be restored. In that case you have to listen for
   1.174 +a specific message, (which is not yet implemented!) and restore your textures
   1.175 +manually or quit the app (which is actually the kind of behaviour you'll see
   1.176 +under iOS, if the OS can not restore your GL context it will just kill your app)
   1.177 +
   1.178 +================================================================================
   1.179 + Threads and the Java VM
   1.180 +================================================================================
   1.181 +
   1.182 +For a quick tour on how Linux native threads interoperate with the Java VM, take
   1.183 +a look here: http://developer.android.com/guide/practices/jni.html
   1.184 +If you want to use threads in your SDL app, it's strongly recommended that you
   1.185 +do so by creating them using SDL functions. This way, the required attach/detach
   1.186 +handling is managed by SDL automagically. If you have threads created by other
   1.187 +means and they make calls to SDL functions, make sure that you call
   1.188 +Android_JNI_SetupThread before doing anything else otherwise SDL will attach
   1.189 +your thread automatically anyway (when you make an SDL call), but it'll never
   1.190 +detach it.
   1.191 +
   1.192 +================================================================================
   1.193 + Using STL
   1.194 +================================================================================
   1.195 +
   1.196 +You can use STL in your project by creating an Application.mk file in the jni
   1.197 +folder and adding the following line:
   1.198 +APP_STL := stlport_static
   1.199 +
   1.200 +For more information check out CPLUSPLUS-SUPPORT.html in the NDK documentation.
   1.201 +
   1.202 +================================================================================
   1.203 + Additional documentation
   1.204 +================================================================================
   1.205 +
   1.206 +The documentation in the NDK docs directory is very helpful in understanding the
   1.207 +build process and how to work with native code on the Android platform.
   1.208 +
   1.209 +The best place to start is with docs/OVERVIEW.TXT
   1.210 +
   1.211 +
   1.212 +================================================================================
   1.213 + Using Eclipse
   1.214 +================================================================================
   1.215 +
   1.216 +First make sure that you've installed Eclipse and the Android extensions as described here:
   1.217 +	http://developer.android.com/sdk/eclipse-adt.html
   1.218 +
   1.219 +Once you've copied the SDL android project and customized it, you can create an Eclipse project from it:
   1.220 + * File -> New -> Other
   1.221 + * Select the Android -> Android Project wizard and click Next
   1.222 + * Enter the name you'd like your project to have
   1.223 + * Select "Create project from existing source" and browse for your project directory
   1.224 + * Make sure the Build Target is set to Android 2.0
   1.225 + * Click Finish
   1.226 +
   1.227 +
   1.228 +================================================================================
   1.229 + Using the emulator
   1.230 +================================================================================
   1.231 +
   1.232 +There are some good tips and tricks for getting the most out of the
   1.233 +emulator here: http://developer.android.com/tools/devices/emulator.html
   1.234 +
   1.235 +Especially useful is the info on setting up OpenGL ES 2.0 emulation.
   1.236 +
   1.237 +Notice that this software emulator is incredibly slow and needs a lot of disk space.
   1.238 +Using a real device works better.
   1.239 +
   1.240 +================================================================================
   1.241 + Troubleshooting
   1.242 +================================================================================
   1.243 +
   1.244 +You can create and run an emulator from the Eclipse IDE:
   1.245 + * Window -> Android SDK and AVD Manager
   1.246 +
   1.247 +You can see if adb can see any devices with the following command:
   1.248 +	adb devices
   1.249 +
   1.250 +You can see the output of log messages on the default device with:
   1.251 +	adb logcat
   1.252 +
   1.253 +You can push files to the device with:
   1.254 +	adb push local_file remote_path_and_file
   1.255 +
   1.256 +You can push files to the SD Card at /sdcard, for example:
   1.257 +	adb push moose.dat /sdcard/moose.dat
   1.258 +
   1.259 +You can see the files on the SD card with a shell command:
   1.260 +	adb shell ls /sdcard/
   1.261 +
   1.262 +You can start a command shell on the default device with:
   1.263 +	adb shell
   1.264 +
   1.265 +You can remove the library files of your project (and not the SDL lib files) with:
   1.266 +	ndk-build clean
   1.267 +
   1.268 +You can do a build with the following command:
   1.269 +	ndk-build
   1.270 +
   1.271 +You can see the complete command line that ndk-build is using by passing V=1 on the command line:
   1.272 +	ndk-build V=1
   1.273 +
   1.274 +If your application crashes in native code, you can use addr2line to convert the
   1.275 +addresses in the stack trace to lines in your code.
   1.276 +
   1.277 +For example, if your crash looks like this:
   1.278 +I/DEBUG   (   31): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 400085d0
   1.279 +I/DEBUG   (   31):  r0 00000000  r1 00001000  r2 00000003  r3 400085d4
   1.280 +I/DEBUG   (   31):  r4 400085d0  r5 40008000  r6 afd41504  r7 436c6a7c
   1.281 +I/DEBUG   (   31):  r8 436c6b30  r9 435c6fb0  10 435c6f9c  fp 4168d82c
   1.282 +I/DEBUG   (   31):  ip 8346aff0  sp 436c6a60  lr afd1c8ff  pc afd1c902  cpsr 60000030
   1.283 +I/DEBUG   (   31):          #00  pc 0001c902  /system/lib/libc.so
   1.284 +I/DEBUG   (   31):          #01  pc 0001ccf6  /system/lib/libc.so
   1.285 +I/DEBUG   (   31):          #02  pc 000014bc  /data/data/org.libsdl.app/lib/libmain.so
   1.286 +I/DEBUG   (   31):          #03  pc 00001506  /data/data/org.libsdl.app/lib/libmain.so
   1.287 +
   1.288 +You can see that there's a crash in the C library being called from the main code.
   1.289 +I run addr2line with the debug version of my code:
   1.290 +	arm-eabi-addr2line -C -f -e obj/local/armeabi/libmain.so
   1.291 +and then paste in the number after "pc" in the call stack, from the line that I care about:
   1.292 +000014bc
   1.293 +
   1.294 +I get output from addr2line showing that it's in the quit function, in testspriteminimal.c, on line 23.
   1.295 +
   1.296 +You can add logging to your code to help show what's happening:
   1.297 +
   1.298 +#include <android/log.h>
   1.299 +
   1.300 +	__android_log_print(ANDROID_LOG_INFO, "foo", "Something happened! x = %d", x);
   1.301 +
   1.302 +If you need to build without optimization turned on, you can create a file called
   1.303 +"Application.mk" in the jni directory, with the following line in it:
   1.304 +APP_OPTIM := debug
   1.305 +
   1.306 +
   1.307 +================================================================================
   1.308 + Memory debugging
   1.309 +================================================================================
   1.310 +
   1.311 +The best (and slowest) way to debug memory issues on Android is valgrind.
   1.312 +Valgrind has support for Android out of the box, just grab code using:
   1.313 +	svn co svn://svn.valgrind.org/valgrind/trunk valgrind
   1.314 +... and follow the instructions in the file README.android to build it.
   1.315 +
   1.316 +One thing I needed to do on Mac OS X was change the path to the toolchain,
   1.317 +and add ranlib to the environment variables:
   1.318 +export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-ranlib
   1.319 +
   1.320 +Once valgrind is built, you can create a wrapper script to launch your
   1.321 +application with it, changing org.libsdl.app to your package identifier:
   1.322 +--- start_valgrind_app -------------------
   1.323 +#!/system/bin/sh
   1.324 +export TMPDIR=/data/data/org.libsdl.app
   1.325 +exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $*
   1.326 +------------------------------------------
   1.327 +
   1.328 +Then push it to the device:
   1.329 +	adb push start_valgrind_app /data/local
   1.330 +
   1.331 +and make it executable:
   1.332 +	adb shell chmod 755 /data/local/start_valgrind_app
   1.333 +
   1.334 +and tell Android to use the script to launch your application:
   1.335 +	adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app"
   1.336 +
   1.337 +If the setprop command says "could not set property", it's likely that
   1.338 +your package name is too long and you should make it shorter by changing
   1.339 +AndroidManifest.xml and the path to your class file in android-project/src
   1.340 +
   1.341 +You can then launch your application normally and waaaaaaaiiittt for it.
   1.342 +You can monitor the startup process with the logcat command above, and
   1.343 +when it's done (or even while it's running) you can grab the valgrind
   1.344 +output file:
   1.345 +	adb pull /sdcard/valgrind.log
   1.346 +
   1.347 +When you're done instrumenting with valgrind, you can disable the wrapper:
   1.348 +	adb shell setprop wrap.org.libsdl.app ""
   1.349 +
   1.350 +================================================================================
   1.351 + Why is API level 10 the minimum required?
   1.352 +================================================================================
   1.353 +
   1.354 +API level 10 is required because SDL requires some functionality for running not
   1.355 +available on older devices and some for building which is not in older NDK/SDKs.
   1.356 +
   1.357 +Support for native OpenGL ES and ES2 applications was introduced in the NDK for
   1.358 +API level 4 and 8. EGL was made a stable API in the NDK for API level 9, which
   1.359 +has since then been obsoleted, with the recommendation to developers to bump the
   1.360 +required API level to 10.
   1.361 +As of this writing, according to http://developer.android.com/about/dashboards/index.html
   1.362 +about 90% of the Android devices accessing Google Play support API level 10 or
   1.363 +higher (March 2013).
   1.364 +
   1.365 +================================================================================
   1.366 + A note regarding the use of the "dirty rectangles" rendering technique
   1.367 +================================================================================
   1.368 +
   1.369 +If your app uses a variation of the "dirty rectangles" rendering technique,
   1.370 +where you only update a portion of the screen on each frame, you may notice a
   1.371 +variety of visual glitches on Android, that are not present on other platforms.
   1.372 +This is caused by SDL's use of EGL as the support system to handle OpenGL ES/ES2
   1.373 +contexts, in particular the use of the eglSwapBuffers function. As stated in the
   1.374 +documentation for the function "The contents of ancillary buffers are always 
   1.375 +undefined after calling eglSwapBuffers".
   1.376 +Setting the EGL_SWAP_BEHAVIOR attribute of the surface to EGL_BUFFER_PRESERVED
   1.377 +is not possible for SDL as it requires EGL 1.4, available only on the API level
   1.378 +17+, so the only workaround available on this platform is to redraw the entire
   1.379 +screen each frame.
   1.380 +
   1.381 +Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html
   1.382 +
   1.383 +================================================================================
   1.384 + Known issues
   1.385 +================================================================================
   1.386 +
   1.387 +- TODO. I'm sure there's a bunch more stuff I haven't thought of