2016-12-18 68 views
2

我正在開發體育跟蹤應用程序,即使屏幕關閉並且手機在口袋裏,也使用位置管理器和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); 
} 
} 
+0

發現對M這個Android的bug:https://code.google.com/p/android/issues/detail?id=193802,也許這是我的情況太多,但我不知道,因爲我得到了相同的行爲也在android 7.1.1上。 –

回答

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

我有聽衆安裝了這個日誌輸出設備進入休眠模式。另外在'打盹限制'中說'系統忽略喚醒鎖定'。 –