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 / Xcode 9 / 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 &&
e.SensorType == MotionSensorType.Gyroscope)
{
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 &&
e.SensorType == MotionSensorType.Gyroscope)
{
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
using AppName.Services;
using Xamarin.Forms;
public class TestPage : ContentPage
{
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からご覧になれます。
https://itblog.dynaspo.com/blog-entry-81.html



関連記事

コメント

コメントの投稿

※名前とタイトルが入力されていないコメントでは他のコメントとの区別ができません。

 入力されていないコメントには返信しませんのであらかじめご了承くださいませ。

※ニックネームでも良いので必ずご入力ください。

    

※必ずご入力ください。

    
    

※必ずご入力ください。

※技術的な質問には環境やエラーについて正確かつ詳細にお教えください。

・正確なエラーの内容

・Windowsのバージョン番号

・Visual Studioのバージョン

・機器の型番

・アプリやソフトのバージョン

    

カテゴリ別記事一覧

広告

プロフィール

石河 純


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

IT関連の知識はざっくりとこんな感じです。
【OS関連】
WindowsServer: 2012/2008R2/2003/2000/NT4
Windows: 10/8/7/XP/2000/me/NT4/98
Linux: CentOS RedHatLinux9
Mac: macOS Catalina 10.15 / Mojave 10.14 / High Sierra 10.13 / Sierra 10.12 / OSX Lion 10.7.5 / OSX Snow Leopard 10.6.8
【言語】
VB.net ASP.NET C#.net Java VBA
Xamarin.Forms
【データベース】
Oracle 10g/9i
SQLServer 2016/2008R2/2005/2000
SQLAnywhere 16/11/8
【BI/レポートツール】
Cognos ReportNet (IBM)
Microsoft PowerBI
ActiveReport (GrapeCity)
CrystalReport
【OCX関連】
GrapeCity InputMan SPREAD MultiRow GridView
【ネットワーク関連】
CCNP シスコ技術者認定
Cisco Catalyst シリーズ
Yamaha RTXシリーズ
FireWall関連
【WEB関連】
SEO SEM CSS jQuery IIS6/7 apache2

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