我已经相当成功地开始了一项服务。但在这个服务中,我有一个位置管理器,我开始从gps提供商那里获得位置更新。
位置管理器成功地将回调发送到我的ILocationManager。但在第二个手机进入睡眠(((PowerManager)GetSystemService(Context.PowerService)).IsScreenOn==false)
我在后台成功地处理了一个位置更新,但在那之后.没有更多的位置更新,是通过回调来的。即使我在前台显式地用startForeground()方法启动它。
为什么会这样?我做错什么了吗?
这里是我启动服务的地方(在MainActivity.cs中,通过Xamarin.FormContentPage的依赖注入)
public event EventHandler<ServiceConnectedEventArgs> LocationServiceConnected = delegate { };
protected RecordingServiceConnection recordingServiceConnection;
private static Intent locationServiceIntent = null;
/// <summary>
/// Start Track Recording Service
/// </summary>
/// <param name="toStart">object to use through service</param>
public void Start(object toStart)
{
// starting a service like this is blocking, so we want to do it on a background thread
new Task(() =>
{
// start our main service
Android.App.Application.Context.StartService(new Intent(Android.App.Application.Context,
typeof(RecordingService)));
// create a new service connection so we can get a binder to the service
this.recordingServiceConnection = new RecordingServiceConnection(null);
// this event will fire when the Service connection in the OnServiceConnected call
this.recordingServiceConnection.ServiceConnected += (object sender, ServiceConnectedEventArgs e) =>
{
// we will use this event to notify MainActivity when to start updating the UI
this.LocationServiceConnected(this, e);
};
// bind our service (Android goes and finds the running service by type, and puts a reference
// on the binder to that service)
// The Intent tells the OS where to find our Service (the Context) and the Type of Service
// we're looking for (RecordingService)
locationServiceIntent = new Intent(Android.App.Application.Context, typeof(RecordingService));
// Log.Debug(logTag, "Calling service binding");
// Finally, we can bind to the Service using our Intent and the ServiceConnection we
// created in a previous step.
Android.App.Application.Context.BindService(locationServiceIntent, recordingServiceConnection,
Bind.AutoCreate);
}).Start();
}
字符串
现在说的服务:
[Service]
public class RecordingService : Android.App.Service, ILocationListener
{
#region Events
public event EventHandler<LocationChangedEventArgs> LocationChanged = delegate { };
public event EventHandler<ProviderDisabledEventArgs> ProviderDisabled = delegate { };
public event EventHandler<ProviderEnabledEventArgs> ProviderEnabled = delegate { };
public event EventHandler<StatusChangedEventArgs> StatusChanged = delegate { };
#endregion
#region locals
//new location
private Location UpdatedLocation = null;
IBinder binder;
//Backgrounding
Timer backgroundInitialiser;
long recordingDelay = 3000; // TODO SET IN SETTINGS
private bool IsGpsEnabled = false;
#endregion
//
// Set our location manager as the system location service
protected LocationManager LocMgr = null;
//
private static PendingIntent pendingIntent = null;
#region Service
public override void OnCreate()
{
base.OnCreate();
try
{
Intent notificationIntent = new Intent(this, typeof(RecordingService));
pendingIntent = PendingIntent.GetActivity(this, 0,
notificationIntent, 0);
var notification = new Notification.Builder(this)
.SetContentTitle("App")
.SetContentText("App is running")
.SetSmallIcon(Resource.Drawable.icon)
.SetOngoing(true)
.SetContentIntent(pendingIntent)
.Build();
// Enlist this instance of the service as a foreground service
StartForeground(999, notification);
System.Diagnostics.Debug.WriteLine("OnCreate called in the Location Service");
}
catch(Exception ex)
{
throw;
}
}
// This gets called when StartService is called in our App class
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
System.Diagnostics.Debug.WriteLine("LocationService started");
// start a task here
new Task(async() =>
{
}).Start();
InitializeBackgroundWork();
return StartCommandResult.Sticky;
}
public override void OnDestroy()
{
base.OnDestroy();
System.Diagnostics.Debug.WriteLine( "Service has been terminated");
}
#endregion
private async void DoSomethinOnChange(object sender, LocationChangedEventArgs e)
{
UpdatedLocation = null;
try
{
await Task.Run(async () =>
{
try
{
Location location = e.Location;
var w= ((PowerManager)GetSystemService(Context.PowerService)).IsScreenOn;
if (w)
{
System.Diagnostics.Debug.WriteLine("INTO");
}
else
System.Diagnostics.Debug.WriteLine("NOT IN");
}
catch (Exception exception)
{
Console.WriteLine(exception);
throw;
}
});
}
catch (Exception exception)
{
Console.WriteLine(exception);
throw;
}
}
#region BackgroundWork
private Thread backgroundWorkThread = null;
/// <summary>
/// Start the ForeGrounding
/// </summary>
private void InitializeBackgroundWork()
{
try
{
Thread backgroundWorkThread = new Thread(() =>
{
if (backgroundInitialiser == null)
{
var autoEvent = new AutoResetEvent(false);
backgroundInitialiser = new Timer(new TimerCallback(PerformBackgroundWork), autoEvent, recordingDelay, recordingDelay);
GC.Collect();
}
else
backgroundInitialiser.Change(recordingDelay, recordingDelay);
StartLocationUpdates();
});
backgroundWorkThread.Start();
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}
/// <summary>
/// Performing foregrounding
/// </summary>
/// <param name="state"></param>
private async void PerformBackgroundWork(object state)
{
//BackgroundWork
await Task.Run(() =>
{
try
{
if (Track.isRecording)
{
try
{
backgroundInitialiser.Change(50000, 50000);
if (UpdatedLocation != null)
UpdateGPS(UpdatedLocation);
//REQUEST CUSTOM UPDATE , USE WAKE LOCK
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
finally
{
backgroundInitialiser.Change(recordingDelay, recordingDelay);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}
#endregion
#region Binder
// This gets called once, the first time any client bind to the Service
// and returns an instance of the LocationServiceBinder. All future clients will
// reuse the same instance of the binder
public override IBinder OnBind(Intent intent)
{
System.Diagnostics.Debug.WriteLine( "Client now bound to service");
binder = new RecordingServiceBinder(this);
return binder;
}
#endregion
// Handle location updates from the location manager, if Network is enabled we take network
public void StartLocationUpdates()
{
try
{
if(!Looper.MainLooper.IsCurrentThread)
Looper.Prepare();
if (LocMgr == null)
{
LocMgr = GetSystemService(LocationService) as LocationManager;
IsGpsEnabled = LocMgr.IsProviderEnabled(LocationManager.GpsProvider);
// IsNetworkEnabled = LocMgr.IsProviderEnabled(LocationManager.NetworkProvider);
if (IsGpsEnabled)
{
LocMgr.RequestLocationUpdates(LocationManager.GpsProvider, 3000, 0, this);
}
LocationChanged += DoSomethinOnChange; // assign delegate to write to file
}
System.Diagnostics.Debug.WriteLine("Now sending location updates");
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
/// <summary>
/// Gps Location Updated
/// </summary>
/// <param name="location"></param>
async void UpdateGPS(Location location)
{
UpdatedLocation = null;
await Task.Run(() =>
{
try
{
this.LocationChanged(this, new LocationChangedEventArgs(location));
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
});
}
#region ILocationListener
public void OnLocationChanged(Location location)
{
UpdatedLocation = location;
}
public void OnProviderDisabled(string provider)
{
this.ProviderDisabled(this, new ProviderDisabledEventArgs(provider));
}
public void OnProviderEnabled(string provider)
{
this.ProviderEnabled(this, new ProviderEnabledEventArgs(provider));
}
public void OnStatusChanged(string provider, Availability status, Bundle extras)
{
this.StatusChanged(this, new StatusChangedEventArgs(provider, status, extras));
}
#endregion
public void StopDoingSomeWork()
{
backgroundWorkThread?.Abort();
LocationChanged -= DoSomethinOnChange;
LocMgr.Dispose();
StopForeground(true);
backgroundInitialiser.Dispose();
StopSelf();
GC.Collect();
}
protected override void Dispose(bool disposing)
{
backgroundInitialiser.Dispose();
//backgroundWorkThread.Abort();
GC.Collect();
}
}
}
型
1条答案
按热度按时间qyuhtwio1#
编辑:目标是将位置管理器注册为服务。因此用户可以接受在后台运行的位置更新。需要通知来保持服务运行。
参见; MSDocs about Android Services
Xamarin Docs, Background Task的