Как сохранить обновления местоположения приемника GPS, когда приложение находится в фоновом режиме (API определения местоположения службы Google Play) - PullRequest
0 голосов
/ 04 сентября 2018

Извините, это длинный вопрос, но я надеюсь, что один из вас, экспертов, сможет помочь новичку, который просто сходит с ума !!

У меня есть приложение для Android, которое использует фоновый сервис для получения исправлений GPS (с использованием Google Play Services) каждые 20 секунд. Он сравнивает широту и долготу с теми, что в списке, и, если он находит совпадение, он отправляет широковещательную рассылку получателю, который запускает действие на переднем плане, чтобы предупредить пользователя.

Я использую фоновую службу, потому что между оповещениями пользователей обычно от 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?

Может кто-нибудь, кто понимает это лучше, чем я (вероятно, нетрудно понять это лучше, чем я!), Помогите, пожалуйста?

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

соответствующая документация по режиму ожидания / дозе говорит

Приложение, занесенное в белый список, может использовать сеть и частично блокировать пробуждение во время Doze и App Standby. Однако к приложению, внесенному в белый список, по-прежнему применяются другие ограничения, как и к другим приложениям. Например, задания и синхронизации приложения из белого списка откладываются (на уровне API 23 и ниже), и его обычные тревоги AlarmManager не запускаются.

Похоже, ваш вариант использования подпадает под "другие ограничения по-прежнему применяются".

Ваше приложение разряжает батарею, когда оно не активно используется, что в точности соответствует поведению App Standby и Doze, которые предназначены для противодействия.

0 голосов
/ 04 сентября 2018

начиная с Android зефир Google представит новые способы оптимизации батареи как

  1. Режим дозирования
  2. Режим ожидания приложения

Вы можете узнать о них больше через Режим ожидания и ожидания и это в этих концепциях держать в спорном улучшение до андроида Oreo. когда Google объявляет Android Oreo, они в значительной степени полагаются на способы оптимизации батареи, они представили новый Apis для обработки фоновых операций, таких как менеджер работ и планировщик заданий Но они также входят в режим ожидания и ожидания. и работать в окне обслуживания дремального режима.
после долгих поисков и отработки наилучшего способа Отслеживание местоположения пользователя каждые 20 секунд. Вам необходимо запустить службу переднего плана с прикрепленным уведомлением переднего плана. Этот способ не прерывается режимом ожидания или ожидания, и он сохраняет обновленное местоположение в соответствии с интервалом. Вот объяснение службы , а также пример запуска службы переднего плана

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...