如何在应用程序处于后台时保持GPS接收器位置更新(Google Play服务位置API)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在应用程序处于后台时保持GPS接收器位置更新(Google Play服务位置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跟踪会再次启动,显示后台服务尚未被杀死。

我假设这与实现省电/ DOZE模式所做的更改有关,而我只是不理解它。但是,我能找到的所有建议似乎都表明后台服务将继续工作,只要它被允许作为设备白名单中的例外,但这显然不会发生。

使后台服务工作是我的首选,因为这意味着编写新代码的工作量最少!但是,对类似问题的一些回复建议使用带有通知的前台服务。这是否符合我的要求,大部分时间都没有可见的用户界面(除了通知),只是提示用户每隔几分钟做一些事情,但同时让他或她自由地做其他事情?它在旧版本的Android中也能正常工作吗?

任何能比我更了解这一点的人(可能比我更难理解它!)请帮忙吗?

答案

applicable standby/doze documentation

白名单中的应用可以使用网络并在Doze和App Standby期间保留部分唤醒锁定。但是,其他限制仍然适用于列入白名单的应用,就像对其他应用一样。例如,白名单应用的作业和同步是延迟的(在API级别23及以下),并且其常规AlarmManager警报不会触发。

您的用例似乎属于“其他限制仍然适用”。

您的应用程序在不主动使用时会耗尽电池,这正是App Standby和Doze要抵消的行为。

另一答案

从Android marshmallow google开始介绍一种新的电池优化方式

  1. 打盹模式
  2. 应用待机模式

你可以通过Doze and Stand by Modethis了解更多关于他们的信息,这些概念一直存在争议,直到android奥利奥。当google宣布android奥利奥时,他们非常依赖电池优化方式,他们引入了新的Apis来处理后台操作,如工作管理器和作业调度程序但他们也进入打瞌睡和待机模式。在打盹模式维护窗口工作。 经过长时间的搜索和练习最好的方法继续跟踪用户位置每20秒你需要启动前台服务与粘性前景通知。这种方式不会通过打盹或待机模式终止,它保持位置更新来根据间隔。这里是Service的解释,也是starting a foreground service的一个例子

以上是关于如何在应用程序处于后台时保持GPS接收器位置更新(Google Play服务位置API)的主要内容,如果未能解决你的问题,请参考以下文章

在后台模式下接收 gps 位置更新 ??iOS 8

当应用程序处于后台时,带有 PendingIntent 的 Android FusedLocationClient 未收到位置更新

平板电脑处于待机状态时,我的 GPS 应用程序是不是可以继续在后台运行?

使用 GPS 在后台运行的应用程序以及如何停止它

应用程序在后台或暂停时的位置更新

Android 在设备处于睡眠状态时获取 GPS 坐标更新(屏幕已关闭)