Перейти к содержанию
Fire Monkey от А до Я
  • 0

Получение GPS координат из сервиса


Rusland

Вопрос

На радостях что сервис теперь может автоматически стартовать после перезагрузки системы (спасибо Ефимову Андрею), решил что пора научится получать координаты GPS через сервис.

 

Вариант 1.

 

Как-то я уже пробовал это сделать прицепив к dfm TLocationSensor, но был крах.

Сегодня я прочитал вот такую статейку где говорится как раз об этом - крошится из-за того что в System.Android.Sensors используется Activity, которое null (у нас же сервис, а не простое приложение) 

и предлагается решение в виде внесения изменение в System.Android.Sensors и System.Sensors.

Я внес указанные изменения (сами файлы в patch.zip прикрепил к сообщению), скачал их Демо пример отсюда, положил вышеуказанные файлы в папку patch, но при компиляции выдает 3 ошибки вида:

 

[DCC Error] System.SensorsDD.pas(805): E2010 Incompatible types: 'TSensorManager.TSensorManagerType' and 'class of TPlatformSensorManager'

[DCC Error] System.SensorsDD.pas(1144): E2361 Cannot access private symbol TGeocoder.GeocoderImplementer

[DCC Error] System.SensorsDD.pas(1449): E2362 Cannot access protected symbol TPlatformGpsStatus.GetGpsStatusImplementer

на строки соответственно

 

FSensorManagerType := TPlatformSensorManager;

TGeocoder.FCurrent := TPlatformGeocoder.GeocoderImplementer;

TGpsStatus.FCurrent := TPlatformGpsStatus.GetGpsStatusImplementer;

Попробуйте кто-нибудь скомпилировать у себя пожалуйста. Пример должен быть рабочий по идее...

 

тогда я решил действовать по другому:

 

Вариант 2.

 

Я вспомнил что можно обойтись без TLocationSensor и использовать LocationListener.

В сервисе  сделал так:

unit Unit2;

interface

uses
  System.SysUtils,
  System.Classes,
  System.Android.Service,
  AndroidApi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Os,
  Androidapi.JNI.App,
  Androidapi.JNI.Location,Androidapi.JNIBridge,Androidapi.JNI.JavaTypes,Androidapi.Helpers, // для координат
  AndroidApi.Log; // лог смотреть через monitor.bat

type
  TLocationListener = class;

  TAndroidServiceDM = class(TAndroidService)
    function AndroidServiceStartCommand(const Sender: TObject;
      const Intent: JIntent; Flags, StartId: Integer): Integer;
  private
    { Private declarations }
    FLocationManager: JLocationManager;
    locationListener: TLocationListener;
  public
    destructor Destroy; override;
    { Public declarations }
    procedure StartLocator();
    procedure onLocationChanged(Location: JLocation);
  end;

  TLocationListener = class(TJavaLocal, JLocationListener)
  private
    [weak]
    FParent: TAndroidServiceDM;
  public
    constructor Create(AParent: TAndroidServiceDM);
    procedure onLocationChanged(Location: JLocation); cdecl;
    procedure onProviderDisabled(provider: JString); cdecl;
    procedure onProviderEnabled(provider: JString); cdecl;
    procedure onStatusChanged(provider: JString; status: Integer; extras: JBundle); cdecl;
  end;

var
  AndroidServiceDM: TAndroidServiceDM;

implementation

{%CLASSGROUP 'FMX.Controls.TControl'}


{$R *.dfm}

function TAndroidServiceDM.AndroidServiceStartCommand(const Sender: TObject;
  const Intent: JIntent; Flags, StartId: Integer): Integer;
begin
  StartLocator();
  Result:=TJService.JavaClass.START_STICKY;
end;

destructor TAndroidServiceDM.Destroy;
begin
  if Assigned(locationListener) then
    FLocationManager.removeUpdates(locationListener);
  inherited;
end;

procedure TAndroidServiceDM.onLocationChanged(Location: JLocation);
var
  M: TMarshaller;
begin
  if Assigned(Location) then
  begin
    Logi(M.AsUtf8('LogLatitude '+ Location.getLongitude.ToString).ToPointer);
    Logi(M.AsUtf8('LogLongitude '+Location.getLongitude.ToString).ToPointer);
  end;
end;

procedure TAndroidServiceDM.StartLocator();
var
  LocationManagerService: JObject;
  GPSLocation, NetworkLocation: JLocation;
