Created
October 17, 2014 18:00
-
-
Save smile0520/1425ed7cb064162fa20e to your computer and use it in GitHub Desktop.
Androidのセンサーを使って端末の向き(縦横)を判定する
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.voidroider.sensorsample; | |
import android.app.Activity; | |
import android.hardware.Sensor; | |
import android.hardware.SensorEvent; | |
import android.hardware.SensorEventListener; | |
import android.hardware.SensorManager; | |
import android.os.Bundle; | |
import android.widget.TextView; | |
public class MainActivity extends Activity implements SensorEventListener { | |
/** | |
* 回転したと判定する際の閾値角度 | |
*/ | |
private static final int THRESHOLD_DEGREE = 60; | |
/** | |
* 縦から横に変化したと判定する際の角度 | |
*/ | |
private static final int VERTICAL_TO_HORIZONTAL_DEGREE = THRESHOLD_DEGREE; | |
/** | |
* 横から縦にに変化したと判定する際の角度 | |
*/ | |
private static final int HORIZONTAL_TO_VERTICAL_DEGREE = 90 - THRESHOLD_DEGREE; | |
/** | |
* 縦向きを表す定数 | |
*/ | |
private static final int ORIENTATION_VERTICAL = 0; | |
/** | |
* 横向きを表す定数 | |
*/ | |
private static final int ORIENTATION_HORIZONTAL = 1; | |
/** | |
* ラジアンを度に変換する際の定数 | |
*/ | |
protected final static double RAD2DEG = 180 / Math.PI; | |
private static final int MATRIX_SIZE = 16; | |
/* 回転行列 */ | |
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]; | |
private int mPreOrientation = -1; | |
SensorManager sensorManager; | |
TextView azimuthText; | |
TextView pitchText; | |
TextView rollText; | |
TextView orientationText; | |
@Override | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
findViews(); | |
initSensor(); | |
} | |
public void onResume() { | |
super.onResume(); | |
sensorManager.registerListener( | |
this, | |
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), | |
SensorManager.SENSOR_DELAY_UI); | |
sensorManager.registerListener( | |
this, | |
sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), | |
SensorManager.SENSOR_DELAY_UI); | |
} | |
public void onPause() { | |
super.onPause(); | |
sensorManager.unregisterListener(this); | |
} | |
protected void findViews() { | |
azimuthText = (TextView) findViewById(R.id.azimuth); | |
pitchText = (TextView) findViewById(R.id.pitch); | |
rollText = (TextView) findViewById(R.id.roll); | |
orientationText = (TextView) findViewById(R.id.orientation); | |
} | |
protected void initSensor() { | |
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); | |
} | |
@Override | |
public void onAccuracyChanged(Sensor sensor, int accuracy) { | |
} | |
@Override | |
public void onSensorChanged(SensorEvent event) { | |
switch (event.sensor.getType()) { | |
case Sensor.TYPE_MAGNETIC_FIELD: | |
magneticValues = event.values.clone(); | |
break; | |
case Sensor.TYPE_ACCELEROMETER: | |
accelerometerValues = event.values.clone(); | |
break; | |
} | |
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); | |
int azimuth = (int) (orientationValues[0] * RAD2DEG); | |
int pitch = (int) (orientationValues[1] * RAD2DEG); | |
int roll = (int) (orientationValues[2] * RAD2DEG); | |
// 以下、縦横判定処理 | |
int absRoll = Math.abs(roll); | |
if (mPreOrientation == -1) { | |
mPreOrientation = absRoll < VERTICAL_TO_HORIZONTAL_DEGREE ? | |
ORIENTATION_VERTICAL : ORIENTATION_HORIZONTAL; | |
} else if (absRoll < 90) { | |
mPreOrientation = getOrientation(mPreOrientation, roll); | |
} else { | |
// プラマイ90度を超える場合は90度未満に置き換えて向きを反転させる。 | |
int plusMinus = roll >= 0 ? 1 : -1; | |
roll = (absRoll - 90) * plusMinus; | |
int preOrientation = invertOrientation(mPreOrientation); | |
mPreOrientation = invertOrientation(getOrientation(preOrientation, roll)); | |
} | |
// 表示の更新 | |
azimuthText.setText(String.valueOf(azimuth)); | |
pitchText.setText(String.valueOf(pitch)); | |
rollText.setText(String.valueOf(roll)); | |
orientationText.setText(mPreOrientation == ORIENTATION_VERTICAL ? "縦" : "横"); | |
} | |
} | |
/** | |
* 与えられた端末の向きを反転させます。 | |
* | |
* @param orientation 端末の向き({@link #ORIENTATION_HORIZONTAL} or {@link #ORIENTATION_VERTICAL} or -1) | |
* @return 反転した端末の向き({@link #ORIENTATION_HORIZONTAL} or {@link #ORIENTATION_VERTICAL} or -1) | |
*/ | |
private int invertOrientation(int orientation) { | |
if (orientation == ORIENTATION_HORIZONTAL) { | |
return ORIENTATION_VERTICAL; | |
} else if (orientation == ORIENTATION_VERTICAL) { | |
return ORIENTATION_HORIZONTAL; | |
} else { | |
return -1; | |
} | |
} | |
/** | |
* 一つ前の端末の向きと現在の傾きを元に、現在の端末の向きを求めます | |
* | |
* @param preOrientation 一つ前の端末の向き({@link #ORIENTATION_HORIZONTAL} or {@link #ORIENTATION_VERTICAL} or -1) | |
* @param roll 傾き(90度未満) | |
* @return 現在の端末の向き({@link #ORIENTATION_HORIZONTAL} or {@link #ORIENTATION_VERTICAL} or -1) | |
*/ | |
private int getOrientation(int preOrientation, int roll) { | |
int absRoll = Math.abs(roll); | |
if (preOrientation == ORIENTATION_VERTICAL) { | |
return (absRoll < VERTICAL_TO_HORIZONTAL_DEGREE) ? | |
ORIENTATION_VERTICAL : ORIENTATION_HORIZONTAL; | |
} else if (preOrientation == ORIENTATION_HORIZONTAL) { | |
return (absRoll < HORIZONTAL_TO_VERTICAL_DEGREE) ? | |
ORIENTATION_VERTICAL : ORIENTATION_HORIZONTAL; | |
} else { | |
return -1; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment