2015-12-07 94 views
4

我正在使用Emabarcadero Delphi XE 10西雅图更新1创建一个Android服务,我发现本教程Link并创建了一个服务应用程序,我想要做的是每5秒钟获取当前位置传感器并保存到数据库。我在我的mainform上这样做,但是当我关闭程序时,它停止了,所以我找不到任何有关如何将我的应用程序和服务同步的文章。我试图添加计时器和Locationsensor服务窗体,但Delphi不允许我添加到服务窗体的任何对象,我想我需要发送命令服务或以某种方式我需要连接服务和程序,我发现一个示例其中显示如何下载服务的图像,但它是像我这样的菜鸟太专家:)delphi xe10 android服务gps

+5

相关(用于Java):http://stackoverflow.com/questions/8828639/android-get-gps- location-via-a-service – mjn

+0

除了服务之外,您还需要AlarmManager重复拨打服务 – mjn

+0

@mjn感谢您的支持,我想我已经错过了,再次感谢。 – BMF

回答

1

看看文章。 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; 
+0

我添加了文章中的主要代码更改。现在可以了? – Rusland

+0

比以前更好。如果它能工作,也比接受的答案好。 – FlanschiFox

+0

这是工作方法。我在我的应用程序中使用它。然而我坚持计时器 - TTimer不工作服务。任何建议? – Rusland

1

如果TTimer不像你以前那样工作pected尝试做在匿名的线程你所有的东西,并使用TThread.CurrentThread.Sleep在主线程

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

    TThread.CreateAnonymousThread(procedure 
    begin 
     repeat 
     TThread.Current.Sleep(MSecsPerSec); 
     TThread.CreateAnonymousThread(procedure 
      DoStuff(); 
     end).Start; 
     TThread.Current.Sleep(MSecsPerSec); 
     until (TThread.Current.CheckTerminated); 
    end).Start; 
end;