begin
  if not Assigned(FLocationManager) then
  begin
    LocationManagerService := SharedActivityContext.getSystemService(TJContext.JavaClass.LOCATION_SERVICE);
    FLocationManager := TJLocationManager.Wrap((LocationManagerService as ILocalObject).GetObjectID);
    if not Assigned(locationListener) then
      locationListener := TLocationListener.Create(self);                                    
    FLocationManager.requestLocationUpdates(TJLocationManager.JavaClass.GPS_PROVIDER, 10000, 0, locationListener,
      TJLooper.JavaClass.getMainLooper);                                                         
    FLocationManager.requestLocationUpdates(TJLocationManager.JavaClass.NETWORK_PROVIDER, 10000, 0, locationListener,
      TJLooper.JavaClass.getMainLooper);
  end;
  GPSLocation := FLocationManager.getLastKnownLocation(TJLocationManager.JavaClass.GPS_PROVIDER);
  NetworkLocation := FLocationManager.getLastKnownLocation(TJLocationManager.JavaClass.NETWORK_PROVIDER);
  onLocationChanged(GPSLocation);
  onLocationChanged(NetworkLocation);
end;

constructor TLocationListener.Create(AParent: TAndroidServiceDM);
begin
  inherited Create;
  FParent := AParent;
end;

procedure TLocationListener.onLocationChanged(Location: JLocation);
begin
  FParent.onLocationChanged(Location);
end;

procedure TLocationListener.onProviderDisabled(provider: JString);
begin

end;

procedure TLocationListener.onProviderEnabled(provider: JString);
begin

end;

procedure TLocationListener.onStatusChanged(provider: JString; status: Integer; extras: JBundle);
begin

end;

end.

После старта приложения, через несколько секунд оно морозится и система спрашивает "Подождать?". 

Расстановка breakpoint-ов мне не помогла, ошибка случается раньше Segment fault 11.

 

Пример в архиве ASARservRepair2.zip прикрепляю.

Посмотрите пожалуйста в чем может быть проблема?

ASARservRepair2.zip

patch.zip

Изменено пользователем Rusland
Ссылка на комментарий

Рекомендуемые сообщения

  • 0

PS. Первое решение оказалось рабочим... не знаю почему у меня вчера отказывалось нормально работать  :) Пользуйтесь.

 

PPS. Надеюсь Embarcadero исправит этот баг в следующей версии и не придется делать столько телодвижений )

 

Странно что после закрытия программы сервис перестает слать координаты - значок GPS пропадает. Хотя в Настройки->Приложения->Работающие я вижу как процесс перезапускается.

Изменено пользователем Rusland
Ссылка на комментарий
  • 0
В 29.01.2016 в 13:19, Rusland сказал:

Странно что после закрытия программы сервис перестает слать координаты - значок GPS пропадает. Хотя в Настройки->Приложения->Работающие я вижу как процесс перезапускается.

Rusland, не нашлось решение этой проблемы?

 

Ссылка на комментарий
  • 0
6 минут назад, Pax Beach сказал:

Пробую Ваше решение на 10 Update 1, но оно не до конца работает, как я понял из темы

А что значит не до конца работает? Вроде все работало... хоть в конечном итоге мне и пришлось отказаться от этой идеи.

Изменено пользователем Rusland
Ссылка на комментарий
  • 0
3 минуты назад, Rusland сказал:

А что значит не до конца работает?

Я имею ввиду фразу «Странно что после закрытия программы сервис перестает слать координаты - значок GPS пропадает. Хотя в Настройки->Приложения->Работающие я вижу как процесс перезапускается.». Эту проблему удалось решить?

Ссылка на комментарий
  • 0

Pax Beach, Насколько помню, там дело обстоит так (и это касается сервисов в целом), после закрытия приложения - сервис отключается и не подает признаков жизни, но через некоторое время снова начинает работать. Я думаю это сделано специально, чтобы в случае какой-нибудь ошибки, суметь добраться до Настроек и удалить приложение :) 

То есть по идее через какое-то время значок GPS снова появится... вот только не знаю чему это время равно.

Изменено пользователем Rusland
Ссылка на комментарий
  • 0

Rusland, второй способ вылетает с ошибкой, пробую первый способ (подключил в сервисе пропатченные модули ...DD, положил компонент TLocationSensor на форму) → при запуске сервиса вылетает ошибка и приложение закрывается. Подскажите, может я чего-то не сделал, например classes.dex надо как-то перестраивать или еще какие-нибудь ухищрения?

Код сервиса простой и лог монитора прилагаю.

function TAndroidServiceDM.AndroidServiceStartCommand(const Sender: TObject; const Intent: JIntent;
  Flags, StartId: Integer): Integer;
begin
//  JavaService.stopSelf;
//  Log.D('Serice started?');
  if not LocationSensor.Active then
    LocationSensor.Active := true;

  Result := TJService.JavaClass.START_STICKY;
end;

procedure TAndroidServiceDM.LocationSensorLocationChanged(Sender: TObject;
  const OldLocation, NewLocation: TLocationCoord2D);
