我正在尝试在
Xamarin
中制作一个 GPS 跟踪应用程序,它也可以在后台运行。目前我创建了一项服务,每两秒检查一次设备的位置。
我目前正在 Android Honor 10 上测试它,我注意到当我使用 Visual Studio 启动调试应用程序时,保持手机连接到 PC,它可以不间断地工作。
另一方面,如果我在没有调试的情况下尝试该应用程序,一段时间后,如果我将其放在后台,它就会停止跟踪 GPS。
所以这是我在主项目中的服务:
public class TrackingService
{
readonly bool stopping = false;
public TrackingService()
{
}
public async Task Run(CancellationToken token)
{
await Task.Run(async () => {
while (!stopping)
{
token.ThrowIfCancellationRequested();
try
{
await Task.Delay(2000);
var request = new GeolocationRequest(GeolocationAccuracy.Best);
var location = await Geolocation.GetLocationAsync(request);
//Other stuff like writing coordinates into a local database
}
catch (Exception ex)
{
Device.BeginInvokeOnMainThread(() =>
{
//Error
});
}
}
return;
}, token);
}
}
这是Android项目服务的启动:
[Register("com.companyname.dolomicchiostreetapp.TrackingService")]
public class AndroidLocationService : Service
{
CancellationTokenSource _cts;
public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
_cts = new CancellationTokenSource();
Notification notif = DependencyService.Get<INotification>().ReturnNotif();
StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notif);
Task.Run(() => {
try
{
var locShared = new TrackingService();
locShared.Run(_cts.Token).Wait();
}
catch (OperationCanceledException)
{
}
finally
{
if (_cts.IsCancellationRequested)
{
var message = new StopServiceMessage();
Device.BeginInvokeOnMainThread(
() => MessagingCenter.Send(message, "ServiceStopped")
);
}
}
}, _cts.Token);
return StartCommandResult.Sticky;
}
public override void OnDestroy()
{
if (_cts != null)
{
_cts.Token.ThrowIfCancellationRequested();
_cts.Cancel();
}
base.OnDestroy();
}
}
这是我的
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.dolomicchiostreetapp">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
<application android:label="dolomicchiostreetapp.Android" android:theme="@style/MainTheme">
<service android:enabled="true" android:foregroundServiceType="location" android:exported="false" android:name="com.companyname.dolomicchiostreetapp.TrackingService" />
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
</manifest>
我遵循了这个 github 示例:XamarinForms.LocationService
有人遇到过这个问题吗?
感谢那些帮助我的人。
请参阅 对后台跟踪的有限更新 - “Android 8.0(API 级别 26)及更高版本 - Android 通过以下方式保持设备电池寿命......如果您的应用程序在后台运行,则每次只能接收几次 位置更新小时”。
Foreground Service
。
这是个好主意,配置应用程序忽略电池优化;
android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
你可以这样做。
Intent intent = new Intent();
String packageName = MainActivity.Instance.PackageName;
PowerManager pm = (PowerManager)MainActivity.Instance.GetSystemService(Context.PowerService);
if (!pm.IsIgnoringBatteryOptimizations(packageName))
{
intent.SetAction(Android.Provider.Settings.ActionRequestIgnoreBatteryOptimizations);
intent.SetData(Android.Net.Uri.Parse("package:" + packageName));
MainActivity.Instance.StartActivity(intent);
}