how to determine android device orientation? lazarus / 43-Android ---------------------------------------------------------------------- stab · 2013-04-05 17:06 Hi, Is it possible to determine android device orientation? Regards stab ---------------------------------------------------------------------- stab · 2013-04-05 19:17 Found a solution to detect landscape or portrait orientation. In my app I have a paintbox covering the whole screen and in OnResize I detect how width and height changes. Have still to figure out how to detect landscape and portrait upside down. /stab ---------------------------------------------------------------------- felipemdc · 2013-04-08 17:19 It needs to be obtained via JNI. Search in Google first to see how is the Java call to do this, you get: http://stackoverflow.com/questions/2795833/check-orientation-on- android-phone Then one needs to convert this Java call into JNI native code. See this file for examples of how to do JNI code: http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/lcl/interfaces/cust omdrawn/customdrawnwslazdeviceapis.pas?view=markup&revision=36524&root =lazarus ---------------------------------------------------------------------- stab · 2013-04-10 12:43 Tried the code for vibration in unit CustomDrawnWSLazDeviceAPIS and it worked of course all right and found following java code to check for orientation:  public String getRotation(Context context){     final int rotation = ((WindowManager) context.getSystemService(Con text.WINDOW_SERVICE)).getDefaultDisplay().getOrientation();            switch (rotation) {             case Surface.ROTATION_0:                 return "portrait";             case Surface.ROTATION_90:                 return "landscape";             case Surface.ROTATION_180:                 return "reverse portrait";             default:                 return "reverse landscape";             }         } Reading http://wiki.freepascal.org/Android_Programming#Android_JNI I understand that I first have get hold of methodId like in   javaMethod_vibrate := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidOSVibratorClass, 'vibrate', '(J)V'); Where do I get information about what classname, name and sig to use, in my case for orientation? Regards stab ---------------------------------------------------------------------- felipemdc · 2013-04-10 18:35 Google, the android sdk documentation and the code that you posted above. Reading the code you can see that 3 method calls are utilized: context.getSystemService(Context.WINDOW_SERVICE) WindowManager.getDefaultDisplay() Display.getOrientation or something similar, the class names I am not 100% at this point. So Google for each method name, for example: getSystemService android One of the first results is: http://developer.android.com/reference/android/content/Context.html Which is the Android SDK documentation for the class Context. Find getSystemService in it. Now you have all information to make a call to this method. Do the same for the other ones. For the second one we get: http://developer.android.com/reference/android/view/WindowManager.html ---------------------------------------------------------------------- stab · 2013-04-11 15:29 Thanks a lot for your answer. Think I got a little forward. Made the following code: procedure TfrmJNITestMain.btnOrientationClick(Sender: TObject); var   windowManagerClass, displayClass : jclass;   javaMethod_WindowService, javaMethod_getDefaultDisplay, javaMethod_getRotation : JMethodID;   lWindowManagerObject, lDisplayObject: JObject;   javaString_WINDOW_SERVICE, javaString_getDefaultDisplay : JString;   // array for the parameters   lParams: array[0..0] of JValue;   rotation : LongInt; const   javaConstant_WINDOW_SERVICE = 'window'; begin   windowManagerClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/view/WindowManager');   if windowManagerClass <> nil then     debugln('******* windowManagerClass NOT nil *******')   else     debugln('******* windowManagerClass nil *******');   displayClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/view/Display');   if displayClass <> nil then     debugln('******* displayClass NOT nil *******')   else     debugln('******* displayClass nil *******');   // get the string Context.WINDOW_SERVICE remember that NewStringUTF does not require ReleaseStringUTFChars   javaString_WINDOW_SERVICE := javaEnvRef^^.NewStringUTF(javaEnvRef, pchar(javaConstant_WINDOW_SERVICE));   if javaString_WINDOW_SERVICE <> nil then     debugln('******* javaString_WINDOW_SERVICE NOT nil *******')   else     debugln('******* javaString_WINDOW_SERVICE nil *******');   // Get the WindowManager object   // Window w = (Window) getSystemService(Context.WINDOW_SERVICE);   lParams[0].l := javaString_WINDOW_SERVICE;   lWindowManagerObject := javaEnvRef^^.CallObjectMethodA(javaEnvRef, javaAndroidContentContextClass, javaMethod_getSystemService, @lParams[0]);   if lWindowManagerObject <> nil then     debugln('******* lWindowManagerObject NOT nil *******')   else     debugln('******* lWindowManagerObject nil *******');   javaMethod_getDefaultDisplay := javaEnvRef^^.GetMethodID(javaEnvRef, windowManagerClass, 'getDefaultDisplay', '()Landroid/view/Display;');   if javaMethod_getDefaultDisplay <> nil then     debugln('******* javaMethod_getDefaultDisplay NOT nil *******')   else     debugln('******* javaMethod_getDefaultDisplay nil *******');   // Get the display object   lDisplayObject := javaEnvRef^^.CallObjectMethod(javaEnvRef, lWindowManagerObject, javaMethod_getDefaultDisplay);   if lDisplayObject <> nil then     debugln('******* lDisplayObject NOT nil *******')   else     debugln('******* lDisplayObject nil *******');   javaMethod_getRotation := javaEnvRef^^.GetMethodID(javaEnvRef, displayClass, 'getRotation', '()I');   if javaMethod_getRotation <> nil then     debugln('******* javaMethod_getRotation NOT nil *******')   else     debugln('******* javaMethod_getRotation nil *******'); // Now call the method from the display object //  lParams[0].j := 300;   javaEnvRef^^.CallVoidMethodA(javaEnvRef, lDisplayObject, javaMethod_getRotation, nil);   debugln('After javaEnvRef^^.CallVoidMethodA'); and got following debug info: I/ActivityManager( 1157): Displayed com.pascal.JNITest/.LCLActivity: +553ms I/lclapp  ( 6707): ******* windowManagerClass NOT nil ******* I/lclapp  ( 6707): ******* displayClass NOT nil ******* I/lclapp  ( 6707): ******* javaString_WINDOW_SERVICE NOT nil ******* I/lclapp  ( 6707): ******* lWindowManagerObject NOT nil ******* I/lclapp  ( 6707): ******* javaMethod_getDefaultDisplay NOT nil ******* I/lclapp  ( 6707): ******* lDisplayObject nil ******* I/lclapp  ( 6707): ******* javaMethod_getRotation NOT nil ******* I/DEBUG   ( 1070): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** I/DEBUG   ( 1070): Build fingerprint: 'SEMC/X10i_1234-8465/X10i:2.3.3/3.0.1.G.0.75/tB_P:user/release-keys' I/DEBUG   ( 1070): pid: 6707, tid: 6707  >>> com.pascal.JNITest <<< I/DEBUG   ( 1070): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000 As one can see, I don't manage to create the display object and the app crashes at call to getRotation. Could you please give me a hint on what my mistake is? Regards stab ---------------------------------------------------------------------- felipemdc · 2013-04-11 18:45 You are in a very good direction. The problem must be related to "lDisplayObject nil" I read your code and so far haven't found the bug. ---------------------------------------------------------------------- felipemdc · 2013-04-11 18:56 The last call is wrong, you did CallVoidMethodA but it should be CallVoidMethod but this does not explain why the display is nil. ---------------------------------------------------------------------- stab · 2013-04-11 19:07 Changed my code a little using CallObjectMethodA and now the LDisplayObject is created allright but the app still crashes. Modified code:     // Get the display object     lParams[0].l := javaString_getDefaultDisplay;     lDisplayObject := javaEnvRef^^.CallObjectMethodA(javaEnvRef, lWindowManagerObject, javaMethod_getSystemService, @lParams[0]); //    lDisplayObject := javaEnvRef^^.CallObjectMethod(javaEnvRef, lWindowManagerObject, javaMethod_getDefaultDisplay);     if lDisplayObject <> nil then       debugln('******* lDisplayObject NOT nil *******')     else       debugln('******* lDisplayObject nil *******');     javaMethod_getRotation := javaEnvRef^^.GetMethodID(javaEnvRef, displayClass, 'getRotation', '()I');     if javaMethod_getRotation <> nil then       debugln('******* javaMethod_getRotation NOT nil *******')     else       debugln('******* javaMethod_getRotation nil *******');   // Now call the method from the display object   //  lParams[0].j := 300;     rotation := javaEnvRef^^.CallLongMethod(javaEnvRef, lDisplayObject, javaMethod_getRotation);     debugln('rotation: ' + IntToStr(rotation));   except     on E:Exception do       debugln('Error:'+ E.Message);   end; and crash message: I/ActivityManager( 1157): Displayed com.pascal.JNITest/.LCLActivity: +582ms I/lclapp  ( 7838): ******* windowManagerClass NOT nil ******* I/lclapp  ( 7838): ******* displayClass NOT nil ******* I/lclapp  ( 7838): ******* javaString_WINDOW_SERVICE NOT nil ******* I/lclapp  ( 7838): ******* lWindowManagerObject NOT nil ******* I/lclapp  ( 7838): ******* javaString_getDefaultDisplay NOT nil ******* I/lclapp  ( 7838): ******* javaMethod_getDefaultDisplay NOT nil ******* I/lclapp  ( 7838): ******* lDisplayObject NOT nil ******* I/lclapp  ( 7838): ******* javaMethod_getRotation NOT nil ******* I/lclapp  ( 7838): rotation: 1073832832 D/AndroidRuntime( 7838): Shutting down VM W/dalvikvm( 7838): threadid=1: thread exiting with uncaught exception (group=0x4001d560) ---------------------------------------------------------------------- felipemdc · 2013-04-11 19:15 aha! Found what might be the cause: You utilized CallLongMethod but it is wrong, it returns an integer not a long so it should be CallIntMethod I have no idea why the A version was required for the getDisplay ... the function has no parameters, the version without A is the correct. But if it works ... ---------------------------------------------------------------------- stab · 2013-04-11 19:23 Changed to CallIntMethod but still crashes: D/Finsky  ( 7161): [1] 5.onFinished: Installation state replication succeeded. I/lclapp  ( 7991): ******* windowManagerClass NOT nil ******* I/lclapp  ( 7991): ******* displayClass NOT nil ******* I/lclapp  ( 7991): ******* javaString_WINDOW_SERVICE NOT nil ******* I/lclapp  ( 7991): ******* lWindowManagerObject NOT nil ******* I/lclapp  ( 7991): ******* javaString_getDefaultDisplay NOT nil ******* I/lclapp  ( 7991): ******* javaMethod_getDefaultDisplay NOT nil ******* I/lclapp  ( 7991): ******* lDisplayObject NOT nil ******* I/lclapp  ( 7991): ******* javaMethod_getRotation NOT nil ******* I/lclapp  ( 7991): rotation: 1073832832 D/AndroidRuntime( 7991): Shutting down VM W/dalvikvm( 7991): threadid=1: thread exiting with uncaught exception (group=0x4001d560) E/AndroidRuntime( 7991): FATAL EXCEPTION: main E/AndroidRuntime( 7991): java.lang.IllegalArgumentException E/AndroidRuntime( 7991):        at java.lang.Thread.join(Thread.java:948) E/AndroidRuntime( 7991):        at com.pascal.JNITest.LCLActivity.LCLOnTouch(Native Method) E/AndroidRuntime( 7991):        at com.pascal.JNITest.LCLActivity$LCLS urface.onTouchEvent(LCLActivity.java:184) E/AndroidRuntime( 7991):        at android.view.View.dispatchTouchEvent(View.java:3934) E/AndroidRuntime( 7991):        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1016) E/AndroidRuntime( 7991):        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1016) E/AndroidRuntime( 7991):        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1016) E/AndroidRuntime( 7991):        at com.android.internal.policy.impl.Ph oneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1691) E/AndroidRuntime( 7991):        at com.android.internal.policy.impl.Ph oneWindow.superDispatchTouchEvent(PhoneWindow.java:1125) E/AndroidRuntime( 7991):        at android.app.Activity.dispatchTouchEvent(Activity.java:2096) E/AndroidRuntime( 7991):        at com.android.internal.policy.impl.Ph oneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1675) E/AndroidRuntime( 7991):        at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2215) E/AndroidRuntime( 7991):        at android.view.ViewRoot.handleMessage(ViewRoot.java:1899) E/AndroidRuntime( 7991):        at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime( 7991):        at android.os.Looper.loop(Looper.java:123) E/AndroidRuntime( 7991):        at android.app.ActivityThread.main(ActivityThread.java:3701) E/AndroidRuntime( 7991):        at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 7991):        at java.lang.reflect.Method.invoke(Method.java:507) E/AndroidRuntime( 7991):        at com.android.internal.os.ZygoteInit$ MethodAndArgsCaller.run(ZygoteInit.java:862) E/AndroidRuntime( 7991):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) E/AndroidRuntime( 7991):        at dalvik.system.NativeStart.main(Native Method) W/ActivityManager( 1157):   Force finishing activity com.pascal.JNITest/.LCLActivity