Отслеживание местоположения в фоновом режиме Android - PullRequest
0 голосов
/ 14 сентября 2018

У меня возникли проблемы с отслеживанием местоположения моего приложения для Android.Все службы, которые мы разработали, работают, но в зависимости от телефонов и уровня API, они рано или поздно убиваются.

Моя цель - уведомить пользователя, когда он выходит из определенного диапазона, и этоработает, когда приложение запущено.

Это служба, которая вычисляет, когда пользователь находится в зоне или вне ее:

public class GeoFenceService extends BaseService {

@Inject
GeoFenceRepository geoFenceRepository;
SettingValueService settingValueService = new SettingValueService();
GeoFence geoFence;
private GeofencingClient mGeofencingClient;
PendingIntent mGeofencePendingIntent;
List<Geofence> mGeofenceList = new ArrayList<>();

public GeoFenceService() {
    super();
    Injector.getInstance().getAppComponent().inject(this);
}

public Observable<GeoFence> saveGeofence(GeoFence geoFence) {
    if (geoFence.getId() == null)
        geoFence.setId(CommonMethods.generateUuid());
    commitToRealm(geoFence);
    if (Application.getHasNetwork())
        return geoFenceRepository.saveGeofence(geoFence);
    else
        return Observable.just(null);
}

public Observable<GeoFence> getGeofence() {
    return geoFenceRepository.getGeofence();
}

public GeoFence getGeofenceFromRealm() {
    Realm realm = Realm.getDefaultInstance();
    RealmQuery<GeoFence> query = realm.where(GeoFence.class);
    GeoFence result = query.findFirst();
    if (result != null)
        return realm.copyFromRealm(result);
    return null;
}

public void initGeoFence(Context context) {
    SettingValue autoCloking = settingValueService.getSettingByName("auto_clocking");
    if (autoCloking != null && autoCloking.getValue().equals("true")) {
        if (mGeofencingClient == null)
            mGeofencingClient = LocationServices.getGeofencingClient(context);
        geoFence = getGeofenceFromRealm();
        if (geoFence != null) {
            addGeofence(geoFence, context);
        }
    }
}

@SuppressLint("MissingPermission")
public void addGeofence(GeoFence geofence, Context context) {
        mGeofenceList.clear();//only 1 geofence at the same time.
        mGeofenceList.add(new Geofence.Builder()
                // Set the request ID of the geofence. This is a string to identify this
                // geofence.
                .setRequestId(geofence.getId())

                .setCircularRegion(
                        geofence.getLatitude(),
                        geofence.getLongitude(),
                        (float) geofence.getRadius()
                )
                .setExpirationDuration(Geofence.NEVER_EXPIRE)
                .setLoiteringDelay(30000)
                .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
                        Geofence.GEOFENCE_TRANSITION_EXIT | Geofence.GEOFENCE_TRANSITION_DWELL)
                .build());
        mGeofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent(context));
}

private PendingIntent getGeofencePendingIntent(Context context) {
    // Reuse the PendingIntent if we already have it.
    if (mGeofencePendingIntent != null) {
        return mGeofencePendingIntent;
    }
    Intent intent = new Intent(context, GeofencingService.class);
    // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
    // calling addGeofences() and removeGeofences().
    mGeofencePendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.
            FLAG_UPDATE_CURRENT);
    return mGeofencePendingIntent;
}

private GeofencingRequest getGeofencingRequest() {
    GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
    builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER | GeofencingRequest.INITIAL_TRIGGER_EXIT);
    builder.addGeofences(mGeofenceList);
    return builder.build();
}

public void removeGeofence(Context context) {
    if (mGeofencingClient != null)
        mGeofencingClient.removeGeofences(getGeofencePendingIntent(context));
}

}

Даже если этоРаботая в фоновом режиме, мы сделали услугу, чтобы разбудить GPS телефона каждые 60 секунд, следуя совету этот вопрос.

Это услуга, которую мы сделали:

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

private static final String TAG = "UpdateLocationService";
private static final int LOCATION_INTERVAL = 60000;
private Context mContext;
private LocationRequest locationRequest;
private GoogleApiClient googleApiClient;
private FusedLocationProviderApi fusedLocationProviderApi;

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

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.e(TAG, "onStartCommand");
    super.onStartCommand(intent, flags, startId);
    return START_STICKY;
}

@Override
public void onCreate() {
    Log.e(TAG, "onCreate");
    mContext = this;
    getLocation();
}

@Override
public void onDestroy() {
    Log.e(TAG, "onDestroy");
    super.onDestroy();
    try {
        if (googleApiClient != null) {
            googleApiClient.disconnect();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void getLocation() {
    locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(LOCATION_INTERVAL);
    locationRequest.setFastestInterval(LOCATION_INTERVAL);
    fusedLocationProviderApi = LocationServices.FusedLocationApi;
    googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    if (googleApiClient != null) {
        googleApiClient.connect();
    }
}

@Override
public void onConnected(Bundle arg0) {
//  Location location = 
fusedLocationProviderApi.getLastLocation(googleApiClient);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
    fusedLocationProviderApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}

@Override
public void onConnectionSuspended(int arg0) {

}


@Override
public void onLocationChanged(Location location) {
    Toast.makeText(mContext, "User location :"+location.getLatitude()+" , "+location.getLongitude(), Toast.LENGTH_SHORT).show();
}



@Override
public void onConnectionFailed(ConnectionResult arg0) {
}
}

и, наконец, это вызов в нашей основной деятельности:

 if (checkGpsProviderEnabled()) {
            geoFenceService.initGeoFence(this);
            Intent msgIntent = new Intent(this, GeofencingService.class);
            startService(msgIntent);
            startService(new Intent(this,UpdateLocationService.class));
        }

Конечно, мы реализуем авторизацию для локализации и декларации сервиса в нашем AndroidManifest

И все работаетхорошо, когда приложение не на переднем плане

Передний план работает на некоторых устройствах, но не на всех, и я хотел знать, могу ли я сделать что-то еще, чтобы заставить наши сервисы запускать все времямне на заднем плане

Заранее спасибо

...