delphi xe10 android服务gps [重复]

Posted

技术标签:

【中文标题】delphi xe10 android服务gps [重复]【英文标题】:delphi xe10 android service gps [duplicate] 【发布时间】:2016-03-12 00:05:42 【问题描述】:

我正在使用Emabarcadero Delphi XE 10 Seattle Update 1 创建一个 android 服务,我找到了本教程 Link 并创建了一个服务应用程序,我想要做的是每 5 秒使用位置传感器获取当前位置并保存到数据库。我在我的主窗体上这样做,但是当我关闭程序时它停止了,所以我找不到任何关于如何同步我的应用程序和服务的文章。我尝试将计时器和位置传感器添加到服务表单,但 Delphi 不允许我将任何对象添加到服务表单,我认为我需要向服务发送命令或者我需要以某种方式连接服务和程序,我找到了一个示例这显示了如何使用服务下载图像,但对于像我这样的新手来说太专业了:)

【问题讨论】:

相关(Java):***.com/questions/8828639/… 除了服务之外,您还需要 AlarmManager 来重复调用服务 @mjn 感谢提醒,我想我错过了,再次感谢。 您的应用程序需要专家开发完成。这不是一个“新手”任务。 此问题与链接中的问题不重复。 【参考方案1】:

查看this 文章。 Daniele Spinetti 在服务中使用 LocationSensor 解决问题。

将 System.Sensors 和 System.Android.Sensors 单元放入您的项目并进行更改(Delphi 10 Seattle)。

System.Sensors.pas

// about line 748
implementation
uses
  System.Variants, System.Math, System.Character,
$IFDEF ANDROID
  // -- patch 
  // include the modified System.Android.Sensors
  System.Android.Sensors;
$ENDIF ANDROID

System.Android.Sensors.pas

//about line 12
uses
  // -- patch 
  // use the modified System.Sensors
  System.Sensors;
...
// about line 70
class constructor TPermission.Create;
var
  PackageInfo: JPackageInfo;
  PackageManager: JPackageManager;
  Activity: JActivity;
  LContext: JContext;
begin
  // -- patch 
  // Activity := TJNativeActivity.Wrap
  // (PANativeActivity(System.DelphiActivity)^.clazz)
  LContext := TJContextWrapper.Wrap(System.JavaContext);
  PackageManager := LContext.getPackageManager();
  PackageInfo := PackageManager.getPackageInfo
    (LContext.getApplicationContext.getPackageName,
    TJPackageManager.JavaClass.GET_PERMISSIONS);
  FPermissions := PackageInfo.requestedPermissions;
end;
...
// about line 100
type
  TAndroidGeocoder = class(TGeocoder)
  private type
    TGeocoderRunnable = class(TJavaLocal, JRunnable)
    private
      FCoord: TLocationCoord2D;
      FLGeocoder: JGeocoder;
    public
      constructor Create(ACoord: TLocationCoord2D; AGeocoder: JGeocoder);
      procedure run; cdecl;
    end;
  private
  class var
    FGeocoder: JGeocoder;
    // FActivity: JActivity; // -- patch 
    FActivity: JContextWrapper; // -- patch 
...
// about line 130
  TUIAndroidLocationSensor = class(TCustomLocationSensor)
  private
    FPermitted: Boolean;
    // FActivity: JNativeActivity; // -- patch 
    FActivity: JContext; // -- patch 
    FLastValue: JLocation;
    FLocationManager: JLocationManager;
    FAccuracy: TLocationAccuracy;
...
// about line 1500
constructor TUIAndroidLocationSensor.Create(AManager: TSensorManager);
var
  LocationService: JObject;
begin
  inherited;
  // FActivity := TJNativeActivity.Wrap
  // (PANativeActivity(System.DelphiActivity)^.clazz); // -- patch 
  FActivity := TJContext.Wrap(System.JavaContext); // -- patch 
  LocationService := FActivity.getSystemService
    (TJContext.JavaClass.LOCATION_SERVICE);
  if Assigned(LocationService) then
    FLocationManager := TJLocationManager.Wrap((LocationService as ILocalObject)
      .GetObjectID);
end;
...
// about line 1530
  function RunIfPossible(var ARunnable: TLocationRunnable;
    var AListener: TLocationListener; AProviderName: JString): Boolean;
  var
    Provider: JLocationProvider;
    LHandler: JHandler;
  begin
    Result := False;
    if FLocationManager.isProviderEnabled(AProviderName) then
    begin
      if AListener = nil then
        AListener := TLocationListener.Create(Self);
      Provider := FLocationManager.getProvider(AProviderName);
      if Provider <> nil then
      begin
        ARunnable := TLocationRunnable.Create(FLocationManager, AListener,
          AProviderName);
        // FActivity.runOnUiThread(ARunnable); // --patch 
        // -- patch 
        // You can use post method of Handler instead runOnUiThread in this case.
        // more info here: http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html
        LHandler := TJHandler.JavaClass.init;
        LHandler.post(ARunnable);
        Result := True;
      end;
    end;
  end;
...
// about line 1730
class constructor TAndroidGeocoder.Create;
begin
  // -- patch 
  // FActivity := TJNativeActivity.Wrap
  // (PANativeActivity(System.DelphiActivity)^.clazz);
  FActivity := TJContextWrapper.Wrap(System.JavaContext);
  FGeocoder := TJGeocoder.JavaClass.init(FActivity);
end;

然后你可以像这样使用 LocationSensor:

uses System.Sensors, System.Android.Sensors;
...
var
  FSensors: TSensorArray;
  Sensor: TCustomSensor;
begin
  TSensorManager.Current.Active := true;
  FSensors := TSensorManager.Current.GetSensorsByCategory(TSensorCategory.Location);

  FSensor := nil;
  for Sensor in FSensors do
  begin
    if TCustomLocationSensor(Sensor).SensorType = TLocationSensorType.GPS then
    begin
      FSensor := TCustomLocationSensor(Sensor);
      Break;
    end;
  end;

  if not Assigned(FSensor) then
    Exit;  no location sensor is available 

   start the sensor if it is not started 
  if not FSensor.Started then
    FSensor.Start;

【讨论】:

我添加了文章中的主要代码更改。现在好了? 比以前更好。如果可行,也比公认的答案更好。 这是工作方法。我在我的应用程序中使用它。但是我坚持使用计时器 - TTimer 在服务中不起作用。有什么建议吗?【参考方案2】:

如果 TTimer 没有按预期工作,请尝试在匿名线程中执行所有操作并在主线程中使用 TThread.CurrentThread.Sleep

function TServiceModule.AndroidServiceStartCommand(const Sender: TObject;
  常量意图:JIntent;标志,StartId:整数):整数;
开始
  结果:= TJService.JavaClass.START_STICKY;

  TThread.CreateAnonymousThread(过程
    开始
      重复
        TThread.Current.Sleep(MSecsPerSec);
        TThread.CreateAnonymousThread(过程
          做东西();
        结束)。开始;
        TThread.Current.Sleep(MSecsPerSec);
      直到(TThread.Current.CheckTerminated);
    结束)。开始;
结尾;

【讨论】:

以上是关于delphi xe10 android服务gps [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Android实例-Delphi开发蓝牙官方实例解析(XE10+小米2+小米5)

Delphi XE10在 Android下调用静态库a文件

gps在DELPHI全职安装android服务的位置

delphi xe10 手机程序事件服务操作退出键操作

Delphi XE10.1 引用计数

Delphi XE10.1 引用计数(Delphi XE10.1 Berlin终于增加了对接口的Weak, UnSafe的支持)