Reputation: 1861
Is there a way to detect the current orientation of an Android device?
I'm not talking about the screen orientation, I'm talking about the way the device is physically being held. All the solutions I've found so far tell me the screen orientation (which is always portrait in my app). I need to know if the user is holding the device horizontally even though I haven't rotated the screen.
Thanks.
Upvotes: 7
Views: 3729
Reputation: 28706
You can use the accelerometer. To use it you need to register a listener on the sensor TYPE_ACCELEROMETER.
Once it is done you will receive notifications when the values of this sensor are changing (very very often when the user holds the device in the hand).
Values received from this sensor are the projection of the (vector representing the) gravity on X, Y and Z axis. (well... this is not exactly true: in fact those values represent the projection of the sum of all forces applied to the device) So :
SensorEvent.values[0]
) : means that the right edge of the device if under the left edge.SensorEvent.values[1]
) : means that the top edge is under the bottom edgeSensorEvent.values[2]
) : means that the front of the device if facing the ground and so the 2 previous rules must be inverted.Here is sample code (Warning : it don't care about the value on the Z-Axis)
/**
* Logs the device orientation. Results are not valid when the screen is facing the ground.
* (when the discriminant value is low (i.e. device almost horizontal) : no logs)
*/
public void onSensorChanged(SensorEvent event) {
if (event.sensor == mAccelerometer) {
if(Math.abs(event.values[1]) > Math.abs(event.values[0])) {
//Mainly portrait
if (event.values[1] > 1) {
Log.d(TAG,"Portrait");
} else if (event.values[1] < -1) {
Log.d(TAG,"Inverse portrait");
}
}else{
//Mainly landscape
if (event.values[0] > 1) {
Log.d(TAG,"Landscape - right side up");
} else if (event.values[0] < -1) {
Log.d(TAG,"Landscape - left side up");
}
}
}
}
Upvotes: 7
Reputation: 14367
You could do it pre 2.2 with the orientation sensor - which was just a fancy mix and match of accelerometer and magnetometer and then deprecated 2.2 onwards. Now you could just code the class yourself. From https://stackoverflow.com/a/10291428/1081340
public class OrientationTestActivity extends Activity implements SensorEventListener
{
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private Sensor mMagnetometer;
private float[] mLastAccelerometer = new float[3];
private float[] mLastMagnetometer = new float[3];
private boolean mLastAccelerometerSet = false;
private boolean mLastMagnetometerSet = false;
private float[] mR = new float[9];
private float[] mOrientation = new float[3];
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
protected void onResume() {
super.onResume();
mLastAccelerometerSet = false;
mLastMagnetometerSet = false;
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
if (event.sensor == mAccelerometer) {
System.arraycopy(event.values, 0, mLastAccelerometer, 0, event.values.length);
mLastAccelerometerSet = true;
} else if (event.sensor == mMagnetometer) {
System.arraycopy(event.values, 0, mLastMagnetometer, 0, event.values.length);
mLastMagnetometerSet = true;
}
if (mLastAccelerometerSet && mLastMagnetometerSet) {
SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);
SensorManager.getOrientation(mR, mOrientation);
Log.i("OrientationTestActivity", String.format("Orientation: %f, %f, %f",
mOrientation[0], mOrientation[1], mOrientation[2]));
}
}
}
Upvotes: 1
Reputation: 12636
Yes, you can read accelerometer directly http://developer.android.com/guide/topics/sensors/sensors_overview.html
Upvotes: 0