Android Tutorial Orientation and accelerometer

Troberg

Well-Known Member
Licensed User
Just to make it as simple as possible, a simple example for accessing only one sensor, as bare bones as it gets:

B4X:
Sub Process_Globals
    Dim ps As PhoneSensors
End Sub

Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        ps.Initialize(ps.TYPE_ACCELEROMETER)
    End If
End Sub

Sub Activity_Resume
    If ps.StartListening("Sensor") = False Then
        Log("Sensor is not supported.")
    End If
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    ps.StopListening
End Sub

Sub Sensor_SensorChanged (Values() As Float)
    Values(2) < -8 Then 'Check Z value
        Log("Device face down")
    Else
        Log("Device face up")
    End If
End Sub
I hope this makes it a little simpler. There was nothing wrong with the example in the first post, but for a simple usage like this (and, typically, you only want to watch one sensor), it took a while to reverse engineer, so hopefully, I've saved someone else the work.

By the way, while this code works, I chose to wait until I had two consecutive values of -8 or less, just to avoid triggering on random shakes and bumps. Also, in this specific application, I chose to use the accelerometer instead of orientation, as I found orientation to be very "noisy" and generally finicky to handle.
 

Turbo3

Active Member
Licensed User
I don't understand. What you people are calling the accelerometer looks like a gyroscope to me. When the device is sitting on a table an accelerometer should read zero (almost) for x, y, and z but that is not what is reported. Instead x, y, and z are the phone's orientation which is a gyroscope not an accelerometer. What am I missing?

How does one read the accelerometer?

I am trying to map over the B4i motion function which returns true acceleration (x,y,z) by using "GetUserAcceleration". What is the equivalent function is B4A?
 
Last edited:

Turbo3

Active Member
Licensed User
I get not supported when I switch the Type from 1 to 10.

It would be helpful if the description for the "ps.TYPE_ACCELEROMETER" made mention that gravity is included in the x,y,z values.

For what I need I think I can make this work even with gravity included. But I would like to keep my iOS and Android code the same so is there an iOS equivalent that includes gravity?
 
Last edited:

alfcen

Well-Known Member
Licensed User
Hello Folks,

Have been away for long time; meanwhile upgraded from Android 2.2 to Android 6.

I noticed that the orientaton sensor (compass) outputs azimuth values between 143 and 146 under Android 6.0.1
while earlier versions are working well with azimuth angles available from 0 to 360.

I browsed a lot but could not find a hint ad-hoc. Apps like "GPS Test Plus" and a bloatware app are working well
under Android 6, in that I believe I am not the smartest guy around here.

Appreciate any hints,

Cheers
Robert
 

Erel

Administrator
Staff member
Licensed User
The example code does work here on an Android 7 device. However please try this code:
B4X:
Sub Process_Globals
   Private accelerometer, magnetic As PhoneSensors
   Private accValues(), magValues() As Float
   Private sm As JavaObject
End Sub

Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
     accelerometer.Initialize(accelerometer.TYPE_ACCELEROMETER)
     magnetic.Initialize(magnetic.TYPE_MAGNETIC_FIELD)
     sm.InitializeStatic("android.hardware.SensorManager")
   End If
End Sub

Private Sub Accelerometer_SensorChanged (Values() As Float)
   accValues = Values
   CalcOrientation
End Sub

Private Sub Magnetic_SensorChanged (Values() As Float)
   magValues = Values
   CalcOrientation
End Sub

Private Sub CalcOrientation
   If accValues.Length = 0 Or magValues.Length = 0 Then Return
   Dim R(9), I(9) As Float
   Dim success As Boolean = sm.RunMethod("getRotationMatrix", Array(R, I, accValues, magValues))
   If success Then
     Dim orientation(3) As Float
     sm.RunMethod("getOrientation", Array(R, orientation))
     Log((orientation(0) * 180 / cPI + 360) mod 360)
   End If
End Sub

Sub Activity_Resume
   accelerometer.StartListening("Accelerometer")
   magnetic.StartListening("Magnetic")
End Sub


Sub Activity_Pause (UserClosed As Boolean)
   accelerometer.StopListening
   magnetic.StopListening
End Sub
It is based on a newer API.
 

alfcen

Well-Known Member
Licensed User
Erel, you are still on top of all things.:cool:
This snippet works (but please don't ask me why) ;)

Thanks a ton for your prompt response.

Cheers
Robert
 

ldb68

Member
Licensed User
I tried the latest Eric example.
If I hold the phone vertically I get completely different values than when I hold the phone horizontally (like a compass).
There is no way to have a stable value of the direction of holding the phone vertically pointed towards an object?
I tried everything without results.
 

ldb68

Member
Licensed User
I tried several things that didn't work.
Thanks Erel.
From what I have seen so there is not a reliable way to get with compass the direction in which a user is watching with the phone vertically pointed in the direction. Some phones (motorcycle E and G) even do not have the compass.

Other solutions are not there?
 

Smart Robot Android

New Member
Licensed User
Thanks a lot for their comments and codes.

Thanks again Erel for all the information you post.

Somebody have founded the solution for the "x-plane" in vertical position of the phone? I've tried several things, and only the "y-plane" and "z-plane" works fine when the phone is vertical. If the phone is horizontal the three planes works fine, but not in vertical position.

Have somebody make it works in vertical position? Thanks in advance, and again, thanks for all your help.
 

Syd Wright

Well-Known Member
Licensed User
The example code does work here on an Android 7 device. However please try this code:
B4X:
Sub Process_Globals
   Private accelerometer, magnetic As PhoneSensors
   Private accValues(), magValues() As Float
   Private sm As JavaObject
End Sub

Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
     accelerometer.Initialize(accelerometer.TYPE_ACCELEROMETER)
     magnetic.Initialize(magnetic.TYPE_MAGNETIC_FIELD)
     sm.InitializeStatic("android.hardware.SensorManager")
   End If
End Sub

Private Sub Accelerometer_SensorChanged (Values() As Float)
   accValues = Values
   CalcOrientation
End Sub

Private Sub Magnetic_SensorChanged (Values() As Float)
   magValues = Values
   CalcOrientation
End Sub

Private Sub CalcOrientation
   If accValues.Length = 0 Or magValues.Length = 0 Then Return
   Dim R(9), I(9) As Float
   Dim success As Boolean = sm.RunMethod("getRotationMatrix", Array(R, I, accValues, magValues))
   If success Then
     Dim orientation(3) As Float
     sm.RunMethod("getOrientation", Array(R, orientation))
     Log((orientation(0) * 180 / cPI + 360) mod 360)
   End If
End Sub

Sub Activity_Resume
   accelerometer.StartListening("Accelerometer")
   magnetic.StartListening("Magnetic")
End Sub


Sub Activity_Pause (UserClosed As Boolean)
   accelerometer.StopListening
   magnetic.StopListening
End Sub
It is based on a newer API.
 

Syd Wright

Well-Known Member
Licensed User
Excellent! I can now use this code for my Protractor project, just by using the
orientation(1) value. The device has to be placed in landscape orientation and place upwards (i.e. standing on the bottom edge of the device). It is ideal to accurately measure angles of sloping surfaces and thus functions as an electronic "Level".
 
Top