Recent

Author Topic: how to determine android device orientation?  (Read 14329 times)

stab

  • Full Member
  • ***
  • Posts: 237
how to determine android device orientation?
« on: April 05, 2013, 07:06:50 pm »
Hi,

Is it possible to determine android device orientation?

Regards
stab %)

stab

  • Full Member
  • ***
  • Posts: 237
Re: how to determine android device orientation?
« Reply #1 on: April 05, 2013, 09:17:38 pm »
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

  • Administrator
  • Hero Member
  • *
  • Posts: 3538
Re: how to determine android device orientation?
« Reply #2 on: April 08, 2013, 07:19:07 pm »
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/customdrawn/customdrawnwslazdeviceapis.pas?view=markup&revision=36524&root=lazarus

stab

  • Full Member
  • ***
  • Posts: 237
Re: how to determine android device orientation?
« Reply #3 on: April 10, 2013, 02:43:48 pm »
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(Context.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

  • Administrator
  • Hero Member
  • *
  • Posts: 3538
Re: how to determine android device orientation?
« Reply #4 on: April 10, 2013, 08:35:55 pm »
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

  • Full Member
  • ***
  • Posts: 237
Re: how to determine android device orientation?
« Reply #5 on: April 11, 2013, 05:29:44 pm »
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

  • Administrator
  • Hero Member
  • *
  • Posts: 3538
Re: how to determine android device orientation?
« Reply #6 on: April 11, 2013, 08:45:07 pm »
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

  • Administrator
  • Hero Member
  • *
  • Posts: 3538
Re: how to determine android device orientation?
« Reply #7 on: April 11, 2013, 08:56:16 pm »
The last call is wrong, you did CallVoidMethodA but it should be CallVoidMethod but this does not explain why the display is nil.

stab

  • Full Member
  • ***
  • Posts: 237
Re: how to determine android device orientation?
« Reply #8 on: April 11, 2013, 09:07:19 pm »
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

  • Administrator
  • Hero Member
  • *
  • Posts: 3538
Re: how to determine android device orientation?
« Reply #9 on: April 11, 2013, 09:15:01 pm »
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

  • Full Member
  • ***
  • Posts: 237
Re: how to determine android device orientation?
« Reply #10 on: April 11, 2013, 09:23:59 pm »
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$LCLSurface.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.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1691)
E/AndroidRuntime( 7991):        at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1125)
E/AndroidRuntime( 7991):        at android.app.Activity.dispatchTouchEvent(Activity.java:2096)
E/AndroidRuntime( 7991):        at com.android.internal.policy.impl.PhoneWindow$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

 

TinyPortal © 2005-2018