FC2ブログ

記事一覧

ジャイロスコープセンサーで端末の振動を検出する方法 | Xamarin.Forms


今回は Xamarin.Forms で ジャイロスコープセンサー を使用して端末の空間での動作情報を取得する方法についてご紹介いたします。
あまりネイティブコードを書かない様に NuGet パッケージ Xam.Plugin.DeviceMotion を採用し、ネイティブコードを呼び出すための DependencyService を使用しています。


前提条件
・Windows10 Pro 64Bit 1709
・Visual Studio 2015 Community Update3
・Xamarin 4.8.0.760 (NuGet Xamarin.Forms 2.4.0.282)
・macOS Sierra 10.12.6 / Xcode9 / Xamarin.iOS 11.6.1.4



1.Xam.Plugin.DeviceMotion

まずは NuGet パッケージマネージャから 「Device Motion Plugin」 で検索してインストールします。
PCL で実装します。v1.1.2 を選択して、全てのプロジェクトにインストールします。
※PCL にも ViewModel クラスを使用している為、インストールが必要です。

xamarin_gyroscope_01.png



2.PCLの記述方法

(1)PCL プロジェクト内に DependencyService で呼び出すためのインターフェースを配置します。

IMotionService.cs
using DeviceMotion.Plugin.Abstractions;
namespace AppName.Services
{
public delegate void OnMotionChangedDelegate(MotionVector vector);

//DependencyServiceから利用する
public interface IMotionService
{
// 非同期で動作情報の変更をリスニングする
void StartGyroscopeSensor(MotionSensorDelay delay, double threshold);

//動作情報変更イベント
event OnMotionChangedDelegate OnMotionChanged;
}
}



3.Androidの実装方法

(1)Android プロジェクト内に MotionService クラスを配置します。

MotionService.cs
using System;
using Xamarin.Forms;
using AppName.Droid.Services;
using AppName.Services;
using DeviceMotion.Plugin;
using DeviceMotion.Plugin.Abstractions;
[assembly: Dependency(typeof(MotionService))]
namespace AppName.Droid.Services
{
public class MotionService : IMotionService
{
private double _threshold = 0;
/// <summary>
/// 非同期で動作情報の変更をリスニングする
/// </summary>
/// <param name="delay">動作を検知する間隔</param>
/// <param name="threshold">変更イベントを通知する閾値</param>
public void StartGyroscopeSensor(MotionSensorDelay delay, int threshold)
{
//閾値を変数に確保する
_threshold = threshold;

//ジャイロセンサーの検知を開始する
IDeviceMotion motion = CrossDeviceMotion.Current;
motion.Start(MotionSensorType.Gyroscope, delay);

//ジャイロセンサーの変更イベントを実装します。
motion.SensorValueChanged += (object sender, SensorValueChangedEventArgs e) =>
{
if (this.OnMotionChanged != null)
{
MotionVector vector = (MotionVector)e.Value;
//閾値を超えた場合のみイベント通知する
if (Math.Abs(vector.X) > _threshold ||
Math.Abs(vector.Y) > _threshold ||
Math.Abs(vector.Z) > _threshold)
{
this.OnMotionChanged((MotionVector)e.Value);
}
}
};
}

//動作情報変更イベント
public event OnMotionChangedDelegate OnMotionChanged;
}
}




4.iOSの実装方法

(1)iOS プロジェクト内に MotionService クラスを配置します。
※ Android で実装しているコードと全く同じです。

