打盹模式停止了位置服务

时间:2016-12-18 21:29:19

标签: android locationmanager android-doze

我正在开发运动跟踪应用程序,该应用程序使用位置管理器和gps提供程序每秒获取位置更新,即使屏幕关闭且手机放在口袋中也是如此。

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

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

突然我收到日志消息'电源管理器空闲模式:是',电话进入打盹模式,我的服务停止获取任何位置更新,直到电话唤醒。

我阅读了有关Doze mode的文档,并发现它不应该影响位置服务,但在我的情况下确实如此。

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

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

1 个答案:

答案 0 :(得分:-1)

当触发ACTION_DEVICE_IDLE_MODE_CHANGED时,打开或关闭打盹是不明确的。还有更多因素会影响空闲模式。

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