Skip to content
This repository has been archived by the owner. It is now read-only.
Browse files


- Moved to 'project' instead of 'testproject'
- Removed extraneous .c files
- Removed the android_libs folder (that was against the NDK agreement anyway)
  • Loading branch information
bieh committed Aug 17, 2010
1 parent bbc81c7 commit 19fd0a0bded05798b26d4a94519d7d18d7b5ce92
@@ -1,5 +1,5 @@
Building the Simple DirectMedia Layer for Android
Simple DirectMedia Layer for Android

Requirements: Android NDK r4 or later
@@ -11,6 +11,6 @@ Instructions:
4. Run 'ndk-build' (a script provided by the NDK). This compiles the C source
4. Run 'ant' in android/testproject. This compiles the .java and eventually
creates a .apk with the C source embedded
6. 'ant install' will push the apk to the device
6. 'ant install' will push the apk to the device or emulator (if connected)

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=""
<application android:label="@string/app_name" android:icon="@drawable/icon">
<activity android:name="SDLActivity"
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -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:
# '' 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.

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="SDLApp" default="help">

<!-- The file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked in in Version
Control Systems. -->
<property file="" />

<!-- The file can be created by you and is never touched
by the 'android' tool. This is the place to change some of the default property values
used by the Ant rules.
Here are some properties you may want to change/update:
the name of your application package as defined in the manifest. Used by the
'uninstall' rule.
the name of the source directory. Default is 'src'.
the name of the output directory. Default is 'bin'.
Properties related to the SDK location or the project target should be updated
using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your application and
should be checked in in Version Control Systems.
<property file="" />

<!-- The file is created and updated by the 'android' tool, as well
as ADT.
This file is an integral part of the build system for your application and
should be checked in in Version Control Systems. -->
<property file="" />

<!-- Custom Android task to deal with the project target, and import the proper rules.
This requires ant 1.6.0 or above. -->
<path id="android.antlibs">
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
<pathelement path="${sdk.dir}/tools/lib/apkbuilder.jar" />
<pathelement path="${sdk.dir}/tools/lib/jarutils.jar" />

<taskdef name="setup"
classpathref="android.antlibs" />

<!-- Execute the Android Setup task that will setup some properties specific to the target,
and import the build rules files.
The rules file is imported from
To customize some build steps for your project:
- copy the content of the main node <project> from android_rules.xml
- paste it in this build.xml below the <setup /> task.
- disable the import by changing the setup task below to <setup import="false" />
This will ensure that the properties are setup correctly but that your customized
build steps are used.
<setup />

@@ -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,
# "", and override values to adapt the script to your
# project structure.

# Project target.
@@ -0,0 +1,18 @@
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := sdlapp
SDL := ../../../


android-support.cpp \
lesson05.c \

LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog -lSDL -lgcc -L$(SDL)

@@ -0,0 +1,242 @@
This file links the Java side of Android with libsdl
#include <jni.h>
#include <sys/time.h>
#include <time.h>
#include <android/log.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>

#define DEBUG

