1

I am developing a cocos2d-x application for Android devices. I would have two different screen configurations which are designed for mobile and tablet device formats. In the main.cpp I would like to add some logic which determines whether the device is tablet or mobile. This way I can load the appropriately laid out interface as the app starts up.

I have seen solutions to detect tablet or device from Java code, but is there a way to do the same thing in C++ in the NDK?

don
  • 1,497
  • 1
  • 13
  • 27
  • 2
    You could always use JNI to call Java functions from C – krsteeve Sep 17 '13 at 19:14
  • I think thats what I am looking for. Can you expand on that a little and give me an example on how to do this? Or point me in the right direction with a link? – don Sep 17 '13 at 19:21

1 Answers1

3

To just get the screen resolution, you can use ANativeWindow:

ANativeWindow nativeWindow = ANativeWindow_fromSurface(env, surface);
int width =  ANativeWindow_getWidth(renderEngine->nativeWindow);
int height = ANativeWindow_getHeight(renderEngine->nativeWindow);

This however isn't enough, you'll also need the screen density which is not available via the NDK. You can get it using JNI. What would be a few lines in Java ends up being:

JNIEnv* jni;
app->activity->vm->AttachCurrentThread(&jni, NULL);

jclass activityClass = jni->FindClass("android/app/NativeActivity");
JNI_ASSERT(jni, activityClass);

jmethodID getWindowManager = jni->GetMethodID (activityClass, "getWindowManager" , "()Landroid/view/WindowManager;"); 
JNI_ASSERT(jni, getWindowManager);

jobject wm = jni->CallObjectMethod(app->activity->clazz, getWindowManager);
JNI_ASSERT(jni, wm);

jclass windowManagerClass = jni->FindClass("android/view/WindowManager");
JNI_ASSERT(jni, windowManagerClass);

jmethodID getDefaultDisplay = jni->GetMethodID(windowManagerClass, "getDefaultDisplay" , "()Landroid/view/Display;");
JNI_ASSERT(jni, getDefaultDisplay);

jobject display = jni->CallObjectMethod(wm, getDefaultDisplay);
JNI_ASSERT(jni, display);

jclass displayClass = jni->FindClass("android/view/Display");
JNI_ASSERT(jni, displayClass);

jclass displayMetricsClass = jni->FindClass("android/util/DisplayMetrics");
JNI_ASSERT(jni, displayMetricsClass);

jmethodID displayMetricsConstructor = jni->GetMethodID(displayMetricsClass, "<init>", "()V");
JNI_ASSERT(jni, displayMetricsConstructor);

jobject displayMetrics = jni->NewObject(displayMetricsClass, displayMetricsConstructor);
JNI_ASSERT(jni, displayMetrics);

jmethodID getMetrics = jni->GetMethodID(displayClass, "getMetrics", "(Landroid/util/DisplayMetrics;)V");
JNI_ASSERT(jni, getMetrics);

jni->CallVoidMethod(display, getMetrics, displayMetrics);
JNI_ASSERT(jni, true);

jfieldID xdpi_id = jni->GetFieldID(displayMetricsClass, "xdpi", "F");
JNI_ASSERT(jni, xdpi_id);

float xdpi = jni->GetFloatField( displayMetrics, xdpi_id);
JNI_ASSERT(jni, true);

Code taken from this question. JNI_ASSERT is a little error-checking macro.

Once you have the resolution of the display and the dpi, it should be straightforward to calculate the screen size. You will have to decide what your cutoff is for "phone" and "tablet". (But you can always peek at where Android draws the line!)

Community
  • 1
  • 1
krsteeve
  • 1,794
  • 4
  • 19
  • 29
  • 1
    Thank you! This is a detailed answer to my question as well as a nice tutorial on JNI. – don Sep 17 '13 at 22:23