Содержание
Встряхивание устройства отслеживается акселерометром (интерфейс — IAccelerometer
). Для обнаружения тряски API .NET MAUI использует необработанные показания акселерометра для вычисления ускорения. Он использует простой механизм очереди для определения того, произошло ли 75% последних событий акселерометра за последние пол секунды. В этой части мы разберемся с тем, как отслеживать встряхивание устройства Android.
Событие встряхивания устройства
Событие ShakeDetected
генерируется каждый раз, как только устройство встряхивается.
event EventHandler? ShakeDetected;
Сам алгоритм определения встряхнуто ли устройство или нет реализован в методе ProcessShakeEvent
класса AccelerometerImplementation
и выглядит следующим образом.
void ProcessShakeEvent(Vector3 acceleration) { var now = Nanoseconds(DateTime.UtcNow); var x = acceleration.X * gravity; var y = acceleration.Y * gravity; var z = acceleration.Z * gravity; var g = x * x + y * y + z * z; queue.Add(now, g > accelerationThreshold); if (queue.IsShaking) { queue.Clear(); var args = new EventArgs(); if (useSyncContext) MainThread.BeginInvokeOnMainThread(() => ShakeDetected?.Invoke(null, args)); else ShakeDetected?.Invoke(null, args); } static long Nanoseconds(DateTime time) => (time.Ticks / TimeSpan.TicksPerMillisecond) * 1_000_000; }
Пороговое значение accelerationThreshold
, которое используется для проверки, выглядит следующим образом:
const double accelerationThreshold = 169;
Таким образом, дл того, чтобы наше приложение каким-либо образом отреагировало на встряхивание устройства, нам необходимо подписаться на событие ShakeDetected
и отслеживать его срабатывание.
Встряхивание устройства
Определение необходимых разрешений
Так как используется обычный акселерометр, то и разрешение нам необходимо как и для всех прочих датчиков устройства — android.permission.HIGH_SAMPLING_RATE_SENSORS
. Создадим новый проект .NET MAUI и добавим это разрешение, используя атрибут сборки:
using Android.App; using Android.Runtime; [assembly: UsesPermission(Android.Manifest.Permission.HighSamplingRateSensors)] namespace MauiShake; [Application] public class MainApplication : MauiApplication { public MainApplication(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership) { } protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); }
Отслеживание встряхивания устройства
По сути, нам необходимо отследить только одно событие и отреагировать на него, поэтому, думаю, нет необходимости создавать в качестве примера отдельную модель представления — воспользуемся обычным code-behind. Откройте файл MainPage.xaml.cs и измените его следующим образом:
namespace MauiShake { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); Accelerometer.ShakeDetected += OnShake; Accelerometer.Default.Start(SensorSpeed.Fastest); } ~MainPage() { Accelerometer.Default.Stop(); Accelerometer.ShakeDetected += OnShake; } private async void OnShake(object? sender, EventArgs e) { await CounterBtn.ScaleTo(2); await CounterBtn.ScaleTo(1); } } }
Здесь в обработчике события OnShake()
выполняется анимация
ScaleTo()
, которая вначале увеличивает кнопку CounterBtn
в 2 раза, а затем — возвращает размер к первоначальному значению.
В конструкторе класса мы подписываемся на событие ShakeDetected
и запускаем датчик акселерометра:
public MainPage() { InitializeComponent(); Accelerometer.ShakeDetected += OnShake; Accelerometer.Default.Start(SensorSpeed.Fastest); }
а в деструкторе — не забываем отписаться от события и отключить датчик:
~MainPage() { Accelerometer.Default.Stop(); Accelerometer.ShakeDetected += OnShake; }
На этом пример окончен — код XAML страницы MainPage
можно не менять и оставить так, как он был в шаблоне проекта. Теперь можно запустить приложение и потрясти устройство — вы увидите, как кнопка меняет свой размер.
Итого
Встряхивание устройства отслеживается в .NET MAUI программно через данные акселерометра. Для того, чтобы приложение могло отреагировать на встряхивание, необходимо подписаться на событие ShakeDetected
акселерометра.