Xamarin.Formsで各種センサーの値を取得するには

#はじめに
スマートフォンは各種センサーもりもり、通信インターフェース複数、RFIDリーダライタなど全部乗せのリッチなIoTデバイスです。
加速度センサー、磁気センサー、照度センサー、GPS（センサーか？）、Wifi、BlueTooth、カメラ、マイクetc etc...
実際、これらの機能をArduinoなどにモジュールで付け足していったら数万はいくんじゃないかなと思います。これらが安ければ1万円ぐらいで手に入るのです。すごいですよね。

これらセンサーの値はアイデア次第でとても面白い使い方ができます。
問題はそのアイデアですが、そんな雲をつかむような話ではなく、ただセンサーの値を取得して眺めて幸せになるにはどうすればいいのか、という話です。

#Xamarin.Formsでセンサーの値を取得するには
Xamarin.Essentialsというライブラリを使うと、共通コードからこれらOS固有の機能を呼び出すことができます。
なので、まずはXamarin.EsssentialsをNuGetからインストールしましょう。
Visual StudioでXamrin.Formsのプロジェクトを作成、NuGetで「xamarin.essentials」と検索すれば出てきます。


- 参考
- https://docs.microsoft.com/ja-jp/xamarin/essentials/?context=xamarin/android
- https://blog.xamarin.com/xamarin-essentials-cross-platform-apis-mobile-apps/


#Xamarin.Essentialsの機能一覧
Xamarin.Essentialsを利用すると以下の機能をXamarin.Formsアプリの中で、OSごとの固有のコードではなく共通コードから使うことができます。
センサーだけでなくいろいろな端末の機能も使えます。
素晴らしい！

- 加速度計 – 3 次元空間内のデバイスの加速度データを取得します。
- アプリ情報 – アプリケーションに関する情報を見つけます。
- バロメーター – 気圧の変化のバロメーターを監視します。
- バッテリ – バッテリ レベル、ソース、および状態を簡単に検出します。
- クリップボード – クリップボード上のテキストをすばやく簡単に設定したり読み取ったりします。
- コンパス – 変化のコンパスを監視します。
- 接続 – 接続状態を確認し、変更を検出します。
- デバイス ディスプレイ情報 – デバイスの画面のメトリックと向きを取得します。
- デバイス情報 – デバイスの詳細を簡単に確認します。
- 電子メール – 電子メール メッセージを簡単に送信します。
- ファイル システム ヘルパー – アプリ データにファイルを簡単に保存します。
- 懐中電灯 – 懐中電灯のオン/オフを簡単に切り替える方法です。
- ジオコーディング – ジオコードとリバース ジオコードのアドレスおよび座標。
- 位置情報 – デバイスの GPS 位置情報を取得します。
- ジャイロスコープ – デバイスの 3 つの主軸の周りの回転を追跡します。
- ランチャー – アプリケーションがシステムで URI を開くことができるようにします。
- 磁力計 – 地球の磁場を基準としたデバイスの向きを検出します。
- メイン スレッド – アプリケーションのメイン スレッドでコードを実行します。
- マップ – 特定の場所にマップ アプリケーションを開きます。
- ブラウザーを開く – ブラウザーで特定の Web サイトをすばやく簡単に開きます。
- 向きセンサー – 3 次元空間内のデバイスの向きを取得します。
- ダイヤラー – ダイヤラーを開きます。
- ユーザー設定 – 永続的なユーザー設定をすばやく簡単に追加します。
- セキュリティで保護されたストレージ – データを安全に格納します。
- Share – 他のアプリにテキストや Web サイトの URI を送信します。
- SMS – 送信用の SMS メッセージを作成します。
- 音声合成 – デバイス上のテキストを音声化します。
- バージョンの追跡 – アプリケーションのバージョンとビルド番号を追跡します。
- バイブレーション – デバイスをバイブレーションさせます。

