2016-12-18 1 views
2

Je développe l'application de suivi de sport qui utilise le gestionnaire de localisation et le fournisseur GPS pour obtenir des mises à jour de localisation chaque seconde même si l'écran est éteint et le téléphone est dans la poche.Le service de localisation a été arrêté par le mode Doze

Lorsque l'utilisateur appuie sur le bouton de démarrage de mon activité, je démarre le service à l'avant-plan, affiche la notification et enregistre l'emplacement.

Le service commence à recevoir les mises à jour de position et les écrit dans mon fichier de piste. Soudainement, je reçois un message de consignation 'Mode inactif du gestionnaire d'énergie: vrai', le téléphone passe en mode Doze et mon service cesse d'obtenir une mise à jour jusqu'à ce que le téléphone se réveille.

Je lis des documents sur Doze mode et je vois que cela ne devrait pas affecter les services de localisation, mais c'est le cas dans mon cas.

Peut-être que je fais quelque chose de mal. Voici le code de mon service, toute aide est vraiment appréciée.

public class LocService 
    extends Service 
implements LocationListener, GpsStatus.Listener 
{ 

private String mName; 
private volatile Looper mServiceLooper; 
private volatile ServiceHandler mServiceHandler; 
private LocationManager locationManager; 

public LocService(String name) 
{ 
    super(); 
    mName = name; 
} 

private final class ServiceHandler extends Handler 
{ 
    public ServiceHandler(Looper looper) 
    { 
     super(looper); 
    } 

    @Override 
    public void handleMessage(Message msg) 
    { 
     if (msg != null && msg.obj != null) 
     { 
      onHandleIntent((Intent)msg.obj); 
     } 
     else 
     { 
      logMessage("msg for intent is not good"); 
     } 
    } 
} 

@Override 
public void onCreate() 
{ 
    super.onCreate(); 
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); 
    thread.start(); 

    mServiceLooper = thread.getLooper(); 
    mServiceHandler = new ServiceHandler(mServiceLooper); 

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
    { 
     logMessage("Enabling Doze mode listener"); 
     IntentFilter filter = new IntentFilter(); 
     filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 
     registerReceiver(new BroadcastReceiver() 
     { 
      @Override 
      public void onReceive(Context context, Intent intent) 
      { 
       onDeviceIdleChanged(); 
      } 
     }, filter); 
    } 

    locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); 
} 

@TargetApi(Build.VERSION_CODES.M) 
private void onDeviceIdleChanged() 
{ 
    PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); 
    if(powerManager != null) 
    { 
     logMessage("Power manager idle mode: " + powerManager.isDeviceIdleMode()); 
    } else 
    { 
     logMessage("Power manager idle changed to ?"); 
    } 
} 

protected void onHandleIntent(Intent intent) 
{ 
    //call start/stop location logging on proper intent 
    if(intent.getIntExtra("cmd", -1) == 1) 
    { 
     startLogging(); 
    } else 
    { 
     stopLogging(); 
    } 
} 

private void startLogging() 
{ 
    logMessage("LocationService.startLogging"); 
    try 
    { 
     locationManager.addGpsStatusListener(this); 
     locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 0, this); 
     logMessage("requesting gps updates"); 

     startForeground(ONGOING_NOTIFICATION, getNotification(-1, -1, true, false)); 
     logMessage("Sending foreground service notification"); 

    } 
    catch (SecurityException ex) 
    { 
     logMessage(" SecurityException while requesting location info: " + ex); 
    } 
} 

private void stopLogging() 
{ 
    try 
    { 
     locationManager.removeUpdates(this); 

     stopForeground(true); 
     notificationManager.cancel(ONGOING_NOTIFICATION); 
    } 
    catch (SecurityException ex) 
    { 
     logMessage(" SecurityException on stopLogging with location manager: " + ex); 
    } 

} 


@Override 
public void onLocationChanged(Location location) 
{ 
    //save location lat, lon directly to track file 
    //flush file 
} 

@Override 
public void onStatusChanged(String provider, int status, Bundle extras) 
{ 
    //do nothing 
} 

@Override 
public void onProviderEnabled(String provider) 
{ 
    logMessage("Location provider enabled " + provider); 
} 

@Override 
public void onProviderDisabled(String provider) 
{ 
    logMessage("Location provider disabled " + provider); 
} 

@Override 
public void onGpsStatusChanged(int event) 
{ 
    try 
    { 
     logMessage(" *** onGpsStatusChanged with " + event); 
     GpsStatus status = locationManager.getGpsStatus(null); 
     int inFix = 0; 
     int total = 0; 
     for (GpsSatellite satellite : status.getSatellites()) 
     { 
      if (satellite.usedInFix()) inFix++; 
      total++; 
     } 
     logMessage(" Sats: " + total + " in fix " + inFix); 
    } 
    catch (SecurityException sex) 
    { 
    } 
    catch (Exception ex) 
    { 
    } 
} 

@Override 
public void onStart(Intent intent, int startId) 
{ 
    Message msg = mServiceHandler.obtainMessage(); 
    msg.arg1 = startId; 
    msg.obj = intent; 
    mServiceHandler.sendMessage(msg); 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) 
{ 
    onStart(intent, startId); 
    return START_STICKY; 
} 

@Override 
public void onDestroy() 
{ 
    mServiceLooper.quit(); 
    try 
    { 
     locationManager.removeUpdates(this); 
    } 
    catch (SecurityException ex) 
    { 
     logMessage(" SecurityException on Destroy service with location manager: " + ex); 
    } 
} 

@Override 
public IBinder onBind(Intent intent) 
{ 
    return null; 
} 

private void logMessage(String msg) 
{ 
    Log.i("LocServ", msg); 
} 
} 
+0

trouvé ce bug Android M: https://code.google.com/p/android/issues/detail?id=193802, c'est probablement mon cas aussi, mais je ne suis pas sûr que je suis même comportement sur Android 7.1.1 aussi. –

Répondre

-1

Il est pas donné que lorsque ACTION_DEVICE_IDLE_MODE_CHANGED est tiré, somnoler a été soit allumé ou éteint. Il y a plus de facteurs qui peuvent affecter le mode inactif.

Essayez de créer et d'acquérir WakeLock.

PowerManager.WakeLock getLock(Context context, String lockName) { 
     if (wakeLock == null) { 
      PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 
      wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName); 
     } 
     return wakeLock; 
    } 

    //on start service 
    getLock(ctxt.getApplicationContext(), "lockName").acquire(); 


    //on destroy service 
    @Override 
    public void onDestroy() { 
     PowerManager.WakeLock lock = getLock(this.getApplicationContext(), "lockName"); 
     if (lock.isHeld()) { 
      lock.release(); 
     } 
     super.onDestroy(); 
    } 
+1

J'ai l'écouteur installé qui fait cette sortie de journal au sujet de l'appareil entrant dans le mode de somnolence. Toujours dans «Doze Restrictions», il est dit que «le système ignore les verrous de sillage». –