2017-05-22 9 views
1

私はサービスを開始するのにかなり成功している。しかし、このサービスの中で、私はgpsプロバイダーからの位置情報の更新を開始するロケーションマネージャーを持っています。電話がスリープ状態になったときにロケーションマネージャが位置更新を停止しないようにする。Xamarin.Android

ロケーションマネージャは、ILocationListenerにコールバックを正常に送信しました。 しかし、第二に電話がスリープ状態に入る(((PowerManager)GetSystemService(Context.PowerService))。IsScreenOn == falseが)

私は1回の場所の更新が正常にバックグラウンドではなく、その後に処理... をこれ以上得ませんでした場所の更新がコールバックを処理しています。場合でも私は明示的にstartForeground()メソッドでフォアグラウンドで起動します。

なぜこのように動作しますか?私は何か間違っているのですか?

[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
:私は今

 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(); 
    } 

(MainActivity.cs、Xamarin.Form ContentPageからtrought依存性注入に)私のサービスを開始するのはここ

は言っサービスです

私は、電話をスリープ状態にしているユーザーを騙す方法を見つけることができた、画面はまだ画面として検出され、基本的には私のバックグラウンドの仕事で起床ロックを使用したここ は、私が使用した方法である:私は本当にこだわっています

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; 
      } 
     }); 
    } 
関連する問題