MotionService.cs
using System;
using Xamarin.Forms;
using AppName.iOS.Services;
using AppName.Services;
using DeviceMotion.Plugin;
using DeviceMotion.Plugin.Abstractions;
[assembly: Dependency(typeof(MotionService))]
namespace AppName.iOS.Services
{
public class MotionService : IMotionService
{
private double _threshold = 0;
/// <summary>
/// 非同期で動作情報の変更をリスニングする
/// </summary>
/// <param name="delay">動作を検知する間隔</param>
/// <param name="threshold">変更イベントを通知する閾値</param>
public void StartGyroscopeSensor(MotionSensorDelay delay, int threshold)
{
//閾値を変数に確保する
_threshold = threshold;

//ジャイロセンサーの検知を開始する
IDeviceMotion motion = CrossDeviceMotion.Current;
motion.Start(MotionSensorType.Gyroscope, delay);

//ジャイロセンサーの変更イベントを実装します。
motion.SensorValueChanged += (object sender, SensorValueChangedEventArgs e) =>
{
if (this.OnMotionChanged != null)
{
MotionVector vector = (MotionVector)e.Value;
//閾値を超えた場合のみイベント通知する
if (Math.Abs(vector.X) > _threshold ||
Math.Abs(vector.Y) > _threshold ||
Math.Abs(vector.Z) > _threshold)
{
this.OnMotionChanged((MotionVector)e.Value);
}
}
};
}

//動作情報変更イベント
public event OnMotionChangedDelegate OnMotionChanged;
}
}




5.使用方法

PCL プロジェクトの中の任意のページに記述します。
MotionSensorDelay には Fastest や Game、 Ui など数値の少ないものもありますが、試してみた感覚では Default で十分だと思います。また、通知する閾値を1に設定していますが、少し動かしただけで検知します。某SNSアプリのふるふるのように大きなモーションを必要な場合は閾値を大きく、微細な振動を検知したい場合は閾値を小さく設定すると良いでしょう。
※閾値につきましては DependencyService の実装部分において3D方向に対する動作幅が閾値を超えた場合に通知する仕組みとさせていただいております。

TestPage.xaml.cs
void GyroscopeSensor_Click(object sender, EventArgs e)
{
DependencyService.Get<IMotionService>().OnMotionChanged += new OnMotionChangedDelegate(this.MotionChanged);

//非同期スレッドを開始する
DependencyService.Get<IMotionService>().StartGyroscopeSensor(DeviceMotion.Plugin.Abstractions.MotionSensorDelay.Default, 1);
}
void MotionChanged(DeviceMotion.Plugin.Abstractions.MotionVector vector)
{
//変更イベントを捕捉してローカル通知で情報をお知らせしています。
DependencyService.Get<INotificationService>().SetNotifyCondition(DateTimeOffset.Now, 0, "");
DependencyService.Get<INotificationService>().On("ジャイロスコープセンサー", "ジャイロスコープセンサーテスト", "X=" + vector.X.ToString() + ";Y=" + vector.Y.ToString() + ";Z=" + vector.Z.ToString());
}

※今回の動作情報変更イベントでは NotificationService を使用して画面に通知しています。詳しくは以前の記事「ローカル通知する方法」をご覧ください。






最後までお読みいただきありがとうございます。
当ブログの内容をまとめた Xamarin逆引きメニュー は以下のURLからご覧になれます。
http://itblogdsi.blog.fc2.com/blog-entry-81.html



関連記事

コメント

コメントの投稿

カテゴリ別記事一覧

広告

プロフィール

石河 純


著者名 :石河 純
自己紹介:素人上がりのIT技術者。趣味は卓球・車・ボウリング

IT関連の知識はざっくりとこんな感じです。
【OS関連】
WindowsServer: 2012/2008R2/2003/2000/NT4
Windows: 10/8/7/XP/2000/me/NT4/98
Linux: CentOS RedHatLinux9
Mac: macOS Sierra 10.12 / OSX Lion 10.7.5 / OSX Snow Leopard 10.6.8
【言語・データベース】
VB.net ASP.NET C#.net Java VBA
Xamarin.Forms
Oracle10g SQLServer2008R2 SQLAnywhere8/11/16
ActiveReport CrystalReport ReportNet(IBM)
【ネットワーク関連】
CCNP シスコ技術者認定
Cisco Catalyst シリーズ
Yamaha RTXシリーズ
FireWall関連
【WEB関連】
SEO SEM CSS IIS6/7 apache2

休みの日は卓球をやっています。
現在、卓球用品通販ショップは休業中です。