Перейти к содержанию
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
В 25.08.2018 в 17:54, gutalin79 сказал:

      В 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);

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

У большинства пользователей, если не у всех, эти параметры, касаемо адреса, будут занулены.

Без интернета и API (того же гугла) этот вопрос не решить.

 

Ссылка на комментарий
  • 0
В 30.05.2017 в 09:04, krapotkin сказал:

ну вроде 100 раз писали, что из телефона трекер не нужно делать. мобильные ОС против.

1. Не зря их нарекли гуглофонами.

2. Однако, JAVA - программы работают отиично! Тот же Locus. Просто Embarcadero не по себе ношу тянет.

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

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

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

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

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

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

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

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

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

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

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