4

I have an app that receives push-notification, detects current device orientation (portrait/right landscape/left landscape) and takes a photo. Orientation is used to set rotation for Camera.Parameters.

I am using SensorManager.getRotationMatrix() to calculate the orientation, but it requires values from geomagnetic sensors. Lenovo S90-A has no compass, so seems like there's no way for me to get these values.

I tried to use this code:

int rotation = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay().getRotation();

from my Service, but it works only when device is on. But if device is sleeping and I receive a push notification, then this method always returns Surface.ROTATION_0.

Device will be fixed on the wall and is not supposed to move.

So, is there a way to detect current device orientation without compass?

agamov
  • 4,407
  • 1
  • 27
  • 31
  • 1
    The device orientation has nothing to do with the compass. It is the accelerometer that provides you with the device orientation. – m0skit0 Oct 13 '15 at 11:30
  • @m0skit0 can you please point me a solution? tried really hard to find it, but no luck. – agamov Oct 13 '15 at 12:08
  • [Use the accelerometer](http://stackoverflow.com/questions/5180187/how-do-i-use-the-android-accelerometer) – m0skit0 Oct 13 '15 at 12:26
  • @m0skit0 that didn't help much :) I know how to use accelerometer and collect its values. the problem is how to get device rotation from these values. But thanks anyway. – agamov Oct 13 '15 at 12:56
  • Those values are actually the device rotation status. – m0skit0 Oct 13 '15 at 13:00
  • 1
    @m0skit0 actually your comment isn't 100% correct. If device's position is flat (e.g. it lies on the table) you can't tell for sure its rotation without compass. – agamov Oct 16 '15 at 13:10

1 Answers1

1

This answer was really helpful. Actually you can't rely only on accelerometer if your device's orientation is flat (e.g. it lies on a table). I ended up with this method that I use for devices without compass. For devices with compass I use SensorManager.getRotationMatrix() and SensorManager.getOrientation().

    /**
     * calculates rotation only from accelerometer values
     * @param g - accelerometer event values
     * @return
     */
    private int getRotationFromAccelerometerOnly(float[] g) {
        double normOfG = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2]);
        // Normalize the accelerometer vector
        g[0] = (float) (g[0] / normOfG);
        g[1] = (float) (g[1] / normOfG);
        g[2] = (float) (g[2] / normOfG);
        int inclination = (int) Math.round(Math.toDegrees(Math.acos(g[2])));
        int rotation;
        if (inclination < 25 || inclination > 155) {
            // device is flat, return 0
            rotation = 0;
        } else {
            // device is not flat
            rotation = (int) Math.round(Math.toDegrees(Math.atan2(g[0], g[1])));
        }

        return rotation;
    }
Community
  • 1
  • 1
agamov
  • 4,407
  • 1
  • 27
  • 31