Продвинутое поведение провайдера Fused Location
так я регистрирую свое приложение для получения обновлений местоположения:
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(Consts.ONE_MINUTE * 10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setFastestInterval(Consts.ONE_MINUTE);
Builder builder = new GoogleApiClient.Builder(context);
builder.addApi(ActivityRecognition.API);
mGoogleApiClient = builder.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
....
....
@Override
public void onConnected(Bundle connectionHint) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationUpdatespendingInent);
}
мое ожидающее намерение было вызвано в фоновом режиме почти точными запрошенными интервалами...
пока что так хорошо.
проблема: Когда WIFI отключен/не подключен к какой-либо сети или когда нет сетевых данных 3G/4G, - поставщик плавного доступа не предоставляет новые обновления местоположения!
Мои настройки доступа к местоположению включены, а GPS-спутники и WI-FI и местоположение мобильной сети проверены.
еще более серьезная проблема: иногда в этом случае, я получаю обратные вызовы обновлений местоположения через ожидающее намерение, но с последним местоположением, которое он знал (даже если это было час назад, м длиной долго ушел миль от этого места)
в соответствии с документацией PRIORITY_BALANCED_POWER_ACCURACY
:
Используется с setPriority (int) для запроса точности "блока". Точность уровня блока считается равной 100-метровой точности. Использование грубой точности, такой как это, часто потребляет меньше энергии.
Я ожидаю, что провайдер плавного местоположения откроет GPS, если у него нет другого выбора, или, по крайней мере, не предоставит новые обновления местоположения, если у него его нет.
другая непредсказуемая и тревожная проблема:
Я изменил PRIORITY_BALANCED_POWER_ACCURACY
на PRIORITY_HIGH_ACCURACY
, чтобы увидеть, как он себя ведет (в течение 24 часов). все интервалы остались прежними (интервал между обновлениями - 10 минут). точное местоположение действительно получено даже в телефонах без сети/сим-карты, но - аккумулятор разрядился быстро! когда я смотрел историю батареи, я был удивлен, увидев, что радиостанция GPS была в режиме полной передачи все время!!!!, и я видел также в своем журнале, что loction принималась каждую минуту, даже что я запросил местоположение каждые десять минут (у меня нет каких-либо других установленных приложений, которые открывают GPS для получения мест.)
Я заметил это поведение на нескольких устройствах (таких как Moto X 2013, HTC One X, Nexus 5), все с последними сервисами Google Play (версия 6.1.11) и android KITKAT 4.4.4
мое приложение сильно зависит от текущего местоположения пользователя и периодически получает обновления местоположения в указанном интервале до тех пор, пока пользователь вошел в систему, поэтому я не хочу использовать режим PRIORITY_HIGH_ACCURACY
, чтобы предотвратить утечку аккумулятора..
мои вопросы:
-
Предполагается, что провайдер с плавным местоположением вообще использует GPS, если он настроен на получение обновлений с помощью PRIORITY_BALANCED_POWER_ACCURACY
и не имеет информации о WI-FI или ячейках.
-
если это так, то что я делаю неправильно?
-
Почему я ошибаюсь в том, что это неверные данные об ошибках? (как я объяснил в разделе "еще большая проблема".
-
почему GPS-радио все время открыто, а не открыто в течение 10-минутного интервала, когда я использовал параметр PRIORITY_HIGH_ACCURACY
? (У меня нет других установленных приложений, которые быстрее ускоряют обновление местоположения.)
Ответы
Ответ 1
По указанным вопросам
1. является провайдером с плавным определением местоположения, предположительно вообще использующим GPS, если он настроен на получение обновлений с помощью PRIORITY_BALANCED_POWER_ACCURACY
и не имеет информации о WI-FI или ячейках. &
2., если это так, то что я делаю неправильно?
По-видимому, нигде в документации не указывается однозначно уникальный источник. С помощью опций PRIORITY
, даже через код, "источник" полученного location
"слит".
[location.getProvider()
возвращает: "fused" ]
Я видел, что GPS используется только тогда, когда LocationRequest имеет PRIORITY_HIGH_ACCURACY. Таким образом, он не использует GPS в других условиях.
4. почему GPS-радио открыто все время, а не открыто в течение 10-минутного интервала, когда я использовал параметр PRIORITY_HIGH_ACCURACY? (У меня нет других установленных приложений, которые быстрее ускоряют обновление местоположения.)
Самый быстрый интервал установлен на 1 минуту. Из того, что я понял, setFastestInterval имеет приоритет над setInterval, когда значение для самого быстрого интервала короче по длительности, чем значение setInterval.
В вашем случае, 1 минута против 10.
Об отсутствии других установленных приложений, которые запускают обновления местоположения, только что приведенные в качестве примера и не указали, что только этот случай явно.
Это обеспечивает максимальную скорость, с которой ваше приложение будет получать обновления местоположения, которые могут быть быстрее, чем setInterval (long) в некоторых ситуаций (например, если другие приложения запускают местоположение обновления).
Итак, что происходит с PRIORITY_HIGH_ACCURACY
, он запрашивает location
в самом быстром интервале - 1min, используя GPS (только для исключительного).
3. Почему я ошибаюсь в том, что эти неправильные данные об ошибках? (как я объяснил в разделе "еще большая проблема".
Необходимо также проверить код для механизма pendingIntent
. Хотя может быть несколько вещей, чтобы принять к сведению:
Вы можете добавить location.getTime()
, чтобы обеспечить и проверить время получения местоположения. Скорее всего, он не обновляется, если в радиусе нет башни с Wi-Fi-ячейками и используется PRIORITY_BALANCED_POWER_ACCURACY
.
Точность местоположения блока на первом месте, которая используется при вызове "lastKnown", не помогла бы.
Потребление батареи было связано с комбинацией GPS и 1-минутным обновлением. Попробуйте установить самый быстрый интервал как 5 или 10 минут, если это подходит для вашей реализации, но PRIORITY_BALANCED_POWER
может не помочь, если вам нужно абсолютно точное местоположение. Обычно я добавляю чек для местоположения, полученного в onLocationChanged
, и в зависимости от этого переключите приоритет в LocationRequest. Это помогает, конечно, получить местоположение вообще, если я не вхожу в здание, не имеющее прямой видимости для GPS и Wi-Fi-сети.
Ответ 2
Я предлагаю вам использовать AlarmManager
и FusedLocationProvider
вместе таким образом, чтобы ваша тревога AlarmManager
срабатывала каждые 10 минут с целью запуска обновлений местоположения.
Как только вы получите обновленное местоположение, отключите клиента местоположения. Вам не нужно постоянно его запускать, установив интервал времени в LocationRequest
, вместо этого вы можете вызвать процесс на каждом временном интервале с помощью AlarmManager
.
В таком виде вы получите следующие преимущества, которые помогут решить ваши проблемы:
- GPS-радио будет оставаться открытым только на несколько секунд при поиске местоположения, потому что вы собираетесь отключиться после первого обновления местоположения. Таким образом, GPS-радио не будет оставаться открытым все время, поэтому батарея будет сохранена.
- Вы сможете получить новое местоположение на каждые 10 минут, не испортив старое местоположение или что-то в этом роде.
Я надеюсь, что это будет полезно.
Ответ 3
Сотовые башни покрывают область в несколько милей, поэтому они не подходят для получения места. Посмотрите на точность местоположения, когда вы работаете с местоположениями.
@Override
public void onLocationChanged(Location location) {
//it happens
if (location == null) {
return;
}
// all locations should have an accuracy
if (!location.hasAccuracy()) {
return;
}
// if its not accurate enough don't use it
// this value is in meters
if (location.getAccuracy() > 200) {
return;
}
}
Вы можете поместить трансляцию сети в состояние сети, а когда нет соединения, вы можете перезапустить своего провайдера местоположения с помощью priority_high_accuracy, который будет использовать GPS только в том случае, если у пользователя включен GPS, иначе он падает на антенны Wi-Fi и сотовые.
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
/** Checks whether the device currently has a network connection */
private boolean isDeviceOnline() {
ConnectivityManager connMgr = (ConnectivityManager) activity
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
return true;
}
return false;
}
Ответ 4
Для обновления координат GPS вы также можете использовать провайдеры GPS и WI-FI. Для обновления позиции используйте также минимальный параметр расстояния. Я дам вам небольшой пример обслуживания GPS.
Ответы:
1) PRIORITY_BALANCED_POWER_ACCURACY do not использует GPS.
2) Для определения местоположения используйте GPS и WI-FI.
3) PRIORITY_BALANCED_POWER_ACCURACY, вероятно, из-за отсутствия области WI-FI.
Пример кода:
public class GPSservice extends Service implements LocationListener {
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 2;
private static final long MIN_TIME_BW_UPDATES = 1000 * 1;
double latitude, longitude;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
Location location;
protected LocationManager locationManager;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
getLocation();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onLocationChanged(Location location) {
new LocationReceiver(location, getApplicationContext());
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
public Location getLocation() {
try {
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
Log.d("Network", "NO network");
} else {
this.canGetLocation = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
}