comparison android-project/src/org/libsdl/app/SDLActivity.java @ 4965:91d0085b7560

Added the Android project and lots of info to README.android
author Sam Lantinga <slouken@libsdl.org>
date Thu, 06 Jan 2011 17:12:31 -0800
parents
children d9fdff945ec9
comparison
equal deleted inserted replaced
4964:6c645018741e 4965:91d0085b7560
1 package org.libsdl.app;
2
3 import javax.microedition.khronos.egl.EGLConfig;
4 import javax.microedition.khronos.opengles.GL10;
5 import javax.microedition.khronos.egl.*;
6
7 import android.app.*;
8 import android.content.*;
9 import android.view.*;
10 import android.os.*;
11 import android.util.Log;
12 import android.graphics.*;
13 import android.text.method.*;
14 import android.text.*;
15 import android.media.*;
16 import android.hardware.*;
17 import android.content.*;
18
19 import java.lang.*;
20
21
22 /**
23 SDL Activity
24 */
25 public class SDLActivity extends Activity {
26
27 //Main components
28 private static SDLActivity mSingleton;
29 private static SDLSurface mSurface;
30
31 //Audio
32 private static AudioTrack mAudioTrack;
33 private static boolean bAudioIsEnabled;
34
35 //Sensors
36 private static boolean bAccelIsEnabled;
37
38 //feature IDs. Must match up on the C side as well.
39 private static int FEATURE_AUDIO = 1;
40 private static int FEATURE_ACCEL = 2;
41
42 //Load the .so
43 static {
44 System.loadLibrary("SDL");
45 System.loadLibrary("main");
46 }
47
48 //Setup
49 protected void onCreate(Bundle savedInstanceState) {
50 super.onCreate(savedInstanceState);
51
52 //So we can call stuff from static callbacks
53 mSingleton = this;
54
55 //Set up the surface
56 mSurface = new SDLSurface(getApplication());
57 setContentView(mSurface);
58 SurfaceHolder holder = mSurface.getHolder();
59 holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
60
61 }
62
63 //Audio
64 public static boolean initAudio(){
65
66 //blah. Hardcoded things are bad. FIXME when we have more sound stuff
67 //working properly.
68 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
69 11025,
70 AudioFormat.CHANNEL_CONFIGURATION_MONO,
71 AudioFormat.ENCODING_PCM_8BIT,
72 2048,
73 AudioTrack.MODE_STREAM);
74 bAudioIsEnabled = true;
75 return true;
76 }
77
78 //Accel
79 public static boolean initAccel(){
80 mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true);
81 bAccelIsEnabled = true;
82 return true;
83 }
84
85 public static boolean closeAccel(){
86 mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, false);
87 bAccelIsEnabled = false;
88 return true;
89 }
90
91
92 //Events
93 protected void onPause() {
94 super.onPause();
95 }
96
97 protected void onResume() {
98 super.onResume();
99 }
100
101
102
103
104
105 //C functions we call
106 public static native void nativeInit();
107 public static native void nativeQuit();
108 public static native void nativeSetScreenSize(int width, int height);
109 public static native void onNativeKeyDown(int keycode);
110 public static native void onNativeKeyUp(int keycode);
111 public static native void onNativeTouch(int action, float x,
112 float y, float p);
113 public static native void onNativeResize(int x, int y, int format);
114 public static native void onNativeAccel(float x, float y, float z);
115
116
117
118 //Java functions called from C
119 private static void createGLContext(){
120 mSurface.initEGL();
121 }
122
123 public static void flipBuffers(){
124 mSurface.flipEGL();
125 }
126
127 public static void updateAudio(byte [] buf){
128
129 if(mAudioTrack == null){
130 return;
131 }
132
133 mAudioTrack.write(buf, 0, buf.length);
134 mAudioTrack.play();
135
136 Log.v("SDL","Played some audio");
137 }
138
139 public static void enableFeature(int featureid, int enabled){
140 Log.v("SDL","Feature " + featureid + " = " + enabled);
141
142 //Yuck. This is all horribly inelegent. If it gets to more than a few
143 //'features' I'll rip this out and make something nicer, I promise :)
144 if(featureid == FEATURE_AUDIO){
145 if(enabled == 1){
146 initAudio();
147 }else{
148 //We don't have one of these yet...
149 //closeAudio();
150 }
151 }
152
153 else if(featureid == FEATURE_ACCEL){
154 if(enabled == 1){
155 initAccel();
156 }else{
157 closeAccel();
158 }
159 }
160 }
161
162
163
164
165
166
167
168 }
169
170 /**
171 Simple nativeInit() runnable
172 */
173 class SDLRunner implements Runnable{
174 public void run(){
175 //SDLActivity.initAudio();
176
177 //Runs SDL_main()
178 SDLActivity.nativeInit();
179
180 Log.v("SDL","SDL thread terminated");
181 }
182 }
183
184
185 /**
186 SDLSurface. This is what we draw on, so we need to know when it's created
187 in order to do anything useful.
188
189 Because of this, that's where we set up the SDL thread
190 */
191 class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
192 View.OnKeyListener, View.OnTouchListener, SensorEventListener {
193
194 //This is what SDL runs in. It invokes SDL_main(), eventually
195 private Thread mSDLThread;
196
197 //EGL private objects
198 private EGLContext mEGLContext;
199 private EGLSurface mEGLSurface;
200 private EGLDisplay mEGLDisplay;
201
202 //Sensors
203 private static SensorManager mSensorManager;
204
205 //Startup
206 public SDLSurface(Context context) {
207 super(context);
208 getHolder().addCallback(this);
209
210 setFocusable(true);
211 setFocusableInTouchMode(true);
212 requestFocus();
213 setOnKeyListener(this);
214 setOnTouchListener(this);
215
216 mSensorManager = (SensorManager)context.getSystemService("sensor");
217 }
218
219 //Called when we have a valid drawing surface
220 public void surfaceCreated(SurfaceHolder holder) {
221 Log.v("SDL","Surface created");
222
223 int width = getWidth();
224 int height = getHeight();
225
226 //Set the width and height variables in C before we start SDL so we have
227 //it available on init
228 SDLActivity.nativeSetScreenSize(width, height);
229
230 //Now start up the C app thread
231 mSDLThread = new Thread(new SDLRunner(), "SDLThread");
232 mSDLThread.start();
233 }
234
235 //Called when we lose the surface
236 public void surfaceDestroyed(SurfaceHolder holder) {
237 Log.v("SDL","Surface destroyed");
238
239 SDLActivity.nativeQuit();
240
241 //Now wait for the SDL thread to quit
242 try{
243 mSDLThread.wait();
244 }catch(Exception e){
245 Log.v("SDL","Problem stopping thread: " + e);
246 }
247 }
248
249 //Called when the surface is resized
250 public void surfaceChanged(SurfaceHolder holder, int format,
251 int width, int height) {
252 Log.v("SDL","Surface resized");
253
254 SDLActivity.onNativeResize(width, height, format);
255 }
256
257 //unused
258 public void onDraw(Canvas canvas) {}
259
260
261 //EGL functions
262 public boolean initEGL(){
263 Log.v("SDL","Starting up");
264
265 try{
266
267 EGL10 egl = (EGL10)EGLContext.getEGL();
268
269 EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
270
271 int[] version = new int[2];
272 egl.eglInitialize(dpy, version);
273
274 int[] configSpec = {
275 //EGL10.EGL_DEPTH_SIZE, 16,
276 EGL10.EGL_NONE
277 };
278 EGLConfig[] configs = new EGLConfig[1];
279 int[] num_config = new int[1];
280 egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config);
281 EGLConfig config = configs[0];
282
283 EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, null);
284
285 EGLSurface surface = egl.eglCreateWindowSurface(dpy, config, this, null);
286
287 egl.eglMakeCurrent(dpy, surface, surface, ctx);
288
289 mEGLContext = ctx;
290 mEGLDisplay = dpy;
291 mEGLSurface = surface;
292
293
294 }catch(Exception e){
295 Log.v("SDL", e + "");
296 for(StackTraceElement s : e.getStackTrace()){
297 Log.v("SDL", s.toString());
298 }
299 }
300 Log.v("SDL","Done making!");
301
302 return true;
303 }
304
305 //EGL buffer flip
306 public void flipEGL(){
307 try{
308
309 EGL10 egl = (EGL10)EGLContext.getEGL();
310 GL10 gl = (GL10)mEGLContext.getGL();
311
312 egl.eglWaitNative(EGL10.EGL_NATIVE_RENDERABLE, null);
313
314 //drawing here
315
316 egl.eglWaitGL();
317
318 egl.eglSwapBuffers(mEGLDisplay, mEGLSurface);
319
320
321 }catch(Exception e){
322 Log.v("SDL", "flipEGL(): " + e);
323
324 for(StackTraceElement s : e.getStackTrace()){
325 Log.v("SDL", s.toString());
326 }
327 }
328 }
329
330
331
332 //Key events
333 public boolean onKey(View v, int keyCode, KeyEvent event){
334
335 if(event.getAction() == KeyEvent.ACTION_DOWN){
336 SDLActivity.onNativeKeyDown(keyCode);
337 return true;
338 }
339
340 else if(event.getAction() == KeyEvent.ACTION_UP){
341 SDLActivity.onNativeKeyUp(keyCode);
342 return true;
343 }
344
345 return false;
346 }
347
348 //Touch events
349 public boolean onTouch(View v, MotionEvent event){
350
351 int action = event.getAction();
352 float x = event.getX();
353 float y = event.getY();
354 float p = event.getPressure();
355
356 //TODO: Anything else we need to pass?
357 SDLActivity.onNativeTouch(action, x, y, p);
358 return true;
359 }
360
361 //Sensor events
362 public void enableSensor(int sensortype, boolean enabled){
363 //TODO: This uses getDefaultSensor - what if we have >1 accels?
364 if(enabled){
365 mSensorManager.registerListener(this,
366 mSensorManager.getDefaultSensor(sensortype),
367 SensorManager.SENSOR_DELAY_GAME, null);
368 }else{
369 mSensorManager.unregisterListener(this,
370 mSensorManager.getDefaultSensor(sensortype));
371 }
372 }
373
374 public void onAccuracyChanged(Sensor sensor, int accuracy){
375 //TODO
376 }
377
378 public void onSensorChanged(SensorEvent event){
379 if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
380 SDLActivity.onNativeAccel( event.values[0],
381 event.values[1],
382 event.values[2] );
383 }
384 }
385
386
387 }
388
389