diff --git a/engine/src/android/com/jme3/app/AndroidHarness.java b/engine/src/android/com/jme3/app/AndroidHarness.java index d8b0c9a03..3071cedf6 100644 --- a/engine/src/android/com/jme3/app/AndroidHarness.java +++ b/engine/src/android/com/jme3/app/AndroidHarness.java @@ -1,27 +1,39 @@ package com.jme3.app; +import java.util.logging.Logger; + import android.app.Activity; -import android.content.res.Resources; +import android.app.AlertDialog; +import android.content.DialogInterface; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; -import com.jme3.R; + +import com.jme3.app.Application; +import com.jme3.input.android.AndroidInput; import com.jme3.system.AppSettings; import com.jme3.system.JmeSystem; import com.jme3.system.android.OGLESContext; + /** * * @author Kirill */ -public class AndroidHarness extends Activity { - - private OGLESContext ctx; - private GLSurfaceView view; +public class AndroidHarness extends Activity implements DialogInterface.OnClickListener +{ + protected final static Logger logger = Logger.getLogger(AndroidHarness.class.getName()); + + protected OGLESContext ctx; + protected GLSurfaceView view; + + protected String appClass = "jme3test.android.Test"; + protected Application app = null; @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) + { super.onCreate(savedInstanceState); JmeSystem.setResources(getResources()); @@ -31,11 +43,13 @@ public class AndroidHarness extends Activity { WindowManager.LayoutParams.FLAG_FULLSCREEN); AppSettings settings = new AppSettings(true); + AndroidInput input = new AndroidInput(this); + + -// String appClass = getResources().getString(R.string.jme3_appclass); - String appClass = "jme3test.android.Test"; - Application app = null; + // Create application instance try{ + @SuppressWarnings("unchecked") Class clazz = (Class) Class.forName(appClass); app = clazz.newInstance(); }catch (Exception ex){ @@ -46,8 +60,8 @@ public class AndroidHarness extends Activity { app.start(); ctx = (OGLESContext) app.getContext(); - view = ctx.createView(this); - setContentView(view); + view = ctx.createView(input); + setContentView(view); } @Override @@ -69,4 +83,50 @@ public class AndroidHarness extends Activity { // Debug.stopMethodTracing(); // } + + /** + * Called when an error has occured. This is typically + * invoked when an uncought exception is thrown in the render thread. + * @param errorMsg The error message, if any, or null. + * @param t Throwable object, or null. + */ + public void handleError(final String errorMsg, final Throwable t) + { + + String s = ""; + if (t != null && t.getStackTrace() != null) + { + for (StackTraceElement ste: t.getStackTrace()) + { + s += ste.getClassName() + "." + ste.getMethodName() + "(" + + ste.getLineNumber() + ") "; + } + } + final String sTrace = s; + this.runOnUiThread(new Runnable() { + @Override + public void run() + { + AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this) + // .setIcon(R.drawable.alert_dialog_icon) + .setTitle(t != null ? t.toString() : "Failed") + .setPositiveButton("Kill", AndroidHarness.this) + .setMessage((errorMsg != null ? errorMsg + ": " : "") + sTrace) + .create(); + dialog.show(); + } + }); + + } + + + /** + * Called by the android alert dialog, terminate the activity and OpenGL rendering + * @param dialog + * @param whichButton + */ + public void onClick(DialogInterface dialog, int whichButton) + { + app.stop(); + this.finish(); + } } diff --git a/engine/src/android/com/jme3/asset/AndroidAssetManager.java b/engine/src/android/com/jme3/asset/AndroidAssetManager.java index 2c1c9be3d..d9e87203b 100644 --- a/engine/src/android/com/jme3/asset/AndroidAssetManager.java +++ b/engine/src/android/com/jme3/asset/AndroidAssetManager.java @@ -66,31 +66,29 @@ public class AndroidAssetManager extends DesktopAssetManager { */ public AndroidAssetManager(URL configFile) { - super(configFile); + System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver"); - if (configFile == null) - { - // Set Default - this.registerLocator("", AndroidLocator.class); - this.registerLocator("", ClasspathLocator.class); - this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg"); - this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3m"); - this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3md"); - this.registerLoader(com.jme3.font.plugins.BitmapFontLoader.class, "fnt"); - this.registerLoader(com.jme3.texture.plugins.DDSLoader.class, "dds"); - this.registerLoader(com.jme3.texture.plugins.PFMLoader.class, "pfm"); - this.registerLoader(com.jme3.texture.plugins.HDRLoader.class, "hdr"); - this.registerLoader(com.jme3.texture.plugins.TGALoader.class, "tga"); - this.registerLoader(com.jme3.export.binary.BinaryImporter.class, "j3o"); - this.registerLoader(com.jme3.scene.plugins.OBJLoader.class, "obj"); - this.registerLoader(com.jme3.scene.plugins.MTLLoader.class, "mtl"); - this.registerLoader(com.jme3.scene.plugins.ogre.MeshLoader.class, "meshxml", "mesh.xml"); - this.registerLoader(com.jme3.scene.plugins.ogre.SkeletonLoader.class, "skeletonxml", "skeleton.xml"); - this.registerLoader(com.jme3.scene.plugins.ogre.MaterialLoader.class, "material"); - this.registerLoader(com.jme3.scene.plugins.ogre.SceneLoader.class, "scene"); - this.registerLoader(com.jme3.shader.plugins.GLSLLoader.class, "vert", "frag", "glsl", "glsllib"); - } + // Set Default Android config + this.registerLocator("", AndroidLocator.class); + this.registerLocator("", ClasspathLocator.class); + this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg"); + this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3m"); + this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3md"); + this.registerLoader(com.jme3.font.plugins.BitmapFontLoader.class, "fnt"); + this.registerLoader(com.jme3.texture.plugins.DDSLoader.class, "dds"); + this.registerLoader(com.jme3.texture.plugins.PFMLoader.class, "pfm"); + this.registerLoader(com.jme3.texture.plugins.HDRLoader.class, "hdr"); + this.registerLoader(com.jme3.texture.plugins.TGALoader.class, "tga"); + this.registerLoader(com.jme3.export.binary.BinaryImporter.class, "j3o"); + this.registerLoader(com.jme3.scene.plugins.OBJLoader.class, "obj"); + this.registerLoader(com.jme3.scene.plugins.MTLLoader.class, "mtl"); + this.registerLoader(com.jme3.scene.plugins.ogre.MeshLoader.class, "meshxml", "mesh.xml"); + this.registerLoader(com.jme3.scene.plugins.ogre.SkeletonLoader.class, "skeletonxml", "skeleton.xml"); + this.registerLoader(com.jme3.scene.plugins.ogre.MaterialLoader.class, "material"); + this.registerLoader(com.jme3.scene.plugins.ogre.SceneLoader.class, "scene"); + this.registerLoader(com.jme3.shader.plugins.GLSLLoader.class, "vert", "frag", "glsl", "glsllib"); + logger.info("AndroidAssetManager created."); } diff --git a/engine/src/android/com/jme3/input/android/AndroidInput.java b/engine/src/android/com/jme3/input/android/AndroidInput.java index 9fa50fec0..54d7e5063 100644 --- a/engine/src/android/com/jme3/input/android/AndroidInput.java +++ b/engine/src/android/com/jme3/input/android/AndroidInput.java @@ -430,6 +430,13 @@ public class AndroidInput extends GLSurfaceView implements KeyInput, MouseInput, { TouchEvent touch = new TouchEvent(TouchEvent.Type.SCALE, TouchEvent.Operation.RUNNING,scaleGestureDetector.getFocusX(),scaleGestureDetector.getFocusY(),0,0,new float[]{scaleGestureDetector.getCurrentSpan(),scaleGestureDetector.getScaleFactor()}); processEvent(touch); + + if (FIRE_MOUSE_EVENTS) + { + MouseMotionEvent mot = new MouseMotionEvent(0, 0, 0, 0, 0, (int)scaleGestureDetector.getScaleFactor()); + mot.setTime(scaleGestureDetector.getEventTime()); + processEvent(mot); + } return false; } diff --git a/engine/src/android/com/jme3/system/JmeSystem.java b/engine/src/android/com/jme3/system/JmeSystem.java index c3fb96c2e..2628b31fb 100644 --- a/engine/src/android/com/jme3/system/JmeSystem.java +++ b/engine/src/android/com/jme3/system/JmeSystem.java @@ -1,5 +1,6 @@ package com.jme3.system; + import android.content.res.Resources; import com.jme3.util.AndroidLogHandler; import com.jme3.asset.AndroidAssetManager; @@ -23,7 +24,69 @@ import java.net.URL; -public class JmeSystem { +public class JmeSystem +{ + + public static enum Platform { + + /** + * Microsoft Windows 32 bit + */ + Windows32, + + /** + * Microsoft Windows 64 bit + */ + Windows64, + + /** + * Linux 32 bit + */ + Linux32, + + + /** + * Linux 64 bit + */ + Linux64, + + /** + * Apple Mac OS X 32 bit + */ + MacOSX32, + + /** + * Apple Mac OS X 64 bit + */ + MacOSX64, + + /** + * Apple Mac OS X 32 bit PowerPC + */ + MacOSX_PPC32, + + /** + * Apple Mac OS X 64 bit PowerPC + */ + MacOSX_PPC64, + + /** + * Android 2.2 + */ + Android_Froyo, + + /** + * Android 2.3 + */ + Android_Gingerbread, + + /** + * Android 3.0 + */ + Android_Honeycomb, + + + } private static final Logger logger = Logger.getLogger(JmeSystem.class.getName()); @@ -31,45 +94,51 @@ public class JmeSystem { private static boolean lowPermissions = false; private static Resources res; - public static void initialize(AppSettings settings){ + public static void initialize(AppSettings settings) + { if (initialized) return; initialized = true; - try { + try + { JmeFormatter formatter = new JmeFormatter(); Handler consoleHandler = new AndroidLogHandler(); consoleHandler.setFormatter(formatter); -// Logger.getLogger("").removeHandler(Logger.getLogger("").getHandlers()[0]); -// Logger.getLogger("").addHandler(consoleHandler); - -// Logger.getLogger("com.g3d").setLevel(Level.FINEST); - } catch (SecurityException ex){ + } + catch (SecurityException ex) + { logger.log(Level.SEVERE, "Security error in creating log file", ex); } logger.info("Running on "+getFullName()); } - public static String getFullName(){ - return "jMonkey Engine 3 ALPHA 0.50 Android"; + public static String getFullName() + { + return "jMonkey Engine 3 ALPHA 0.6 Android"; } - public static void setLowPermissions(boolean lowPerm){ + public static void setLowPermissions(boolean lowPerm) + { lowPermissions = lowPerm; } - public static boolean isLowPermissions() { + public static boolean isLowPermissions() + { return lowPermissions; } - public static JmeContext newContext(AppSettings settings, Type contextType) { + public static JmeContext newContext(AppSettings settings, Type contextType) + { initialize(settings); return new OGLESContext(); } - public static AudioRenderer newAudioRenderer(AppSettings settings) { - return new AudioRenderer() { + public static AudioRenderer newAudioRenderer(AppSettings settings) + { + return new AudioRenderer() + { public void setListener(Listener listener) {} public void setEnvironment(Environment env) {} public void playSourceInstance(AudioNode src) {} @@ -92,26 +161,41 @@ public class JmeSystem { }; } - public static void setResources(Resources res){ + public static void setResources(Resources res) + { JmeSystem.res = res; } - public static Resources getResources(){ + public static Resources getResources() + { return res; } - public static AssetManager newAssetManager(){ + public static AssetManager newAssetManager() + { logger.info("newAssetManager()"); return new AndroidAssetManager(null); } - public static AssetManager newAssetManager(URL url){ + public static AssetManager newAssetManager(URL url) + { logger.info("newAssetManager(" + url + ")"); return new AndroidAssetManager(url); } - public static boolean showSettingsDialog(AppSettings settings, boolean loadSettings) { + public static boolean showSettingsDialog(AppSettings settings, boolean loadSettings) + { return true; } + + public static Platform getPlatform() + { + String os = System.getProperty("os.name").toLowerCase(); + String arch = System.getProperty("os.arch").toLowerCase(); + + return Platform.Android_Froyo; + // throw new UnsupportedOperationException("The specified platform: "+os+" is not supported."); + + } } diff --git a/engine/src/android/com/jme3/system/android/OGLESContext.java b/engine/src/android/com/jme3/system/android/OGLESContext.java index 353bd56ca..3b569067c 100644 --- a/engine/src/android/com/jme3/system/android/OGLESContext.java +++ b/engine/src/android/com/jme3/system/android/OGLESContext.java @@ -33,8 +33,11 @@ package com.jme3.system.android; import android.app.Activity; +import android.content.Context; import android.opengl.GLSurfaceView; import android.view.SurfaceHolder; + +import com.jme3.app.AndroidHarness; import com.jme3.input.JoyInput; import com.jme3.input.KeyInput; import com.jme3.input.MouseInput; @@ -120,13 +123,27 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer protected void initInThread() { logger.info("OGLESContext create"); - logger.fine("Running on thread: "+Thread.currentThread().getName()); + logger.info("Running on thread: "+Thread.currentThread().getName()); - Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { - public void uncaughtException(Thread thread, Throwable thrown) { - listener.handleError("Uncaught exception thrown in "+thread.toString(), thrown); - } - }); + final Context ctx = this.view.getContext(); + + // Setup unhandled Exception Handler + if (ctx instanceof AndroidHarness) + { + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread thread, Throwable thrown) { + ((AndroidHarness)ctx).handleError("Uncaught exception thrown in "+thread.toString(), thrown); + } + }); + } + else + { + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread thread, Throwable thrown) { + listener.handleError("Uncaught exception thrown in "+thread.toString(), thrown); + } + }); + } timer = new AndroidTimer();