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);
}
}
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. –