README-android.txt
changeset 7222 2435b221d77d
parent 7166 8d17ec58f019
child 7241 28602f5ca96d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README-android.txt	Sun May 26 11:06:17 2013 -0700
@@ -0,0 +1,384 @@
+================================================================================
+Simple DirectMedia Layer for Android
+================================================================================
+
+Requirements:
+
+Android SDK (version 10 or later)
+http://developer.android.com/sdk/index.html
+
+Android NDK r7 or later
+http://developer.android.com/sdk/ndk/index.html
+
+inimum API level supported by SDL: 10 (Android 2.3.3)
+
+================================================================================
+ How the port works
+================================================================================
+
+- Android applications are Java-based, optionally with parts written in C
+- As SDL apps are C-based, we use a small Java shim that uses JNI to talk to 
+the SDL library
+- This means that your application C code must be placed inside an Android 
+Java project, along with some C support code that communicates with Java
+- This eventually produces a standard Android .apk package
+
+The Android Java code implements an "Activity" and can be found in:
+android-project/src/org/libsdl/app/SDLActivity.java
+
+The Java code loads your game code, the SDL shared library, and
+dispatches to native functions implemented in the SDL library:
+src/SDL_android.cpp
+
+Your project must include some glue code that starts your main() routine:
+src/main/android/SDL_android_main.cpp
+
+
+================================================================================
+ Building an app
+================================================================================
+
+Instructions:
+1. Copy the android-project directory wherever you want to keep your projects
+   and rename it to the name of your project.
+2. Move or symlink this SDL directory into the <project>/jni directory
+3. Edit <project>/jni/src/Android.mk to include your source files
+4. Run 'ndk-build' (a script provided by the NDK). This compiles the C source
+
+If you want to use the Eclipse IDE, skip to the Eclipse section below.
+
+5. Create <project>/local.properties and use that to point to the Android SDK directory, by writing a line with the following form:
+sdk.dir=PATH_TO_ANDROID_SDK
+6. Run 'ant debug' in android/project. This compiles the .java and eventually 
+   creates a .apk with the native code embedded
+7. 'ant debug install' will push the apk to the device or emulator (if connected)
+
+Here's an explanation of the files in the Android project, so you can customize them:
+
+android-project/
+	AndroidManifest.xml	- package manifest. Among others, it contains the class name
+				  of the main Activity and the package name of the application.
+	build.properties	- empty
+	build.xml		- build description file, used by ant. The actual application name
+				  is specified here.
+	default.properties	- holds the target ABI for the application, android-10 and up
+	project.properties	- holds the target ABI for the application, android-10 and up
+	local.properties	- holds the SDK path, you should change this to the path to your SDK
+	jni/			- directory holding native code
+	jni/Android.mk		- Android makefile that can call recursively the Android.mk files
+				  in all subdirectories
+	jni/SDL/		- (symlink to) directory holding the SDL library files
+	jni/SDL/Android.mk	- Android makefile for creating the SDL shared library
+	jni/src/		- directory holding your C/C++ source
+	jni/src/Android.mk	- Android makefile that you should customize to include your 
+                                  source code and any library references
+	res/			- directory holding resources for your application
+	res/drawable-*		- directories holding icons for different phone hardware. Could be
+				  one dir called "drawable".
+	res/layout/main.xml	- Usually contains a file main.xml, which declares the screen layout.
+				  We don't need it because we use the SDL video output.
+	res/values/strings.xml	- strings used in your application, including the application name
+				  shown on the phone.
+	src/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.
+
+
+================================================================================
+ Customizing your application name
+================================================================================
+
+To customize your application name, edit AndroidManifest.xml and replace
+"org.libsdl.app" with an identifier for your product package.
+
+Then create a Java class extending SDLActivity and place it in a directory
+under src matching your package, e.g.
+	src/com/gamemaker/game/MyGame.java
+
+Here's an example of a minimal class file:
+--- MyGame.java --------------------------
+package com.gamemaker.game;
+
+import org.libsdl.app.SDLActivity; 
+
+/* 
+ * A sample wrapper class that just calls SDLActivity 
+ */ 
+
+public class MyGame extends SDLActivity { }
+
+------------------------------------------
+
+Then replace "SDLActivity" in AndroidManifest.xml with the name of your
+class, .e.g. "MyGame"
+
+================================================================================
+ Customizing your application icon
+================================================================================
+
+Conceptually changing your icon is just replacing the "ic_launcher.png" files in
+the drawable directories under the res directory. There are four directories for
+different screen sizes. These can be replaced with one dir called "drawable",
+containing an icon file "ic_launcher.png" with dimensions 48x48 or 72x72.
+
+You may need to change the name of your icon in AndroidManifest.xml to match
+this icon filename.
+
+================================================================================
+ Loading assets
+================================================================================
+
+Any files you put in the "assets" directory of your android-project directory
+will get bundled into the application package and you can load them using the
+standard functions in SDL_rwops.h.
+
+There are also a few Android specific functions that allow you to get other
+useful paths for saving and loading data:
+SDL_AndroidGetInternalStoragePath()
+SDL_AndroidGetExternalStorageState()
+SDL_AndroidGetExternalStoragePath()
+
+See SDL_system.h for more details on these functions.
+
+The asset packaging system will, by default, compress certain file extensions.
+SDL includes two asset file access mechanisms, the preferred one is the so
+called "File Descriptor" method, which is faster and doesn't involve the Dalvik
+GC, but given this method does not work on compressed assets, there is also the
+"Input Stream" method, which is automatically used as a fall back by SDL. You
+may want to keep this fact in mind when building your APK, specially when large
+files are involved.
+For more information on which extensions get compressed by default and how to
+disable this behaviour, see for example:
+    
+http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/
+
+================================================================================
+ Pause / Resume behaviour
+================================================================================
+
+If SDL is compiled with SDL_ANDROID_BLOCK_ON_PAUSE defined (the default),
+the event loop will block itself when the app is paused (ie, when the user
+returns to the main Android dashboard). Blocking is better in terms of battery
+use, and it allows your app to spring back to life instantaneously after resume
+(versus polling for a resume message).
+
+Upon resume, SDL will attempt to restore the GL context automatically.
+In modern devices (Android 3.0 and up) this will most likely succeed and your
+app can continue to operate as it was.
+
+However, there's a chance (on older hardware, or on systems under heavy load),
+where the GL context can not be restored. In that case you have to listen for
+a specific message, (which is not yet implemented!) and restore your textures
+manually or quit the app (which is actually the kind of behaviour you'll see
+under iOS, if the OS can not restore your GL context it will just kill your app)
+
+================================================================================
+ Threads and the Java VM
+================================================================================
+
+For a quick tour on how Linux native threads interoperate with the Java VM, take
+a look here: http://developer.android.com/guide/practices/jni.html
+If you want to use threads in your SDL app, it's strongly recommended that you
+do so by creating them using SDL functions. This way, the required attach/detach
+handling is managed by SDL automagically. If you have threads created by other
+means and they make calls to SDL functions, make sure that you call
+Android_JNI_SetupThread before doing anything else otherwise SDL will attach
+your thread automatically anyway (when you make an SDL call), but it'll never
+detach it.
+
+================================================================================
+ Using STL
+================================================================================
+
+You can use STL in your project by creating an Application.mk file in the jni
+folder and adding the following line:
+APP_STL := stlport_static
+
+For more information check out CPLUSPLUS-SUPPORT.html in the NDK documentation.
+
+================================================================================
+ Additional documentation
+================================================================================
+
+The documentation in the NDK docs directory is very helpful in understanding the
+build process and how to work with native code on the Android platform.
+
+The best place to start is with docs/OVERVIEW.TXT
+
+
+================================================================================
+ Using Eclipse
+================================================================================
+
+First make sure that you've installed Eclipse and the Android extensions as described here:
+	http://developer.android.com/sdk/eclipse-adt.html
+
+Once you've copied the SDL android project and customized it, you can create an Eclipse project from it:
+ * File -> New -> Other
+ * Select the Android -> Android Project wizard and click Next
+ * Enter the name you'd like your project to have
+ * Select "Create project from existing source" and browse for your project directory
+ * Make sure the Build Target is set to Android 2.0
+ * Click Finish
+
+
+================================================================================
+ Using the emulator
+================================================================================
+
+There are some good tips and tricks for getting the most out of the
+emulator here: http://developer.android.com/tools/devices/emulator.html
+
+Especially useful is the info on setting up OpenGL ES 2.0 emulation.
+
+Notice that this software emulator is incredibly slow and needs a lot of disk space.
+Using a real device works better.
+
+================================================================================
+ Troubleshooting
+================================================================================
+
+You can create and run an emulator from the Eclipse IDE:
+ * Window -> Android SDK and AVD Manager
+
+You can see if adb can see any devices with the following command:
+	adb devices
+
+You can see the output of log messages on the default device with:
+	adb logcat
+
+You can push files to the device with:
+	adb push local_file remote_path_and_file
+
+You can push files to the SD Card at /sdcard, for example:
+	adb push moose.dat /sdcard/moose.dat
+
+You can see the files on the SD card with a shell command:
+	adb shell ls /sdcard/
+
+You can start a command shell on the default device with:
+	adb shell
+
+You can remove the library files of your project (and not the SDL lib files) with:
+	ndk-build clean
+
+You can do a build with the following command:
+	ndk-build
+
+You can see the complete command line that ndk-build is using by passing V=1 on the command line:
+	ndk-build V=1
+
+If your application crashes in native code, you can use addr2line to convert the
+addresses in the stack trace to lines in your code.
+
+For example, if your crash looks like this:
+I/DEBUG   (   31): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 400085d0
+I/DEBUG   (   31):  r0 00000000  r1 00001000  r2 00000003  r3 400085d4
+I/DEBUG   (   31):  r4 400085d0  r5 40008000  r6 afd41504  r7 436c6a7c
+I/DEBUG   (   31):  r8 436c6b30  r9 435c6fb0  10 435c6f9c  fp 4168d82c
+I/DEBUG   (   31):  ip 8346aff0  sp 436c6a60  lr afd1c8ff  pc afd1c902  cpsr 60000030
+I/DEBUG   (   31):          #00  pc 0001c902  /system/lib/libc.so
+I/DEBUG   (   31):          #01  pc 0001ccf6  /system/lib/libc.so
+I/DEBUG   (   31):          #02  pc 000014bc  /data/data/org.libsdl.app/lib/libmain.so
+I/DEBUG   (   31):          #03  pc 00001506  /data/data/org.libsdl.app/lib/libmain.so
+
+You can see that there's a crash in the C library being called from the main code.
+I run addr2line with the debug version of my code:
+	arm-eabi-addr2line -C -f -e obj/local/armeabi/libmain.so
+and then paste in the number after "pc" in the call stack, from the line that I care about:
+000014bc
+
+I get output from addr2line showing that it's in the quit function, in testspriteminimal.c, on line 23.
+
+You can add logging to your code to help show what's happening:
+
+#include <android/log.h>
+
+	__android_log_print(ANDROID_LOG_INFO, "foo", "Something happened! x = %d", x);
+
+If you need to build without optimization turned on, you can create a file called
+"Application.mk" in the jni directory, with the following line in it:
+APP_OPTIM := debug
+
+
+================================================================================
+ Memory debugging
+================================================================================
+
+The best (and slowest) way to debug memory issues on Android is valgrind.
+Valgrind has support for Android out of the box, just grab code using:
+	svn co svn://svn.valgrind.org/valgrind/trunk valgrind
+... and follow the instructions in the file README.android to build it.
+
+One thing I needed to do on Mac OS X was change the path to the toolchain,
+and add ranlib to the environment variables:
+export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-ranlib
+
+Once valgrind is built, you can create a wrapper script to launch your
+application with it, changing org.libsdl.app to your package identifier:
+--- start_valgrind_app -------------------
+#!/system/bin/sh
+export TMPDIR=/data/data/org.libsdl.app
+exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $*
+------------------------------------------
+
+Then push it to the device:
+	adb push start_valgrind_app /data/local
+
+and make it executable:
+	adb shell chmod 755 /data/local/start_valgrind_app
+
+and tell Android to use the script to launch your application:
+	adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app"
+
+If the setprop command says "could not set property", it's likely that
+your package name is too long and you should make it shorter by changing
+AndroidManifest.xml and the path to your class file in android-project/src
+
+You can then launch your application normally and waaaaaaaiiittt for it.
+You can monitor the startup process with the logcat command above, and
+when it's done (or even while it's running) you can grab the valgrind
+output file:
+	adb pull /sdcard/valgrind.log
+
+When you're done instrumenting with valgrind, you can disable the wrapper:
+	adb shell setprop wrap.org.libsdl.app ""
+
+================================================================================
+ Why is API level 10 the minimum required?
+================================================================================
+
+API level 10 is required because SDL requires some functionality for running not
+available on older devices and some for building which is not in older NDK/SDKs.
+
+Support for native OpenGL ES and ES2 applications was introduced in the NDK for
+API level 4 and 8. EGL was made a stable API in the NDK for API level 9, which
+has since then been obsoleted, with the recommendation to developers to bump the
+required API level to 10.
+As of this writing, according to http://developer.android.com/about/dashboards/index.html
+about 90% of the Android devices accessing Google Play support API level 10 or
+higher (March 2013).
+
+================================================================================
+ A note regarding the use of the "dirty rectangles" rendering technique
+================================================================================
+
+If your app uses a variation of the "dirty rectangles" rendering technique,
+where you only update a portion of the screen on each frame, you may notice a
+variety of visual glitches on Android, that are not present on other platforms.
+This is caused by SDL's use of EGL as the support system to handle OpenGL ES/ES2
+contexts, in particular the use of the eglSwapBuffers function. As stated in the
+documentation for the function "The contents of ancillary buffers are always 
+undefined after calling eglSwapBuffers".
+Setting the EGL_SWAP_BEHAVIOR attribute of the surface to EGL_BUFFER_PRESERVED
+is not possible for SDL as it requires EGL 1.4, available only on the API level
+17+, so the only workaround available on this platform is to redraw the entire
+screen each frame.
+
+Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html
+
+================================================================================
+ Known issues
+================================================================================
+
+- TODO. I'm sure there's a bunch more stuff I haven't thought of