From 69a41fadaa3465a32eee38f4d43f8776998cc5d6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 6 Jan 2011 17:12:31 -0800 Subject: [PATCH] Added the Android project and lots of info to README.android --- README.android | 68 ++- android-project/AndroidManifest.xml | 15 + android-project/build.properties | 17 + android-project/build.xml | 67 +++ android-project/default.properties | 11 + android-project/jni/Android.mk | 1 + android-project/jni/src/Android.mk | 19 + android-project/local.properties | 10 + android-project/res/drawable-hdpi/icon.png | Bin 0 -> 4147 bytes android-project/res/drawable-ldpi/icon.png | Bin 0 -> 1723 bytes android-project/res/drawable-mdpi/icon.png | Bin 0 -> 2574 bytes android-project/res/layout/main.xml | 13 + android-project/res/values/strings.xml | 4 + .../src/org/libsdl/app/SDLActivity.java | 389 ++++++++++++++++++ 14 files changed, 608 insertions(+), 6 deletions(-) create mode 100644 android-project/AndroidManifest.xml create mode 100644 android-project/build.properties create mode 100644 android-project/build.xml create mode 100644 android-project/default.properties create mode 100644 android-project/jni/Android.mk create mode 100644 android-project/jni/src/Android.mk create mode 100644 android-project/local.properties create mode 100644 android-project/res/drawable-hdpi/icon.png create mode 100644 android-project/res/drawable-ldpi/icon.png create mode 100644 android-project/res/drawable-mdpi/icon.png create mode 100644 android-project/res/layout/main.xml create mode 100644 android-project/res/values/strings.xml create mode 100644 android-project/src/org/libsdl/app/SDLActivity.java diff --git a/README.android b/README.android index dade7eea7..23458bd2f 100644 --- a/README.android +++ b/README.android @@ -2,8 +2,13 @@ Simple DirectMedia Layer for Android ================================================================================ -Requirements: Android SDK and Android NDK r4 or later -http://developer.android.com/ +Requirements: + +Android SDK +http://developer.android.com/sdk/index.html + +Android NDK r4 or later +http://developer.android.com/sdk/ndk/index.html ================================================================================ How the port works @@ -22,7 +27,7 @@ Java project, along with some C support code that communicates with Java ================================================================================ Instructions: -1. Copy the android-project directory wherever you want your Android project to go +1. Copy the android-project directory wherever you want to keep your projects and rename it to the name of your project. 2. Move this SDL directory into the /jni directory 3. Place your application source files in the /jni/src directory 4. Edit /jni/src/Android.mk to include your source files @@ -35,16 +40,54 @@ If you want to use the Eclipse IDE, skip to the Eclipse section below. creates a .apk with the native code embedded 8. 'ant 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, do not modify + build.properties - empty + build.xml - build description file, used by ant + default.properties - holds the ABI for the application, currently android-4 which corresponds to the Android 1.6 system image + local.properties - holds the SDK path, you should change this to the path to your SDK + jni/ - directory holding native code and Android.mk + jni/Android.mk - Android makefile that includes all subdirectories + jni/SDL/ - directory holding the SDL library files + jni/SDL/Android.mk - Android makefile for creating the SDL shared library + jni/src/ - directory holding your application 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 + res/layout/main.xml - place holder for the main screen layout, overridden by 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. + + +================================================================================ + 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 ================================================================================ -NEED CONTENT +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 1.6 + * Click Finish ================================================================================ - Loading files + Loading files and resources ================================================================================ NEED CONTENT @@ -54,7 +97,20 @@ NEED CONTENT Troubleshooting ================================================================================ -NEED CONTENT +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 ================================================================================ diff --git a/android-project/AndroidManifest.xml b/android-project/AndroidManifest.xml new file mode 100644 index 000000000..182232582 --- /dev/null +++ b/android-project/AndroidManifest.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/android-project/build.properties b/android-project/build.properties new file mode 100644 index 000000000..edc7f2305 --- /dev/null +++ b/android-project/build.properties @@ -0,0 +1,17 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked in Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + diff --git a/android-project/build.xml b/android-project/build.xml new file mode 100644 index 000000000..37b376807 --- /dev/null +++ b/android-project/build.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android-project/default.properties b/android-project/default.properties new file mode 100644 index 000000000..9d79b12c7 --- /dev/null +++ b/android-project/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-4 diff --git a/android-project/jni/Android.mk b/android-project/jni/Android.mk new file mode 100644 index 000000000..5053e7d64 --- /dev/null +++ b/android-project/jni/Android.mk @@ -0,0 +1 @@ +include $(call all-subdir-makefiles) diff --git a/android-project/jni/src/Android.mk b/android-project/jni/src/Android.mk new file mode 100644 index 000000000..5e6e48b08 --- /dev/null +++ b/android-project/jni/src/Android.mk @@ -0,0 +1,19 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := main + +SDL_PATH := ../SDL + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include + +# Add your application source files here... +LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.cpp \ + YourSourceHere.c + +LOCAL_SHARED_LIBRARIES := SDL + +LOCAL_LDLIBS := -lGLESv1_CM -llog + +include $(BUILD_SHARED_LIBRARY) diff --git a/android-project/local.properties b/android-project/local.properties new file mode 100644 index 000000000..2818bb832 --- /dev/null +++ b/android-project/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=/Users/hercules/eclipse/android-sdk-mac_86 diff --git a/android-project/res/drawable-hdpi/icon.png b/android-project/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8074c4c571b8cd19e27f4ee5545df367420686d7 GIT binary patch literal 4147 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 literal 0 HcmV?d00001 diff --git a/android-project/res/drawable-ldpi/icon.png b/android-project/res/drawable-ldpi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1095584ec21f71cd0afc9e0993aa2209671b590c GIT binary patch literal 1723 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 + + + + diff --git a/android-project/res/values/strings.xml b/android-project/res/values/strings.xml new file mode 100644 index 000000000..9bce51cb3 --- /dev/null +++ b/android-project/res/values/strings.xml @@ -0,0 +1,4 @@ + + + SDL App + diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java new file mode 100644 index 000000000..dff571f91 --- /dev/null +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -0,0 +1,389 @@ +package org.libsdl.app; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; +import javax.microedition.khronos.egl.*; + +import android.app.*; +import android.content.*; +import android.view.*; +import android.os.*; +import android.util.Log; +import android.graphics.*; +import android.text.method.*; +import android.text.*; +import android.media.*; +import android.hardware.*; +import android.content.*; + +import java.lang.*; + + +/** + SDL Activity +*/ +public class SDLActivity extends Activity { + + //Main components + private static SDLActivity mSingleton; + private static SDLSurface mSurface; + + //Audio + private static AudioTrack mAudioTrack; + private static boolean bAudioIsEnabled; + + //Sensors + private static boolean bAccelIsEnabled; + + //feature IDs. Must match up on the C side as well. + private static int FEATURE_AUDIO = 1; + private static int FEATURE_ACCEL = 2; + + //Load the .so + static { + System.loadLibrary("SDL"); + System.loadLibrary("main"); + } + + //Setup + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + //So we can call stuff from static callbacks + mSingleton = this; + + //Set up the surface + mSurface = new SDLSurface(getApplication()); + setContentView(mSurface); + SurfaceHolder holder = mSurface.getHolder(); + holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); + + } + + //Audio + public static boolean initAudio(){ + + //blah. Hardcoded things are bad. FIXME when we have more sound stuff + //working properly. + mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, + 11025, + AudioFormat.CHANNEL_CONFIGURATION_MONO, + AudioFormat.ENCODING_PCM_8BIT, + 2048, + AudioTrack.MODE_STREAM); + bAudioIsEnabled = true; + return true; + } + + //Accel + public static boolean initAccel(){ + mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true); + bAccelIsEnabled = true; + return true; + } + + public static boolean closeAccel(){ + mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, false); + bAccelIsEnabled = false; + return true; + } + + + //Events + protected void onPause() { + super.onPause(); + } + + protected void onResume() { + super.onResume(); + } + + + + + + //C functions we call + public static native void nativeInit(); + public static native void nativeQuit(); + public static native void nativeSetScreenSize(int width, int height); + public static native void onNativeKeyDown(int keycode); + public static native void onNativeKeyUp(int keycode); + public static native void onNativeTouch(int action, float x, + float y, float p); + public static native void onNativeResize(int x, int y, int format); + public static native void onNativeAccel(float x, float y, float z); + + + + //Java functions called from C + private static void createGLContext(){ + mSurface.initEGL(); + } + + public static void flipBuffers(){ + mSurface.flipEGL(); + } + + public static void updateAudio(byte [] buf){ + + if(mAudioTrack == null){ + return; + } + + mAudioTrack.write(buf, 0, buf.length); + mAudioTrack.play(); + + Log.v("SDL","Played some audio"); + } + + public static void enableFeature(int featureid, int enabled){ + Log.v("SDL","Feature " + featureid + " = " + enabled); + + //Yuck. This is all horribly inelegent. If it gets to more than a few + //'features' I'll rip this out and make something nicer, I promise :) + if(featureid == FEATURE_AUDIO){ + if(enabled == 1){ + initAudio(); + }else{ + //We don't have one of these yet... + //closeAudio(); + } + } + + else if(featureid == FEATURE_ACCEL){ + if(enabled == 1){ + initAccel(); + }else{ + closeAccel(); + } + } + } + + + + + + + +} + +/** + Simple nativeInit() runnable +*/ +class SDLRunner implements Runnable{ + public void run(){ + //SDLActivity.initAudio(); + + //Runs SDL_main() + SDLActivity.nativeInit(); + + Log.v("SDL","SDL thread terminated"); + } +} + + +/** + SDLSurface. This is what we draw on, so we need to know when it's created + in order to do anything useful. + + Because of this, that's where we set up the SDL thread +*/ +class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, + View.OnKeyListener, View.OnTouchListener, SensorEventListener { + + //This is what SDL runs in. It invokes SDL_main(), eventually + private Thread mSDLThread; + + //EGL private objects + private EGLContext mEGLContext; + private EGLSurface mEGLSurface; + private EGLDisplay mEGLDisplay; + + //Sensors + private static SensorManager mSensorManager; + + //Startup + public SDLSurface(Context context) { + super(context); + getHolder().addCallback(this); + + setFocusable(true); + setFocusableInTouchMode(true); + requestFocus(); + setOnKeyListener(this); + setOnTouchListener(this); + + mSensorManager = (SensorManager)context.getSystemService("sensor"); + } + + //Called when we have a valid drawing surface + public void surfaceCreated(SurfaceHolder holder) { + Log.v("SDL","Surface created"); + + int width = getWidth(); + int height = getHeight(); + + //Set the width and height variables in C before we start SDL so we have + //it available on init + SDLActivity.nativeSetScreenSize(width, height); + + //Now start up the C app thread + mSDLThread = new Thread(new SDLRunner(), "SDLThread"); + mSDLThread.start(); + } + + //Called when we lose the surface + public void surfaceDestroyed(SurfaceHolder holder) { + Log.v("SDL","Surface destroyed"); + + SDLActivity.nativeQuit(); + + //Now wait for the SDL thread to quit + try{ + mSDLThread.wait(); + }catch(Exception e){ + Log.v("SDL","Problem stopping thread: " + e); + } + } + + //Called when the surface is resized + public void surfaceChanged(SurfaceHolder holder, int format, + int width, int height) { + Log.v("SDL","Surface resized"); + + SDLActivity.onNativeResize(width, height, format); + } + + //unused + public void onDraw(Canvas canvas) {} + + + //EGL functions + public boolean initEGL(){ + Log.v("SDL","Starting up"); + + try{ + + EGL10 egl = (EGL10)EGLContext.getEGL(); + + EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + + int[] version = new int[2]; + egl.eglInitialize(dpy, version); + + int[] configSpec = { + //EGL10.EGL_DEPTH_SIZE, 16, + EGL10.EGL_NONE + }; + EGLConfig[] configs = new EGLConfig[1]; + int[] num_config = new int[1]; + egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config); + EGLConfig config = configs[0]; + + EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, null); + + EGLSurface surface = egl.eglCreateWindowSurface(dpy, config, this, null); + + egl.eglMakeCurrent(dpy, surface, surface, ctx); + + mEGLContext = ctx; + mEGLDisplay = dpy; + mEGLSurface = surface; + + + }catch(Exception e){ + Log.v("SDL", e + ""); + for(StackTraceElement s : e.getStackTrace()){ + Log.v("SDL", s.toString()); + } + } + Log.v("SDL","Done making!"); + + return true; + } + + //EGL buffer flip + public void flipEGL(){ + try{ + + EGL10 egl = (EGL10)EGLContext.getEGL(); + GL10 gl = (GL10)mEGLContext.getGL(); + + egl.eglWaitNative(EGL10.EGL_NATIVE_RENDERABLE, null); + + //drawing here + + egl.eglWaitGL(); + + egl.eglSwapBuffers(mEGLDisplay, mEGLSurface); + + + }catch(Exception e){ + Log.v("SDL", "flipEGL(): " + e); + + for(StackTraceElement s : e.getStackTrace()){ + Log.v("SDL", s.toString()); + } + } + } + + + + //Key events + public boolean onKey(View v, int keyCode, KeyEvent event){ + + if(event.getAction() == KeyEvent.ACTION_DOWN){ + SDLActivity.onNativeKeyDown(keyCode); + return true; + } + + else if(event.getAction() == KeyEvent.ACTION_UP){ + SDLActivity.onNativeKeyUp(keyCode); + return true; + } + + return false; + } + + //Touch events + public boolean onTouch(View v, MotionEvent event){ + + int action = event.getAction(); + float x = event.getX(); + float y = event.getY(); + float p = event.getPressure(); + + //TODO: Anything else we need to pass? + SDLActivity.onNativeTouch(action, x, y, p); + return true; + } + + //Sensor events + public void enableSensor(int sensortype, boolean enabled){ + //TODO: This uses getDefaultSensor - what if we have >1 accels? + if(enabled){ + mSensorManager.registerListener(this, + mSensorManager.getDefaultSensor(sensortype), + SensorManager.SENSOR_DELAY_GAME, null); + }else{ + mSensorManager.unregisterListener(this, + mSensorManager.getDefaultSensor(sensortype)); + } + } + + public void onAccuracyChanged(Sensor sensor, int accuracy){ + //TODO + } + + public void onSensorChanged(SensorEvent event){ + if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){ + SDLActivity.onNativeAccel( event.values[0], + event.values[1], + event.values[2] ); + } + } + + +} + +