В статье рассматривается проблема активации GPS-датчика в Android-приложениях, использующих POSIX-таймеры. Приведены примеры кода на Object Pascal (Delphi), а также описывается метод решения, основанный на использовании LocalBroadcastManager.
Проблема активации GPS-датчика
При использовании POSIX-таймеров в Android-сервисах для периодической активации и деактивации GPS-датчика может возникать ошибка:
Сan't start sensor: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Ошибка возникает, когда в обработчике событий таймера происходит обращение к свойствам TSensorManager.Current. Если тот же код выполнить в методах AndroidServiceStartCommand или AndroidServiceCreate, то активация датчика проходит успешно.
Пример кода, вызывающего ошибку
Вот пример кода, который вызывает описанную проблему:
Для решения проблемы активации GPS-датчика в фоновом режиме с использованием POSIX-таймеров было найдено следующее решение:
Создать фильтр для LocalBroadcastManager на действие ACTION_LOCATION_CHANGE, зарегистрировав LocalBroadcastReceiver.
В обработчике событий таймера отправлять sendBroadcast с действием ACTION_LOCATION_CHANGE.
В обработчике LocalBroadcastReceiver изменять свойство активности TLocationSensor.
Пример кода для LocalBroadcastReceiver:
procedure TMyApplication.LocalBroadcastReceiver(const Sender: TObject; const Message: TObject);
begin
if TMessage<PStringArray>(Message).ParamStrs[0] = 'ACTION_LOCATION_CHANGE' then
begin
with TLocationSensorManager.Current do
begin
if Active then
Deactivate
else
Activate;
end;
end;
end;
Подготовка Looper
Ошибка Can't create handler inside thread that has not called Looper.prepare() указывает на то, что поток, в котором выполняется код, не был подготовлен для работы с Looper. Это означает, что в данном потоке не было вызвано Looper.prepare(). Для того чтобы исправить это, необходимо использовать механизмы Android для работы с сообщениями и обработчиками событий, которые предполагают наличие Looper.
Пример реализации таймера
Для создания таймера и его обработчика событий можно использовать следующий код:
var
TimerID: Integer;
begin
TimerID := AndroidTimerCreate(AndroidTimerType.POSIX, nil, @TMyApplication.TimerProc, 5000, 0, false);
end;
procedure TMyApplication.TimerProc(Param: Integer);
begin
// Отправка сообщения для активации или деактивации GPS
LocalBroadcastManager.SendBroadcastStringArray(nil, 'ACTION_LOCATION_CHANGE');
end;
Заключение
Использование LocalBroadcastManager позволяет решить проблему активации GPS-датчика через POSIX-таймер без нарушения правил работы потоков в Android. Приведенные примеры кода демонстрируют, как можно реализовать периодическую активацию и деактивацию датчика, избегая при этом ошибки связанной с подготовкой Looper.
Статья рассматривает проблему активации GPS-датчика в Android-сервисе с использованием POSIX-таймеров, связанную с необходимостью подготовки Looper для потока обработчика событий, и предлагает решение с использованием `LocalBroadcastManager`.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.