var
  M: TMarshaller;
begin
//  if Assigned(NewLocation) then
//  begin
    Logi(M.AsUtf8('LogLatitude '+ NewLocation.Latitude.ToString).ToPointer);
    Logi(M.AsUtf8('LogLongitude '+NewLocation.Longitude.ToString).ToPointer);
//  end;
//  Log.D(Format('Coords:%8.8f;%8.8f', [NewLocation.Latitude, NewLocation.Longitude]));
end;

 

2016-05-05_12-55-35.png

Ссылка на комментарий
  • 0
42 минуты назад, Rusland сказал:

Нет, я неправ. Сейчас проверил. в 12:07 закрыл программу, значок GPS пропал и не появляется до настоящего времени (12:47) :(

Я пробую пример итальянского коллеги, он работает почему-то. В нем, когда убиваешь в памяти приложение, монитор выбрасывает такой Warning:

05-05 13:14:30.008: W/linker(22430): /data/app/com.embarcadero.LocationSensorDemo-1/lib/arm/libProxyAndroidService.so: is missing DT_SONAME will use basename as a replacement: "libProxyAndroidService.so"


Антенна GPS пропадает, лог больше ничего не собирает. Сервис самостоятельно не запускается.

 

Изменено пользователем Pax Beach
Ссылка на комментарий
  • 0
21 минуту назад, Rusland сказал:

Вот собрал проект на 10-ке LocationSensorPatch3.rar

Да, этот пример работает. Спасибо.

Описанная выше ошибка (не запускается сервис) вылетает, если я с нуля собираю проект. Видимо, как-то классы сервиса присоединять в classes.dex приложения нужно и пересобирать его.

 

Ссылка на комментарий
  • 0
3 минуты назад, Pax Beach сказал:

Видимо, как-то классы сервиса присоединять в classes.dex приложения нужно и пересобирать его.

Думаю что нет. Я же прислал пример без готового classes.dex 

Ссылка на комментарий
  • 0

Rusland, спасибо за пример 2.

Много времени потратил на изучение работы из под сервиса.

В итоге, в Berlin в сервисе отлично работает JLocationManager и JLocationListener.

 

Ссылка на комментарий
  • 0
2 минуты назад, MikeWuzHere сказал:

Удалось решить проблему с вылетом сервиса? Приложение закрываешь и все, координаты не летят.

Какое устройство, ОС, версия Delphi?

Ссылка на комментарий
  • 0
5 минут назад, Pax Beach сказал:

Какое устройство, ОС, версия Delphi?

Андроид (Le Eco Le 2, самсунг гал 3), 10 seattle. Проблема в том, что как только чистится память или закрывается приложени в ручную умирает и сервис, точнее не сам сервис, а координаты идти перестают.

Ссылка на комментарий
  • 0
1 час назад, MikeWuzHere сказал:

Андроид (Le Eco Le 2, самсунг гал 3), 10 seattle. Проблема в том, что как только чистится память или закрывается приложени в ручную умирает и сервис, точнее не сам сервис, а координаты идти перестают.

Что наталкивает нас на мысльо том, что либо сервис стартует без команды дальнейшего перезапуска, либо не перезапускается, либо запускается и валится с ошибкой.

Лог монитор в помощь. Что показывает?

Ссылка на комментарий
  • 0
Только что, Pax Beach сказал:

Что наталкивает нас на мысльо том, что либо сервис стартует без команды дальнейшего перезапуска, либо не перезапускается, либо запускается и валится с ошибкой.

Лог монитор в помощь. Что показывает?

Вроде писал start sticky, но почему то по выходу с приложения и сервиса не видно. С логами не разобрался как работать, но вот вроде что то нарыл (до этого видел что туда летят координаты).

592d0eb0736bc_.png.43c3d68ca30bfad7884457bac1b9d0a4.png

Судя по логам по завершеню работы самой программы - умирает и сервис, но старт стики почему то не срабатывает О_О

Ссылка на комментарий
  • 0
3 минуты назад, MikeWuzHere сказал:

Вроде писал start sticky, но почему то по выходу с приложения и сервиса не видно. С логами не разобрался как работать, но вот вроде что то нарыл (до этого видел что туда летят координаты).

592d0eb0736bc_.png.43c3d68ca30bfad7884457bac1b9d0a4.png

Судя по логам по завершеню работы самой программы - умирает и сервис, но старт стики почему то не срабатывает О_О

Что-то не так в логах. Фигурирует три пакета com.embarcadero... А должно быть максимум два.

Надо всё почистить и заново собрать. Если не заработает, смотреть код.

GPS трекер отлично работает нас телефонах. Только Xiomi не победил пока.

Ссылка на комментарий
  • 0
Только что, Pax Beach сказал:

Что-то не так в логах. Фигурирует три пакета com.embarcadero... А должно быть максимум два.

Надо всё почистить и заново собрать. Если не заработает, смотреть код.

GPS трекер отлично работает нас телефонах. Только Xiomi не победил пока.

А я код и не менял, пример от RUSLAND который был собран им под 10ку, все стоковое, собрал и вот такое вот.  Не менял прям вот совсем ничего, может как то по другому можно логи отфильтровать? 

Ссылка на комментарий
  • 0
В 30.05.2017 в 12:27, Pax Beach сказал:

Что-то не так в логах. Фигурирует три пакета com.embarcadero... А должно быть максимум два.

Надо всё почистить и заново собрать. Если не заработает, смотреть код.

GPS трекер отлично работает нас телефонах. Только Xiomi не победил пока.

Можете сделать сэмпл? Уже установил Rad Studio Tokio, сменил мобильник на LG, проблема не решается. Как только я тапаю на кнопку домой то gps данные перестают лететь в логи, а как только закрываю приложение то пропадает значок gps.

p.s. я уже было за голову схватился, но оказалось что gps все же шлет данные в свернутом виде. Проблема при закрытии самого приложения осталась. 

Прикладываю логи: 

Цитата

06-06 15:01:07.785: I/info(4760): New location available -> Latitude: 40,278767, Longitude: 70,895717 
06-06 15:01:15.730: I/info(4760): FMX: LocationSensorDemo: [Context Exception]: Error in context method 'DoFinalizeShader'.
06-06 15:01:15.730: I/info(4760): FMX: LocationSensorDemo: [Context Exception]: Error in context method 'DoFinalizeShader'.
06-06 15:01:15.730: I/info(4760): FMX: LocationSensorDemo: [Context Exception]: Error in context method 'DoFinalizeShader'.
06-06 15:01:15.730: I/info(4760): FMX: LocationSensorDemo: [Context Exception]: Error in context method 'DoFinalizeShader'.
06-06 15:01:17.307: W/linker(5097): /data/app/com.embarcadero.LocationSensorDemo-1/lib/arm/libProxyAndroidService.so: unused DT entry: type 0xf arg 0x8f21
06-06 15:01:17.307: W/linker(5097): /data/app/com.embarcadero.LocationSensorDemo-1/lib/arm/libProxyAndroidService.so: is missing DT_SONAME will use basename as a replacement: "libProxyAndroidService.so"
06-06 15:01:17.325: W/linker(5097): /data/app/com.embarcadero.LocationSensorDemo-1/lib/arm/libLocationService.so: unused DT entry: type 0xf arg 0x9f19
06-06 15:01:17.325: W/linker(5097): /data/app/com.embarcadero.LocationSensorDemo-1/lib/arm/libLocationService.so: is missing DT_SONAME will use basename as a replacement: "libLocationService.so"

 

Изменено пользователем MikeWuzHere
Ссылка на комментарий
  • 0
В 06.06.2017 в 14:59, M1shQa сказал:

Можете сделать сэмпл? Уже установил Rad Studio Tokio, сменил мобильник на LG, проблема не решается. Как только я тапаю на кнопку домой то gps данные перестают лететь в логи, а как только закрываю приложение то пропадает значок gps.

p.s. я уже было за голову схватился, но оказалось что gps все же шлет данные в свернутом виде. Проблема при закрытии самого приложения осталась. 

Прикладываю логи: 

 

Такая же проблема! А еще не понятно как вытащить адрес...

Ссылка на комментарий
  • 0
13 часов назад, gutalin79 сказал:

Такая же проблема! А еще не понятно как вытащить адрес...

Для работы локатора в свернутом приложении, стоит работу с GPS вынести в сервис. Понятно, что это только для Android.

Вытащить адрес, видимо речь о почтовых адресах, нужно использовать API Google services, у них такое есть.

 

Ссылка на комментарий
  • 0
6 часов назад, Pax Beach сказал:

Для работы локатора в свернутом приложении, стоит работу с GPS вынести в сервис. Понятно, что это только для Android.

Вытащить адрес, видимо речь о почтовых адресах, нужно использовать API Google services, у них такое есть.

 

      В System.Android.SensorsDD тоже что-то такое есть.

      Addr.AdminArea       := JStringToString(LAddress.getAdminArea);
      Addr.CountryName     := JStringToString(LAddress.getCountryName);
      Addr.CountryCode     := JStringToString(LAddress.getCountryCode);
........
      Addr.SubLocality     := JStringToString(LAddress.getSubLocality);
      Addr.SubThoroughfare := JStringToString(LAddress.getSubThoroughfare);
      Addr.Thoroughfare    := JStringToString(LAddress.getThoroughfare);

только я так и не вытащил город или улицу и т.д....

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...