我每5分钟在后台更新一次位置。
我在三星和摩托罗拉设备的 Android Oreo及更高版本中检查了以下代码。一切正常。但是,当我签入MI,OPPO和VIVO时,如果我从最近任务中删除了应用程序,位置就不会更新。
我检查了this解决方案,但是没有用。
public class GpsTracker extends Service
implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks, LocationListener {
final static int REQUEST_LOCATION = 199;
private static final String TAG = GpsTracker.class.getSimpleName();
private static final int PERMISSIONS_REQUEST_PLAYLOCATION = 2000;
private static final int PERMISSIONS_REQUEST_LOCATION = 2001;
public static boolean IS_SERVICE_RUNNING = false;
protected LocationManager locationManager;
private PowerManager pm;
private PowerManager.WakeLock wl;
private Handler handler = new Handler();
private boolean mPlayLocationPermissionGranted;
private boolean mLocationPermissionGranted;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location mCurrentLocation;
private LocationTypes locationTypes = LocationTypes.HEARTBEAT;
private GPSTrackerVM gpsTrackerVM;
private boolean noConnect = true;
private Runnable periodicUpdate = new Runnable() {
@Override
public void run() {
handler.postDelayed(periodicUpdate, 5 * 60 * 1000 - SystemClock.elapsedRealtime() % 1000);
// whatever you want to do below
Utils.Log(TAG, "run: Service");
locationTypes = LocationTypes.HEARTBEAT;
buildGoogleApiClient();
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction() != null) {
showNotification();
Utils.Log(TAG, "onStartCommand: " + intent.getAction());
switch (intent.getAction()) {
case AppConfig.ACTION.START_FOREGROUND_ACTION:
Utils.Log(TAG, "Uploading Start");
locationTypes = LocationTypes.HEARTBEAT;
handler.post(periodicUpdate);
break;
case AppConfig.ACTION.START_DAY:
locationTypes = LocationTypes.IN;
buildGoogleApiClient();
break;
case AppConfig.ACTION.END_DAY:
locationTypes = LocationTypes.OUT;
buildGoogleApiClient();
break;
}
}
return START_STICKY;
}
@Override
public void onCreate() {
gpsTrackerVM = new GPSTrackerVM(MyApp.getInstance());
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp:GpsTracker");
wl.acquire();
}
@Override
public void onDestroy() {
IS_SERVICE_RUNNING = false;
super.onDestroy();
wl.release();
}
private void mStopService() {
Utils.Log(TAG, "Sync Stop");
if (handler != null) {
handler.removeCallbacks(periodicUpdate);
}
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
stopForeground(true);
stopSelf();
}
private void showNotification() {
if (!IS_SERVICE_RUNNING) {
String channelId = AppConfig.NOTIFICATION_ID.SYNC_CHANNEL;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
channelId = createmNotificationChannel();
}
Intent notificationIntent = new Intent();
notificationIntent.setAction(AppConfig.ACTION.MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_logo_notification);
Notification notification = new NotificationCompat.Builder(this, channelId)
.setContentTitle(getString(R.string.app_name))
.setTicker(getString(R.string.res_sync))
.setContentText(getString(R.string.res_sync))
.setSmallIcon(R.drawable.ic_logo_notification)
.setPriority(Notification.PRIORITY_DEFAULT)
.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
startForeground(AppConfig.NOTIFICATION_ID.FOREGROUND_SERVICE_SYNC,
notification);
IS_SERVICE_RUNNING = true;
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private String createmNotificationChannel() {
String channelId = AppConfig.NOTIFICATION_ID.SYNC_CHANNEL;
String channelName = AppConfig.NOTIFICATION_ID.SYNC_CHANNEL;
NotificationChannel chan = new NotificationChannel(channelId,
channelName, NotificationManager.IMPORTANCE_DEFAULT);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager service = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
service.createNotificationChannel(chan);
return channelId;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
public synchronized void buildGoogleApiClient() {
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
retrieveCurrentLocation();
return;
}
mGoogleApiClient = new GoogleApiClient.Builder(MyApp.getInstance())
.addConnectionCallbacks(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
public synchronized void stopLocationUpdates() {
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
// mGoogleApiClient.disconnect();
}
}
private void createLocationRequest() {
long UPDATE_INTERVAL_IN_MILLISECONDS = 100000;
long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
@Override
public void onConnected(@Nullable Bundle bundle) {
retrieveCurrentLocation();
}
private void retrieveCurrentLocation() {
Log.d(TAG, "retrieveCurrentLocation: 11");
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// get GPS status
boolean checkGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!checkGPS) {
Utils.Log(TAG, "retrieveCurrentLocation: GPS is Off");
updateCurrentLocation(null, "GPS is Turned Off");
return;
}
if (!hasLocationPermissions()) {
Utils.Log(TAG, "retrieveCurrentLocation: Location Permission Denied");
updateCurrentLocation(null, "Location Permission Denied");
return;
}
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient,
builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(@NonNull LocationSettingsResult result) {
mPlayLocationPermissionGranted = false;
final Status status = result.getStatus();
final LocationSettingsStates states = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
mPlayLocationPermissionGranted = true;
requestLocations();
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
mPlayLocationPermissionGranted = false;
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Utils.Log(TAG, "retrieveCurrentLocation: GPS is On, but they need to allow location access from Settings");
updateCurrentLocation(null, "GPS is On, but they need to allow location access from Settings");
break;
}
}
});
}
private void requestLocations() {
Log.d(TAG, "requestLocations: 11");
try {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mCurrentLocation == null) {
noConnect = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (noConnect) {
updateCurrentLocation(null, "GPS is On, but your device needs one restart to continue locating the device.");
}
}
}, 1000);
}
// updateCurrentLocation(mCurrentLocation);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
} catch (SecurityException ex) {
ex.printStackTrace();
}
}
private boolean hasLocationPermissions() {
if (ActivityCompat.checkSelfPermission(MyApp.getInstance(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED
&&
ActivityCompat.checkSelfPermission(MyApp.getInstance(),
Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED
) {
mLocationPermissionGranted = true;
} else {
mLocationPermissionGranted = false;
}
return mLocationPermissionGranted;
}
@Override
public void onLocationChanged(Location location) {
Utils.LogW(TAG, "onLocationChanged: " + location.toString());
if (noConnect) {
noConnect = false;
}
updateCurrentLocation(location, "None");
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed: ");
}
@Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended: ");
}
public void updateCurrentLocation(Location location, String remark) {
mCurrentLocation = location;
GPSData gpsData = new GPSData(UUID.randomUUID().toString());
gpsData.setLatitude(location == null ? 0 : location.getLatitude());
gpsData.setLongitude(location == null ? 0 : location.getLongitude());
gpsData.setAddress("None");
gpsData.setRemarks(remark);
gpsData.setTimeStamp(System.currentTimeMillis() / 1000L);
gpsData.setLocationType(locationTypes.getValue());
// Log.w(TAG, "updateCurrentLocation: " + location);
stopLocationUpdates();
if (locationTypes == LocationTypes.IN) {
Utils.Log(TAG, "In Success ");
Intent startIntent = new Intent(this, GpsTracker.class);
startIntent.setAction(AppConfig.ACTION.START_FOREGROUND_ACTION);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(startIntent);
} else {
startService(startIntent);
}
} else if (locationTypes == LocationTypes.OUT) {
Utils.Log(TAG, "out Success ");
mStopService();
} else if (locationTypes == LocationTypes.HEARTBEAT) {
Utils.Log(TAG, "HEARTBEAT Success ");
}
serverUpdate(gpsData);
}
private void serverUpdate(GPSData gpsData) {
gpsTrackerVM.updateLocation(gpsData);
}
public void onPermissionGrantStatus(boolean isGratned) {
Log.d(TAG, "onPermissionGrantStatus() called with: isGratned = [" + isGratned + "]");
}
}
在AndroidManifest.xml
<service android:name=".services.GpsTracker" />