Android 位置服务已被Doze模式停止

Android 位置服务已被Doze模式停止,android,locationmanager,android-doze,Android,Locationmanager,Android Doze,我正在开发一款运动追踪应用程序,它使用位置管理器和gps提供商每秒获取位置更新,即使屏幕关闭,手机在口袋里 当用户在“我的活动”中按下“开始”按钮时,我将在前台启动服务,并显示通知和注册位置侦听器 服务开始接收位置更新并将其写入我的跟踪文件 突然,我收到一条日志消息“Power manager idle mode:true”,手机进入睡眠模式,我的服务停止获取任何位置更新,直到手机醒来 我阅读了有关的文档,发现它不应该影响定位服务,但在我的案例中确实如此 可能是我做错了什么。这是我的服务代码,非

我正在开发一款运动追踪应用程序,它使用位置管理器和gps提供商每秒获取位置更新,即使屏幕关闭,手机在口袋里

当用户在“我的活动”中按下“开始”按钮时,我将在前台启动服务,并显示通知和注册位置侦听器

服务开始接收位置更新并将其写入我的跟踪文件

突然,我收到一条日志消息“Power manager idle mode:true”,手机进入睡眠模式,我的服务停止获取任何位置更新,直到手机醒来

我阅读了有关的文档,发现它不应该影响定位服务,但在我的案例中确实如此

可能是我做错了什么。这是我的服务代码,非常感谢您的帮助

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

当启动操作设备空闲模式改变时,doze不是打开就是关闭的,这不是一个已知的情况。影响怠速模式的因素更多

尝试创建并获取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();
    }

我安装了一个监听器,用于记录设备进入睡眠模式的情况。另外,在《打瞌睡限制》中说“系统忽略唤醒锁”。发现M:,可能也是我的情况,但我不确定,因为我在android 7.1.1上也有同样的行为。