对不起,这是一个很长的问题,但我希望你们中的一位专家可以帮助一个正在悄悄发疯的新手!
我有一个 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 中也能正常工作吗?
谁能比我更了解这一点(可能不比我更好地理解它!)请帮忙?