#使ってみよう
こちらの[Xamarin.Essentialsの概要](https://docs.microsoft.com/ja-jp/xamarin/essentials/?context=xamarin/android)のページでは、機能概要の項のリストで各機能にリンクが張ってあります。

それらのリンクの先には各機能の実装方法がコードとともに紹介されていて、そのとおりに実装するだけでその機能を使うことができるという、とても良いチュートリアルにもなっています。
これをもとに各機能の動きを確認してみるとよいでしょう。

<img src="https://qiita-image-store.s3.amazonaws.com/0/245438/e138e7cd-53f2-cfdd-5ca2-0ff4292d28f3.png" title="" alt="image.png" width="60%" height="" >

例えば、「コンパス」の使ってみましょう。
Xamarin.Formsのプロジェクトを作ってXamarin.Essentialsをインストールしてあるとします。
ちなみに、Xamarin.Essentialsは共通コードから使うので各OSのプロジェクトにではなく共通コードのプロジェクトにだけインストールします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/245438/55e406f9-ddae-8c88-5884-6e39dce01b34.png" title="" alt="image.png" width="60%" height="" >



Xamarin.Essentialsのコンパス機能は、`Compass`クラスを使います。このクラスの使い方はとてもシンプルで、`ReadingChanged`イベントと`Start`、`Stop`メソッド、そして動いているかどうかの状態を表す`IsMonitoring`プロパティだけです。
データの取得頻度は`SensorSpeed`構造体をStartメソッドの引数として渡すことで指定することができます。

ポイントは以下のとおりです。

- `Start`メソッドでコンパスデータの値の取得を開始し、`Stop`メソッドで取得を停止します。
- 取得中は`IsMonitoring`プロパティがtrueになります。
- 指定した取得頻度に応じて一定間隔で値を取得し、
- 値を取得したら`ReadingChanged`イベントが発火します。
- `ReadingChanged`イベントにイベントハンドラを登録しておき、値をUIに表示させたりします。

とても簡単ですね。
コンパスから取得した値をLabelコントロールに表示するだけのアプリケーションは以下のとおりです。

```csharp:MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamarinEssentialsCompassTest"
             x:Class="XamarinEssentialsCompassTest.MainPage">

    <StackLayout>
        <!-- Labelに名前をつけます。LabelCompass-->
        <Label x:Name="LabelCompass" Text="Welcome to Xamarin.Forms!" 
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" />
    </StackLayout>

</ContentPage>
```

```csharp:MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace XamarinEssentialsCompassTest
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();

            //値を取得したときのイベントハンドラをセット
            Compass.ReadingChanged += Compass_ReadingChanged;

            //コンパス値の取得開始
            Compass.Start(SensorSpeed.UI);
        }

        //値を取得したときに実行される
        private void Compass_ReadingChanged(object sender, CompassChangedEventArgs e)
        {
            var data = e.Reading;
            //ラベルに表示
            LabelCompass.Text = data.HeadingMagneticNorth.ToString();
        }
    }

}

```

#おわりに
公式サイトの説明を読んでいただいてもわかるとおり、とても簡単に端末の機能を使えることがわかると思います。
今回はコンパス機能を例に紹介しましたが、これが特別に簡単なわけではなく他の機能も大体こんな感じです。
各種センサーを簡単に、しかも共通のコードで複数のプラットフォームで使えるのですから、わくわくがとまりませんね。

このコードはGitHubに公開してあります。
https://github.com/shuheydev/XamarinEssentialsCompassTest

そして、Xamarin.Essentialsの機能をセンサーを中心にいろいろ突っ込んで表示させるアプリも公開しておきます。
https://github.com/shuheydev/XamarinFormsEssentialsTest

各センサーのいろいろな値を表示するようになっています。
少なくともXamarin.Essentialsで取得できるセンサーの値をSensorSpeed.UIの速度で取得し続けますし、GPSが10秒おきに位置情報をとったりと割といい感じにバッテリーを消費していきます。
しかし、センサーの値が変化し続ける様子を見るのはきっと楽しいと思います。
おすすめです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/245438/a93876c6-ea7a-9df2-1b17-3eb05c71d9ea.png" title="" alt="Screenshot_20181223-221859.png" width="60%" height="" >