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.1 引用计数(Delphi XE10.1 Berlin终于增加了对接口的Weak, UnSafe的支持)