Androidの端末姿勢監視
アプリケーション内で端末がどのような姿勢になっているかを取得したいときは端末に内蔵されている下記のセンサーを使います。
- 加速度センサー:x,y,z方向のそれぞれの重力加速度をセンシングする。
- 地磁気センサー:x(東西),y(南北),z(天地)方向のそれぞれの地磁気をセンシングする。
複雑な計算が必要になりますが、SensorManagerには計算を行ってくれる便利なメソッドが用意されています。
public class DeviceAttitudeManager implements SensorEventListener {
private boolean mIsMagSensor;
private boolean mIsAccSensor;
private final SensorManager mManager;
private DeviceAttitude mDeviceAttitude;
public DeviceAttitudeManager(Context context) {
mManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mDeviceAttitude = new DeviceAttitude();
}
public void onResume() {
// センサの取得
List<Sensor> sensors = mManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor : sensors) {
if (sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
mManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI);
mIsMagSensor = true;
}
if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI);
mIsAccSensor = true;
}
}
}
public void onPause() {
//センサーマネージャのリスナ登録破棄
if (mIsMagSensor || mIsAccSensor) {
mManager.unregisterListener(this);
mIsMagSensor = false;
mIsAccSensor = false;
}
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
return;
}
switch (event.sensor.getType()) {
case Sensor.TYPE_MAGNETIC_FIELD:
mDeviceAttitude.setMagneticValues(event.values.clone());
break;
case Sensor.TYPE_ACCELEROMETER:
mDeviceAttitude.setAccelerometerValues(event.values.clone());
break;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public DeviceAttitude getDeviceAttitude() {
return mDeviceAttitude;
}
static public class DeviceAttitude {
private static final int MATRIX_SIZE = 16;
/**
* 傾斜角
*/
private int mPitch;
/**
* 回転角
*/
private int mRoll;
/**
* 方位角
*/
private int mAzimuth;
/* 回転行列 */
float[] inR = new float[MATRIX_SIZE];
float[] outR = new float[MATRIX_SIZE];
float[] I = new float[MATRIX_SIZE];
/* センサーの値 */
float[] orientationValues = new float[3];
float[] magneticValues = new float[3];
float[] accelerometerValues = new float[3];
public int getPitch() {
return mPitch;
}
public int getRoll() {
return mRoll;
}
public int getAzimuth() {
return mAzimuth;
}
public void setMagneticValues(float[] magneticValues) {
this.magneticValues = magneticValues;
updateAttitude();
}
public void setAccelerometerValues(float[] accelerometerValues) {
this.accelerometerValues = accelerometerValues;
updateAttitude();
}
private void updateAttitude() {
if (magneticValues != null && accelerometerValues != null) {
SensorManager.getRotationMatrix(inR, I, accelerometerValues, magneticValues);
SensorManager.remapCoordinateSystem(inR, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR);
SensorManager.getOrientation(outR, orientationValues);
mPitch = radianToDegree(orientationValues[1]);
mRoll = radianToDegree(orientationValues[2]);
mAzimuth = radianToDegree(orientationValues[0]);
if (mAzimuth < 0) {
mAzimuth += 360;
}
}
}
int radianToDegree(float rad) {
return (int) Math.floor(Math.toDegrees(rad));
}
}
}