static long _getTime(void){
struct timeval now;
gettimeofday(&now, NULL);
return (long)(now.tv_sec*1000 + now.tv_usec/1000);

JNIEnv* mEnv = NULL;
JNIEnv* mAudioThreadEnv = NULL; //See the note below for why this is necessary
JavaVM* mVM = NULL;

//Main activity
jclass mActivityInstance;

//method signatures
jmethodID midCreateGLContext;
jmethodID midFlipBuffers;
jmethodID midEnableFeature;
jmethodID midUpdateAudio;

extern "C" int SDL_main();
extern "C" int Android_OnKeyDown(int keycode);
extern "C" int Android_OnKeyUp(int keycode);
extern "C" void Android_SetScreenResolution(int width, int height);
extern "C" void Android_OnResize(int width, int height, int format);
extern "C" int SDL_SendQuit();
extern "C" void Android_EnableFeature(int featureid, bool enabled);

//If we're not the active app, don't try to render
bool bRenderingEnabled = false;

//Feature IDs
static const int FEATURE_AUDIO = 1;
static const int FEATURE_ACCEL = 2;

//Accelerometer data storage
float fLastAccelerometer[3];

Functions called by JNI

//Library init
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved){

JNIEnv* env = NULL;
jint result = -1;

if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return result;

mEnv = env;

__android_log_print(ANDROID_LOG_INFO, "SDL", "JNI: OnLoad");

jclass cls = mEnv->FindClass ("org/libsdl/app/SDLActivity");
mActivityInstance = cls;
midCreateGLContext = mEnv->GetStaticMethodID(cls,"createGLContext","()V");
midFlipBuffers = mEnv->GetStaticMethodID(cls,"flipBuffers","()V");
midEnableFeature = mEnv->GetStaticMethodID(cls,"enableFeature","(II)V");
midUpdateAudio = mEnv->GetStaticMethodID(cls,"updateAudio","([B)V");

if(!midCreateGLContext || !midFlipBuffers || !midEnableFeature ||
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Bad mids\n");
#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Good mids\n");

return JNI_VERSION_1_4;

//Start up the SDL app
extern "C" void Java_org_libsdl_app_SDLActivity_nativeInit( JNIEnv* env,
jobject obj ){

__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Native Init");

mEnv = env;
bRenderingEnabled = true;

Android_EnableFeature(FEATURE_ACCEL, true);


extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(JNIEnv* env,
jobject obj, jint keycode){

int r = Android_OnKeyDown(keycode);
#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL",
"SDL: native key down %d, %d\n", keycode, r);


extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(JNIEnv* env,
jobject obj, jint keycode){

int r = Android_OnKeyUp(keycode);
#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL",
"SDL: native key up %d, %d\n", keycode, r);


extern "C" void Java_org_libsdl_app_SDLActivity_onNativeTouch(JNIEnv* env,
jobject obj, jint action, jfloat x, jfloat y, jfloat p){

#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL",
"SDL: native touch event %d @ %f/%f, pressure %f\n",
action, x, y, p);

//TODO: Pass this off to the SDL multitouch stuff


extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit( JNIEnv* env,
jobject obj ){

//Stop rendering as we're no longer in the foreground
bRenderingEnabled = false;

//Inject a SDL_QUIT event
int r = SDL_SendQuit();

__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Native quit %d", r);

//Screen size
extern "C" void Java_org_libsdl_app_SDLActivity_nativeSetScreenSize(
JNIEnv* env, jobject obj, jint width, jint height){

__android_log_print(ANDROID_LOG_INFO, "SDL",
"SDL: Set screen size on init: %d/%d\n", width, height);
Android_SetScreenResolution(width, height);


extern "C" void Java_org_libsdl_app_SDLActivity_onNativeResize(
JNIEnv* env, jobject obj, jint width,
jint height, jint format){
Android_OnResize(width, height, format);

extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel(
JNIEnv* env, jobject obj,
jfloat x, jfloat y, jfloat z){
fLastAccelerometer[0] = x;
fLastAccelerometer[1] = y;
fLastAccelerometer[2] = z;

Functions called by SDL into Java
extern "C" void Android_CreateContext(){
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: sdl_create_context()\n");

bRenderingEnabled = true;

mEnv->CallStaticVoidMethod(mActivityInstance, midCreateGLContext );

extern "C" void Android_Render(){


//When we get here, we've accumulated a full frame
mEnv->CallStaticVoidMethod(mActivityInstance, midFlipBuffers );

extern "C" void Android_EnableFeature(int featureid, bool enabled){

mEnv->CallStaticVoidMethod(mActivityInstance, midEnableFeature,
featureid, (int)enabled);

extern "C" void Android_UpdateAudioBuffer(unsigned char *buf, int len){

//Annoyingly we can't just call into Java from any thread. Because the audio
//callback is dispatched from the SDL audio thread (that wasn't made from
//java, we have to do some magic here to let the JVM know about the thread.
//Because everything it touches on the Java side is static anyway, it's
//not a big deal, just annoying.
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Need to set up audio thread env\n");

mVM->AttachCurrentThread(&mAudioThreadEnv, NULL);

__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: ok\n");

jbyteArray arr = mAudioThreadEnv->NewByteArray(len);

//blah. We probably should rework this so we avoid the copy.
mAudioThreadEnv->SetByteArrayRegion(arr, 0, len, (jbyte *)buf);

__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: copied\n");

mAudioThreadEnv->CallStaticVoidMethod( mActivityInstance,
midUpdateAudio, arr );

__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: invoked\n");


0 comments on commit 19fd0a0

Please sign in to comment.