SIN@SAPPOROWORKSの覚書

C#を中心に、夜な夜な試行錯誤したコードの記録です。

Xamarin.Android 方位の取得(傾きセンサー)

【 Xamarin 記事一覧 】


1 方位の取得方法

Androidで方位を取得する方法は、次の2つがあります。

(1) TYPE_ORIENTATION(傾きセンサー)による方法
(2) TYPE_MAGNETIC_FIELD(磁界センサー)とTYPE_ACCELEROMETER(加速度センサー)による方法

今回は、(1)の傾きセンサーを使用してみます。

針の指している方向がちょっと?となりますが・・・
磁北は、真北(地図の真上)より、左(西)に少しずれています。(偏角

2 傾きセンサー(TYPE_ORIENTATION)


まずは、OnCreate()で、SensorManagerのインスタンスや、表示のための初期化を行っています。
リスナー(ISensorEventListener)は、自分自身として実装し、登録及び解除は、OnResume()及びOnPause()で行っています。

OnSensorChanged()で取得できるのは、「方位角」「傾斜角」「回転角」の3つですが、
この方位角は、現在の角度(0〜360の左回り)です。

サンプルでは、この値(角度)を1回分保存し、前回との差分で画像を回転させています。

[Activity(Label = "AndroidApplication1", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity,ISensorEventListener{

    private SensorManager _senseManager;
    private ImageView _imageView;
    private TextView _textView;
    private Matrix _matrix;
    private float _centerX; //回転の中心座標
    private float _centerY; //回転の中心座標

    protected override void OnCreate(Bundle bundle){
       base.OnCreate(bundle);
       SetContentView(Resource.Layout.Main);

       _senseManager = (SensorManager) GetSystemService(SensorService);
       _imageView = FindViewById<ImageView>(Resource.Id.image);
       _textView = FindViewById<TextView>(Resource.Id.textView);
      _matrix = new Matrix();

       //ディスプレイのサイズ取得
       var display = WindowManager.DefaultDisplay;
       var dispWidth = display.Width;
       var dispHeight = display.Height;

       //画像のサイズ取得
       var d = Resources.GetDrawable(Resource.Drawable.magnet);
       var imageWidth = d.IntrinsicWidth;
       var imageHeight = d.IntrinsicHeight;

       //画像を画面の中央に移動する
       _matrix.PostTranslate((dispWidth - imageWidth) / 2, (dispHeight - imageHeight) / 2);
       //回転させる際の中心座標を保存しておく
       _centerX = dispWidth/2;
       _centerY = dispHeight/2;
    }

    protected override void OnResume(){
        base.OnResume();
        //傾きセンサー取得
        var list = _senseManager.GetSensorList(SensorType.Orientation);
        //取得に成功した場合のみ処理
        if (list.Count > 0){
            //リスナーに登録(第3引数は感度)
            _senseManager.RegisterListener(this,list[0], SensorDelay.Normal);
        }
    }
    protected override void OnPause(){
        base.OnPause();
        //リスナー解除
        _senseManager.UnregisterListener(this);
    }

    //ISensorEventListenerで必須
    public void OnAccuracyChanged(Sensor sensor, SensorStatus accuracy){ }

    private float _keepValue;//前回の角度

    public void OnSensorChanged(SensorEvent e) {
        //傾きセンサーのみ処理
        if (e.Sensor.Type == SensorType.Orientation){

            //e.Values[0] 方位角
            //e.Values[1] 傾斜角
            //e.Values[2] 回転角

            //現在の角度を取得
            var value = e.Values[0];

            //中心座標と回転角(前回角度ー現在角度)をセットする
            _matrix.PostRotate(_keepValue - value, _centerX, _centerY);
            //画像を回転させる
            _imageView.ImageMatrix = _matrix;
            //テキスト表示
            _textView.Text = string.Format("{0} - {1} = {2}", _keepValue,value,_keepValue - value);

            //次回用に角度を保存する
            _keepValue = value;
        }
    }

}

【 Xamarin 記事一覧 】