はじめに
Android端末の位置(Azimuth/Pitch/Roll)を測定する方法について解説。
加速度センサーと地磁気センサーを組み合わせることで、端末の位置を測定。
Azimuth/Pitch/Rollについて

上記の図の通り。地面と水平に、北向きに端末を置いた場合、Azimuth/Pitch/Rollともに0となる。
コード
- センサーイベントリスナー(
SensorEventListener
)インターフェースを継承。 - センサーマネージャー(
sensorManager
)を定義し、onResume
時にリスナーを登録、onPause
時にリスナーを解除する。 -
onSensorChanged
メソッド内で端末の位置を測定。
MainActivity.kt
class MainActivity : AppCompatActivity(), SensorEventListener {
/** ViewBinding */
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
/** センサーマネージャー */
private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager }
private val accelerometerReading = FloatArray(3)
private val magnetometerReading = FloatArray(3)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
override fun onResume() {
super.onResume()
//加速度センサー
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
if (accelerometer != null) sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL)
//地磁気センサー
val magneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
if (magneticField != null) sensorManager.registerListener(this, magneticField, SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}
override fun onSensorChanged(event: SensorEvent) {
//加速度センサー
if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
System.arraycopy(event.values, 0, accelerometerReading, 0, accelerometerReading.size)
}
//地磁気センサー
if (event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) {
System.arraycopy(event.values, 0, magnetometerReading, 0, magnetometerReading.size)
}
val rotationMatrix = FloatArray(9)
val orientationAngles = FloatArray(3)
SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading)
SensorManager.getOrientation(rotationMatrix, orientationAngles)
val azimuth = Math.toDegrees(orientationAngles[0].toDouble())
val pitch = Math.toDegrees(orientationAngles[1].toDouble())
val roll = Math.toDegrees(orientationAngles[2].toDouble())
//TODO ここに処理を記載
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
}