簡體   English   中英

當應用程序在后台運行時,如何保持GPS接收器位置更新(Google Play服務位置API)

[英]How to keep GPS receiver location updates when the app is in background ( Google Play Service Location API)

抱歉,這是一個很長的問題,但是我希望你們中的一位專家可以幫助正在悄悄發瘋的新手!

我有一個Android應用程序,該應用程序每20秒使用后台服務獲取GPS修復(使用Google Play服務)。 它將緯度和經度與列表中的緯度和經度進行比較,如果找到匹配項,則會將廣播發送到接收器,從而觸發前台活動以警告用戶。

我使用后台服務是因為用戶提醒之間通常需要2到20分鍾之間,並且在此之間沒有用戶交互。 該應用程序使用前景活動供用戶選擇他想要的選項,但隨后關閉所有前景活動,僅使背景活動運行。

在我的舊設備上的Android 4.3上運行良好,但現在我更新了它在Android 8(Oreo)上運行(在Sony Xperia XZ1Compact上進行了測試)。 我已經添加了

<uses-permission 
android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/

到清單上,這導致該應用在首次運行時要求獲得許可。 然后,我的設備設置顯示該應用程序具有允許的節能例外。

后台服務的代碼(很抱歉,其中有很多,但是我將它們包括在內以防萬一!)

package com.barney.trackgps;

import android.Manifest;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;



public class ApiTrackService extends Service implements
    GoogleApiClient.ConnectionCallbacks, 
GoogleApiClient.OnConnectionFailedListener,
    LocationListener {

GoogleApiClient mLocationClient;
LocationRequest mLocationRequest = new LocationRequest();
public static final String ACTION_LOCATION_BROADCAST = 
ApiTrackService.class.getName() + "LocationBroadcast";
public static final String EXTRA_LATITUDE = "extra_latitude";
public static final String EXTRA_LONGITUDE = "extra_longitude";

int interval=20; //time between fixes in seconds


@Override
public void onDestroy(){
    super.onDestroy();
    stopSelf();
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.v("sTag","Got to apitrack");
    mLocationClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    mLocationRequest.setInterval(interval*1000);
    mLocationRequest.setFastestInterval(1000);
    int priority = LocationRequest.PRIORITY_HIGH_ACCURACY;
    mLocationRequest.setPriority(priority);
    mLocationClient.connect();
    return START_STICKY;
}


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


@Override
public void onConnected(Bundle dataBundle) {
    if (ActivityCompat.checkSelfPermission(this, 
Manifest.permission.ACCESS_FINE_LOCATION) != 
PackageManager.PERMISSION_GRANTED && 
ActivityCompat.checkSelfPermission(this, 
Manifest.permission.ACCESS_COARSE_LOCATION) != 
PackageManager.PERMISSION_GRANTED) {
        return;
    }

LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, 
mLocationRequest, this);
}


@Override
public void onConnectionSuspended(int i) {
}


//to get the location change
@Override
public void onLocationChanged(Location location) {
    boolean locFound=false;
    Log.v("sTag","Got a fix");
        /*does stuff to compare latitude and longitude with places in a list 
        and sets locFound=true if it finds a match*/
    if (location != null) {
        GPSLog=GPSLog+"Found";
        if (locFound) {
            Log.v("sTag", "Sending broadcast");
            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
            intent.setAction("com.AboutMyJourney.posBroadcast");
            sendBroadcast(intent);
        }
    }
}


@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    //Log.d(TAG, "Failed to connect to Google API");
}

}

只要該應用程序的其中一項前台活動處於打開狀態且可見,它就可以正常運行。 使用logcat進行跟蹤顯示,后台服務正在獲取GPS修復,並且onLocationChanged(請參見上面的代碼)下的代碼每20秒運行一次。

如果我允許我的應用關閉所有前台活動並僅運行上面的后台服務,則該應用仍然可以正常運行,並且onLocationChanged方法仍每20秒運行一次,只要另一個正在調用GPS的應用(完全不相關)位置開放且可見。

但是,如果我在屏幕上看不到任何使用GPS的應用程序,則GPS跟蹤會停止; onLocationChanged方法不再運行,並且我不再獲得GPS修復。

如果然后我打開應用程序的前台活動之一,則GPS跟蹤將再次啟動,表明后台服務尚未終止。

我假設這與實現省電/休眠模式所做的更改有關,並且我只是不太了解它。 但是,我能找到的所有建議似乎都暗示,只要設備白名單中允許例外,后台服務就可以繼續工作,但這顯然沒有發生。

使后台服務正常工作是我的首選,因為這意味着編寫新代碼的工作最少。 但是,對類似問題的一些答復建議改為使用帶有通知的前台服務。 滿足我的要求,在大多數情況下大部分時間都沒有可見的用戶界面(可能是針對通知的除外),僅提示用戶每隔幾分鍾執行一次操作,但同時讓他或她自由執行其他操作嗎? 在較舊的Android版本中也可以正常工作嗎?

請誰能比我更好地理解(可能不難理解?),可以幫助嗎?

從Android棉花糖開始,谷歌介紹了一種新的電池優化方式,例如

  1. 打ze模式
  2. 應用待機模式

你可以了解更多關於他們通過打盹和待機模式在這些概念在不斷改善有爭議的Android為止奧利奧。 當Google宣布android Oreo時,他們在很大程度上依靠電池優化方式,他們引入了新的Apis來處理后台操作,例如工作管理器和工作計划程序,但是他們也進入打ze和待機模式。 並在打ze模式維護窗口中工作。
經過長時間的搜索並嘗試了每20秒跟蹤一次用戶位置的最佳方法,您需要啟動帶有粘性前景通知的前台服務。這種方法不會因打ze睡或待命模式而終止,並且會保持位置更新。間隔。 這是服務的說明,也是啟動前台服務的示例

適用的待機/打documentation文檔

被列入白名單的應用程序可以在Doze和App Standby期間使用網絡並持有部分喚醒鎖。 但是,其他限制仍然適用於列入白名單的應用程序,就像對其他應用程序一樣。 例如,列入白名單的應用程序的作業和同步被推遲(在API級別23及以下),並且其常規AlarmManager警報不會觸發。

看來您的用例屬於“其他限制仍然適用”。

您的應用程序在不活躍使用時會耗盡電池電量,這正是App Standby和Doze旨在抵消的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM