- Renamed SExposedVideoData::window to SExposedVideoData::Window
- Fontsize in Android example depends now on the dpi. This also adds example code of how to access the Android Java code from c++. git-svn-id: http://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@4661 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
72e924bf0c
commit
f2c944ec0f
|
@ -0,0 +1,114 @@
|
|||
#include "android_tools.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace android
|
||||
{
|
||||
|
||||
// Not all DisplayMetrics are available through the NDK.
|
||||
// So we access the Java classes with the JNI interface.
|
||||
// You can access other Java classes available in Android in similar ways.
|
||||
// Function based roughly on the code from here: http://stackoverflow.com/questions/13249164/android-using-jni-from-nativeactivity
|
||||
bool getDisplayMetrics(android_app* app, SDisplayMetrics & metrics)
|
||||
{
|
||||
if (!app || !app->activity || !app->activity->vm )
|
||||
return false;
|
||||
|
||||
JNIEnv* jni = 0;
|
||||
app->activity->vm->AttachCurrentThread(&jni, NULL);
|
||||
if (!jni )
|
||||
return false;
|
||||
|
||||
|
||||
// get all the classes we want to access from the JVM
|
||||
jclass classNativeActivity = jni->FindClass("android/app/NativeActivity");
|
||||
jclass classWindowManager = jni->FindClass("android/view/WindowManager");
|
||||
jclass classDisplay = jni->FindClass("android/view/Display");
|
||||
jclass classDisplayMetrics = jni->FindClass("android/util/DisplayMetrics");
|
||||
|
||||
if (!classNativeActivity || !classWindowManager || !classDisplay || !classDisplayMetrics)
|
||||
{
|
||||
app->activity->vm->DetachCurrentThread();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Get all the methods we want to access from the JVM classes
|
||||
// Note: You can get the signatures (third parameter of GetMethodID) for all
|
||||
// functions of a class with the javap tool, like in the following example for class DisplayMetrics:
|
||||
// javap -s -classpath myandroidpath/adt-bundle-linux-x86_64-20131030/sdk/platforms/android-10/android.jar android/util/DisplayMetrics
|
||||
jmethodID idNativeActivity_getWindowManager = jni->GetMethodID( classNativeActivity
|
||||
, "getWindowManager"
|
||||
, "()Landroid/view/WindowManager;");
|
||||
jmethodID idWindowManager_getDefaultDisplay = jni->GetMethodID( classWindowManager
|
||||
, "getDefaultDisplay"
|
||||
, "()Landroid/view/Display;");
|
||||
jmethodID idDisplayMetrics_constructor = jni->GetMethodID( classDisplayMetrics
|
||||
, "<init>"
|
||||
, "()V");
|
||||
jmethodID idDisplay_getMetrics = jni->GetMethodID( classDisplay
|
||||
, "getMetrics"
|
||||
, "(Landroid/util/DisplayMetrics;)V");
|
||||
|
||||
if (!idNativeActivity_getWindowManager || !idWindowManager_getDefaultDisplay || !idDisplayMetrics_constructor
|
||||
|| !idDisplay_getMetrics)
|
||||
{
|
||||
app->activity->vm->DetachCurrentThread();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// In Java the following code would be: getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||
// Note: If you need to call java functions in time-critical places you can split getting the jmethodID's
|
||||
// and calling the functions into separate functions as you only have to get the jmethodID's once.
|
||||
jobject windowManager = jni->CallObjectMethod(app->activity->clazz, idNativeActivity_getWindowManager);
|
||||
|
||||
if (!windowManager)
|
||||
{
|
||||
app->activity->vm->DetachCurrentThread();
|
||||
return false;
|
||||
}
|
||||
jobject display = jni->CallObjectMethod(windowManager, idWindowManager_getDefaultDisplay);
|
||||
if (!display)
|
||||
{
|
||||
app->activity->vm->DetachCurrentThread();
|
||||
return false;
|
||||
}
|
||||
jobject displayMetrics = jni->NewObject( classDisplayMetrics, idDisplayMetrics_constructor);
|
||||
if (!displayMetrics)
|
||||
{
|
||||
app->activity->vm->DetachCurrentThread();
|
||||
return false;
|
||||
}
|
||||
jni->CallVoidMethod(display, idDisplay_getMetrics, displayMetrics);
|
||||
|
||||
// access the fields of DisplayMetrics (we ignore the DENSITY constants)
|
||||
jfieldID idDisplayMetrics_widthPixels = jni->GetFieldID( classDisplayMetrics, "widthPixels", "I");
|
||||
jfieldID idDisplayMetrics_heightPixels = jni->GetFieldID( classDisplayMetrics, "heightPixels", "I");
|
||||
jfieldID idDisplayMetrics_density = jni->GetFieldID( classDisplayMetrics, "density", "F");
|
||||
jfieldID idDisplayMetrics_densityDpi = jni->GetFieldID( classDisplayMetrics, "densityDpi", "I");
|
||||
jfieldID idDisplayMetrics_scaledDensity = jni->GetFieldID( classDisplayMetrics, "scaledDensity", "F");
|
||||
jfieldID idDisplayMetrics_xdpi = jni->GetFieldID(classDisplayMetrics, "xdpi", "F");
|
||||
jfieldID idDisplayMetrics_ydpi = jni->GetFieldID(classDisplayMetrics, "ydpi", "F");
|
||||
|
||||
if ( idDisplayMetrics_widthPixels )
|
||||
metrics.widthPixels = jni->GetIntField(displayMetrics, idDisplayMetrics_widthPixels);
|
||||
if ( idDisplayMetrics_heightPixels )
|
||||
metrics.heightPixels = jni->GetIntField(displayMetrics, idDisplayMetrics_heightPixels);
|
||||
if (idDisplayMetrics_density )
|
||||
metrics.density = jni->GetFloatField(displayMetrics, idDisplayMetrics_density);
|
||||
if (idDisplayMetrics_densityDpi)
|
||||
metrics.densityDpi = jni->GetIntField(displayMetrics, idDisplayMetrics_densityDpi);
|
||||
if (idDisplayMetrics_scaledDensity)
|
||||
metrics.scaledDensity = jni->GetFloatField(displayMetrics, idDisplayMetrics_scaledDensity);
|
||||
if ( idDisplayMetrics_xdpi )
|
||||
metrics.xdpi = jni->GetFloatField(displayMetrics, idDisplayMetrics_xdpi);
|
||||
if ( idDisplayMetrics_ydpi )
|
||||
metrics.ydpi = jni->GetFloatField(displayMetrics, idDisplayMetrics_ydpi);
|
||||
|
||||
app->activity->vm->DetachCurrentThread();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace irr
|
|
@ -0,0 +1,32 @@
|
|||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __IRR_ANDROID_TOOLS_H__
|
||||
#define __IRR_ANDROID_TOOLS_H__
|
||||
|
||||
#include <irrlicht.h>
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace android
|
||||
{
|
||||
|
||||
struct SDisplayMetrics
|
||||
{
|
||||
irr::s32 widthPixels;
|
||||
irr::s32 heightPixels;
|
||||
irr::f32 density;
|
||||
irr::s32 densityDpi;
|
||||
irr::f32 scaledDensity;
|
||||
irr::f32 xdpi;
|
||||
irr::f32 ydpi;
|
||||
};
|
||||
|
||||
// Access SDisplayMetrics
|
||||
extern bool getDisplayMetrics(android_app* app, SDisplayMetrics & metrics);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __IRR_ANDROID_TOOLS_H__
|
|
@ -24,7 +24,7 @@ endif
|
|||
|
||||
LOCAL_C_INCLUDES := ../../include
|
||||
|
||||
LOCAL_SRC_FILES := main.cpp
|
||||
LOCAL_SRC_FILES := main.cpp android_tools.cpp
|
||||
|
||||
LOCAL_LDLIBS := -lEGL -llog -lGLESv1_CM -lGLESv2 -lz -landroid
|
||||
|
||||
|
@ -44,4 +44,6 @@ $(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/Shaders/*.* $(IRRLICHT_PROJECT_P
|
|||
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/irrlichtlogo3.png $(IRRLICHT_PROJECT_PATH)/assets/media/)
|
||||
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/sydney.md2 $(IRRLICHT_PROJECT_PATH)/assets/media/)
|
||||
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/sydney.bmp $(IRRLICHT_PROJECT_PATH)/assets/media/)
|
||||
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/fonthaettenschweiler.bmp $(IRRLICHT_PROJECT_PATH)/assets/media/)
|
||||
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/bigfont.png $(IRRLICHT_PROJECT_PATH)/assets/media/)
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifdef _IRR_ANDROID_PLATFORM_
|
||||
|
||||
#include <android_native_app_glue.h>
|
||||
#include "android_tools.h"
|
||||
|
||||
using namespace irr;
|
||||
using namespace core;
|
||||
|
@ -134,8 +135,7 @@ int run ( IrrlichtDevice *device )
|
|||
{
|
||||
stringw str = L"FPS: ";
|
||||
str += (s32)device->getVideoDriver()->getFPS();
|
||||
|
||||
stat->setText ( str.c_str() );
|
||||
// stat->setText ( str.c_str() );
|
||||
}
|
||||
}
|
||||
device->yield(); // probably nicer to the battery
|
||||
|
@ -159,15 +159,33 @@ int example_helloworld(android_app* app)
|
|||
IGUIEnvironment* guienv = device->getGUIEnvironment();
|
||||
|
||||
// access to the Android native window
|
||||
ANativeWindow* nativeWindow = static_cast<ANativeWindow*>(driver->getExposedVideoData().OGLESAndroid.window);
|
||||
ANativeWindow* nativeWindow = static_cast<ANativeWindow*>(driver->getExposedVideoData().OGLESAndroid.Window);
|
||||
int32_t windowWidth = ANativeWindow_getWidth(app->window);
|
||||
int32_t windowHeight = ANativeWindow_getHeight(app->window);
|
||||
|
||||
// get display metrics (accessing the Java functions of the JVM directly in this case as there is no NDK function for that yet)
|
||||
irr::android::SDisplayMetrics displayMetrics;
|
||||
memset(&displayMetrics, 0, sizeof displayMetrics);
|
||||
irr::android::getDisplayMetrics(app, displayMetrics);
|
||||
|
||||
// Wherever you put your media. But it must be inside the assets folder.
|
||||
// This example copies the media in the Android.mk makefile.
|
||||
stringc mediaPath = "media/";
|
||||
|
||||
// Set the font-size depending on your device
|
||||
// dpi=dots per inch. 1 inch = 2.54 cm
|
||||
// (xdpi and ydpi are typically very similar or identical, but certainly don't have to be)
|
||||
IGUISkin* skin = guienv->getSkin();
|
||||
IGUIFont* font = 0;
|
||||
if ( displayMetrics.xdpi < 100 ) // just guessing some value where fontsize might start to get too small
|
||||
font = guienv->getFont(mediaPath + "fonthaettenschweiler.bmp");
|
||||
else
|
||||
font = guienv->getFont(mediaPath + "bigfont.png");
|
||||
if (font)
|
||||
skin->setFont(font);
|
||||
|
||||
|
||||
IGUIStaticText *text = guienv->addStaticText(L"FPS: 25",
|
||||
rect<s32>(10,15,200,30), false, false, 0, GUI_INFO_FPS );
|
||||
IGUIStaticText *text = guienv->addStaticText(stringw(displayMetrics.xdpi).c_str(),
|
||||
rect<s32>(15,15,300,60), false, false, 0, GUI_INFO_FPS );
|
||||
|
||||
// add irrlicht logo
|
||||
IGUIImage * logo = guienv->addImage(driver->getTexture(mediaPath + "irrlichtlogo3.png"),
|
||||
|
@ -175,7 +193,9 @@ int example_helloworld(android_app* app)
|
|||
s32 minLogoWidth = windowWidth/3;
|
||||
if ( logo && logo->getRelativePosition().getWidth() < minLogoWidth )
|
||||
{
|
||||
// scale to make it better visible on high-res devices
|
||||
// Scale to make it better visible on high-res devices
|
||||
// We could also work with displayMetrics.widthPixels, but it's generally better to work with the windowWidth which already subtract
|
||||
// things like a taskbar which your device might have.
|
||||
logo->setScaleImage(true);
|
||||
core::rect<s32> logoPos(logo->getRelativePosition());
|
||||
f32 scale = (f32)minLogoWidth/(f32)logoPos.getWidth();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
-----
|
||||
SETUP
|
||||
-----
|
||||
------------
|
||||
REQUIREMENTS
|
||||
------------
|
||||
|
||||
To use Android you need to have installed:
|
||||
- Android SDK (from http://developer.android.com)
|
||||
|
@ -11,6 +11,10 @@ To use Android you need to have installed:
|
|||
- A recent version of awk
|
||||
- On Windows you need to have Cygwin (at least version 1.7) installed
|
||||
|
||||
----------------------------
|
||||
BUILDING Irrlicht & your App
|
||||
----------------------------
|
||||
|
||||
1. Assign your Android SDK path to an ANDROID_HOME environment variable.
|
||||
2. Add $ANDROID_HOME/tools and $ANDROID_HOME/platform-tools and the Android NDK main folder to your PATH environment variable.
|
||||
3. Go to: source->Irrlicht->Android and call "ndk-build" or "ndk-build NDEBUG=1"
|
||||
|
@ -56,8 +60,11 @@ jni/Application.mk:
|
|||
|
||||
res:
|
||||
A folder with resources which are compiled into your application and can be accessed via ID's.
|
||||
There is also support for things like different target resolutions.
|
||||
Unfortunately no direct NDK access to resources at the time of writing this. So you either have
|
||||
to access them with java-code and copy to c++ somehow or you have to use hacks to read the format
|
||||
directly (which is done by some apps, but not future-safe and google recommends not doing that).
|
||||
Please check the official "App Resources" android developer documention, as this is rather complex.
|
||||
We use it only for the application icons in this example.
|
||||
|
||||
assets:
|
||||
Files in here are distributed with your app. It's acting like a typical file system.
|
||||
|
@ -78,9 +85,3 @@ libs:
|
|||
|
||||
src:
|
||||
Created by our makefile because the ant build.xml in the android sdk needs it for some reason. It's empty (so far?).
|
||||
|
||||
----------
|
||||
DEPLOYMENT
|
||||
----------
|
||||
When you require EDT_OGLES2 your android:glEsVersion in AndroidManifest.xml should be "0x00020000"
|
||||
while for EDT_OGLES1 it should be "0x00010000".
|
||||
|
|
|
@ -96,7 +96,7 @@ struct SExposedVideoData
|
|||
struct
|
||||
{
|
||||
//! The ANativeWindow object.
|
||||
void* window;
|
||||
void* Window;
|
||||
|
||||
} OGLESAndroid;
|
||||
};
|
||||
|
|
|
@ -208,7 +208,7 @@ void CIrrDeviceAndroid::handleAndroidCommand(android_app* app, int32_t cmd)
|
|||
break;
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
os::Printer::log("Android command APP_CMD_INIT_WINDOW", ELL_DEBUG);
|
||||
Device->getExposedVideoData().OGLESAndroid.window = app->window;
|
||||
Device->getExposedVideoData().OGLESAndroid.Window = app->window;
|
||||
|
||||
if (Device->CreationParams.WindowSize.Width == 0 || Device->CreationParams.WindowSize.Height == 0)
|
||||
{
|
||||
|
|
|
@ -47,7 +47,7 @@ bool CEGLManager::initialize(const SIrrlichtCreationParameters& params, const SE
|
|||
EglWindow = (NativeWindowType)Data.OpenGLLinux.X11Window;
|
||||
EglDisplay = eglGetDisplay((NativeDisplayType)Data.OpenGLLinux.X11Display);
|
||||
#elif defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
|
||||
EglWindow = (ANativeWindow*)Data.OGLESAndroid.window;
|
||||
EglWindow = (ANativeWindow*)Data.OGLESAndroid.Window;
|
||||
EglDisplay = eglGetDisplay((NativeDisplayType) EGL_DEFAULT_DISPLAY);
|
||||
#endif
|
||||
|
||||
|
@ -113,7 +113,7 @@ bool CEGLManager::generateSurface()
|
|||
// this needs an update method instead!
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
|
||||
EglWindow = (ANativeWindow*)Data.OGLESAndroid.window;
|
||||
EglWindow = (ANativeWindow*)Data.OGLESAndroid.Window;
|
||||
#endif
|
||||
|
||||
EGLint EglOpenGLBIT = 0;
|
||||
|
|
Loading…
Reference in New Issue