brunnengi Опубликовано 29 сентября, 2014 Поделиться Опубликовано 29 сентября, 2014 Здравствуйте. Как получить координаты GPS без использования компонента TLocationSensors? Цитата Ссылка на комментарий
0 Администраторы Brovin Yaroslav Опубликовано 29 сентября, 2014 Администраторы Поделиться Опубликовано 29 сентября, 2014 (изменено) Добрый вечер, Можно задействовать сенсоры из RTL напрямую: Запросить менеджер сенсоров System.Sensors.TSensorManager.Current; Запросить у менеджера сенсоров список сенсоров по категории TSensorCategory.Location TSensorManager.GetSensorsByFilter Выбрать из списка сенсоров необходимый. Проверив, доступные свойства TCustomLocationSensor.AvailableProperties, которые каждый может выдавать и другие характеристики сенсоров. Работать на прямую с выбранным сенсором локации TCustomLocationSensor P.S. Но по сути вы получите тот же объект, что и в компоненте TLocationSensor.Sensor. Правда без использования непосредственно компонента. Изменено 29 сентября, 2014 пользователем Brovin Yaroslav zairkz и Kitty 2 Цитата Ссылка на комментарий
0 Pax Beach Опубликовано 28 июня, 2016 Поделиться Опубликовано 28 июня, 2016 В 30.09.2014 в 23:57, Brovin Yaroslav сказал: Запросить менеджер сенсоров System.Sensors.TSensorManager.Current; Обнаружил нюанс: если обращаться к TSensorManager.Current из события POSIX таймера, монитор выдает такую ошибку: E/error(19014): - Сan't start sensor: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() А что это за лупер, и почему его нет в моем потоке, я пока ни как не могу разобраться. Цитата Ссылка на комментарий
0 Администраторы Brovin Yaroslav Опубликовано 29 июня, 2016 Администраторы Поделиться Опубликовано 29 июня, 2016 19 часов назад, Pax Beach сказал: А что это за лупер, и почему его нет в моем потоке, я пока ни как не могу разобраться. Эта реализация с Posix таймерами работает в отдельном треде. Который никак не связан с джава и андроидом. Поэтому, если вы хотите работать с сенсорами, вам достаточно синхронизировать вызов с главным тредом. Pax Beach 1 Цитата Ссылка на комментарий
0 Pax Beach Опубликовано 29 июня, 2016 Поделиться Опубликовано 29 июня, 2016 1 минуту назад, Brovin Yaroslav сказал: Эта реализация с Posix таймерами работает в отдельном треде. Который никак не связан с джава и андроидом. Поэтому, если вы хотите работать с сенсорами, вам достаточно синхронизировать вызов с главным тредом. Спасибо, Ярослав. Есть вопросы: какой вызов нужно синхронизировать с главным потоком и как это делается в Delphi? Сложный для моего понимания вопрос. Ни как не могу понять, как синхронизация позволяет передать в поток таймера контекст основного потока. Наверное, потому что кусками материал изучаю. Вот если бы пример на Java или, еще лучше, Delphi. Цитата Ссылка на комментарий
0 Модераторы Равиль Зарипов (ZuBy) Опубликовано 29 июня, 2016 Модераторы Поделиться Опубликовано 29 июня, 2016 если брать реализацию для андроида, то есть решение без сенсора в этой теме там в первом сообщении, вложение Pax Beach и zairkz 2 Цитата Ссылка на комментарий
0 Администраторы Brovin Yaroslav Опубликовано 29 июня, 2016 Администраторы Поделиться Опубликовано 29 июня, 2016 TThread.Synchronize; Вызывать из кода обработчика таймера Чтобы понять, как это происходит, нужно почитать о том, как работает UI Thread (например тут). В этой статье, как раз рассказывает, что такое лупер и как организуется "якобы многозадачность" (отрисовка, обработка событий и тд) в рамках одного треда. Синхронизация не передает контекст. В данном случае контекст привязан к потоку. Он является частью потока. Поэтому по сути, когда вы синхронизируете (по сути просто вызываете ваш код из лупера, то по сути вы уже работаете в контексте :-) Если заглянуть в исходники андроида: public final class Looper { // Вырезан код public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); } } ///------------------------------ } То есть по сути это просто бесконечный цикл, в котором из очереди вытаскиваются задания и выполняются по очереди. Как только возникает событие, оно просто складывается в очередь, и лупер в UI треде его просто обрабатывает. Когда вы вызываете TThread.Synchronize, то в конечном итоге ваш код завернется в сообщение, которое будет вызвано из этого куска кода zairkz, Pax Beach и Равиль Зарипов (ZuBy) 3 Цитата Ссылка на комментарий
0 Pax Beach Опубликовано 29 июня, 2016 Поделиться Опубликовано 29 июня, 2016 31 минуту назад, ZuBy сказал: если брать реализацию для андроида, то есть решение без сенсора в этой теме там в первом сообщении, вложение Спасибо, актуально. Но мои устройства работают без интернета, sim-карт и Wi-Fi, только GPS в сервисе. Соответственно, работать могу только с сенсором. Цитата Ссылка на комментарий
0 Pax Beach Опубликовано 30 июня, 2016 Поделиться Опубликовано 30 июня, 2016 (изменено) В 29.06.2016 в 12:00, Brovin Yaroslav сказал: TThread.Synchronize; Вызывать из кода обработчика таймера Попробовал синхронизацию — сервис зависает на вызове TThread.Synchronize. TJLocalBroadcastManager решил проблему, код ниже. Правда, когда приложение завершается, и сервис перезапускается, последний перестает ловить сообщения для ресивера, потому что сервис уничтожается, а поток остается жить. Видимо, я не правильно убиваю поток. Помогите пожалуйста понять, как уничтожить анонимный поток, когда завершаться сервис (или приложение)? procedure TSvcMain.AndroidServiceCreate(Sender: TObject); var LThread: TThread; begin MyService := JavaService; // глобальная переменная FThreads := TObjectList<TThread>.Create; RegisterReceiver; StartLocationSensor; LThread := TThread.CreateAnonymousThread( procedure begin Log('+ Thread [%d] started', [TThread.CurrentThread.ThreadID]); while TThread.CurrentThread.Started do begin Log('... Thread [%d] ticked', [TThread.CurrentThread.ThreadID]); Sleep(TimerInterval); if (not Assigned(MyService)) or (not TThread.CurrentThread.Started) then begin Log('- stop Thread [%d]', [TThread.CurrentThread.ThreadID]); break; end else begin TJLocalBroadcastManager.JavaClass.getInstance(MyService) .sendBroadcast(TJIntent.JavaClass.init(StringToJString(LocationAction))); end; end; TThread.CurrentThread.Terminate; end); LThread.FreeOnTerminate := false; FThreads.Add(LThread); LThread.Start; end; При уничтожении сервиса я пытаюсь убить поток: procedure TSvcMain.AndroidServiceDestroy(Sender: TObject); var i: Integer; begin StopLocationSensor; try for i := 0 to FThreads.Count - 1 do if Assigned(FThreads.Items[i]) then begin Log('Thread [%d] terminated', [FThreads.Items[i].ThreadID]); FThreads.Items[i].Terminate; end; finally FThreads.Free; end; end; Изменено 1 июля, 2016 пользователем Pax Beach Цитата Ссылка на комментарий
Вопрос
brunnengi
Здравствуйте.
Как получить координаты GPS без использования компонента TLocationSensors?
Ссылка на комментарий
8 ответов на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.