我一直非常成功地开始服务。但是在这项服务中,我有一位位置经理,我开始从gps提供商那里获得位置更新。
位置管理器成功将回调发送到我的ILocationListener。 但是第二次手机进入睡眠状态(((PowerManager)GetSystemService(Context.PowerService))。IsScreenOn == false)
我在后台成功处理了一个位置更新,但之后... 没有更多的位置更新,即将进行回调。即使我使用startForeground()方法在前台显式启动它。
为什么会这样?我做错了吗?
这是我开始服务的地方(在MainActivity.cs中,来自Xamarin.Form ContentPage的trought依赖注入)
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 trought 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 connectin 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 Newtwork 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();
}
}
}
答案 0 :(得分:0)
我设法找到一种方法来欺骗用户手机处于睡眠状态,屏幕仍被检测为屏幕关闭,基本上我在后台工作时使用了唤醒锁
这是我使用的方法:
private async void PerformBackgroundWork(object state)
{
//BackgroundWork
await Task.Run(() =>
{
try
{
if (Track.isRecording)
{
try
{
backgroundInitialiser.Change(50000, 50000);
if (UpdatedLocation != null)
UpdateGPS(UpdatedLocation);
else
{
//REQUEST CUSTOM UPDATE , USE WAKE LOCK
PowerManager pm = ((PowerManager)GetSystemService(Context.PowerService));
PowerManager.WakeLock wl = pm.NewWakeLock(WakeLockFlags.ScreenDim,"00");
wl.Acquire();
Criteria c = new Criteria()
{
Accuracy = Accuracy.NoRequirement,
PowerRequirement = Power.NoRequirement
};
LocMgr.RequestSingleUpdate(c, this,this.MainLooper);
wl.Release();
pm = null;
wl=null;
c = null;
GC.Collect();
}
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
finally
{
backgroundInitialiser.Change(recordingDelay, recordingDelay);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}