Содержание
Встряхивание устройства отслеживается акселерометром (интерфейс — 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 акселерометра.