Android: местоположение Google Maps с низким уровнем использования батареи
В настоящее время мое приложение использует Карты Google Play Services
speficying:
mMap.setMyLocationEnabled(true);
Я понимаю каждый раз, когда я показываю карту в своем приложении:
- местоположение отображается на карте синей точкой
- значок местоположения отображается в верхней строке
- Если я перейду в Настройки/Местоположение телефона, мое приложение будет указано как "Высокое потребление батареи"
Тем не менее, я вижу, что есть приложения, которые используют Карты и все еще отображают голубую точку местоположения, но значок местоположения не отображается в верхнем баре, и их использование батареи низкое.
Мое приложение в настоящее время предоставляет оба разрешения:
-
android.permission.ACCESS_COARSE_LOCATION
-
android.permission.ACCESS_FINE_LOCATION
Мой вопрос:
как я могу показать местоположение синей точки с низким уровнем использования батареи?
Можно ли указать точность/использование батареи по коду?
UPDATE
На самом деле я понял, что способ сделать это - использовать GoogleApiClient
FusedLocationApi
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Я настроил GoogleApiClient внутри своей активности, вызвав:
-
GoogleApiClient.connect()
в начале действия
-
GoogleApiClient.disconnect()
на остановке активности
в обратном вызове onConnected
Я установил критерии для обновлений местоположения: самый быстрый интервал в 1 минуту с низким приоритетом мощности:
private static final LocationRequest REQUEST = LocationRequest.create()
.setFastestInterval(60000) // in milliseconds
.setInterval(180000) // in milliseconds
.setPriority(LocationRequest.PRIORITY_LOW_POWER);
@Override
public void onConnected(Bundle bundle) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient,
REQUEST,
this); // LocationListener
}
Я тестировал, что GoogleApiClient правильно подключается в начале, но по каким-то причинам, когда я посещаю фрагмент со встроенным MapView, я по-прежнему получаю использование аккумулятора для моего приложения в настройках/местоположении экран!
Кажется, MapView игнорирует эти критерии низкой мощности!
Ответы
Ответ 1
НАЙДЕНО РЕШЕНИЕ!!!
благодаря Тристану за его ответ!
По умолчанию GoogleMap использует свой провайдер местоположения, который не является поставщиком Fused Location. Чтобы использовать поставщика Fused Location Provider (который позволяет вам контролировать точность местоположения и энергопотребление), вам необходимо явно установить источник местоположения карты с помощью GoogleMap.setLocationSource()
(документации). )
Я сообщаю здесь пример активности, чтобы сделать это:
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener;
import com.google.android.gms.maps.LocationSource;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends FragmentActivity
implements
ConnectionCallbacks,
OnConnectionFailedListener,
LocationSource,
LocationListener,
OnMyLocationButtonClickListener,
OnMapReadyCallback {
private GoogleApiClient mGoogleApiClient;
private TextView mMessageView;
private OnLocationChangedListener mMapLocationListener = null;
// location accuracy settings
private static final LocationRequest REQUEST = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMessageView = (TextView) findViewById(R.id.message_text);
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void onResume() {
super.onResume();
mGoogleApiClient.connect();
}
@Override
public void onPause() {
super.onPause();
mGoogleApiClient.disconnect();
}
@Override
public void onMapReady(GoogleMap map) {
map.setLocationSource(this);
map.setMyLocationEnabled(true);
map.setOnMyLocationButtonClickListener(this);
}
public void showMyLocation(View view) {
if (mGoogleApiClient.isConnected()) {
String msg = "Location = "
+ LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
}
/**
* Implementation of {@link LocationListener}.
*/
@Override
public void onLocationChanged(Location location) {
mMessageView.setText("Location = " + location);
if (mMapLocationListener != null) {
mMapLocationListener.onLocationChanged(location);
}
}
@Override
public void onConnected(Bundle connectionHint) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient,
REQUEST,
this); // LocationListener
}
@Override
public void onConnectionSuspended(int cause) {
// Do nothing
}
@Override
public void onConnectionFailed(ConnectionResult result) {
// Do nothing
}
@Override
public boolean onMyLocationButtonClick() {
Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT).show();
// Return false so that we don't consume the event and the default behavior still occurs
// (the camera animates to the user current position).
return false;
}
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
mMapLocationListener = onLocationChangedListener;
}
@Override
public void deactivate() {
mMapLocationListener = null;
}
}
Ответ 2
Вы хотите, чтобы ваша деятельность (или, лучше, отдельный объект для этой цели) реализовала интерфейс LocationSource
.
Проще всего вам нужно сохранить прослушиватель, переданный в методе activate()
, и вызвать его при обновлении местоположения и забыть его при вызове deactivate()
. См. этот ответ, например, вы, вероятно, захотите его обновить, чтобы использовать FusedLocationProvider
.
Как только вы настроите эту настройку, вы можете передать свою деятельность как LocationSource
для такой карты mMap.setLocationSource(this)
(documentation).
Это остановит использование карты по умолчанию LocationSource
, в которой используются службы определения местоположения с высокой загрузкой.
Ответ 3
В нем указано здесь, что
FusedLocationProviderApi обеспечивает улучшенное определение местоположения и использование энергии и используется синей точкой "Мое местоположение".
Точка "Мое местоположение" на карте подается FusedLocationProviderApi
. И когда вы предоставляете разрешение android.permission.ACCESS_FINE_LOCATION
, вы позволяете FusedLocationProviderApi
для вашего приложения получать данные с GPS, что может привести к интенсивному использованию батареи.
Так что добавьте только android.permission.ACCESS_COARSE_LOCATION
разрешение на манифестацию, и Android не должен обвинять вас в использовании аккумулятора.
Ответ 4
Вы можете сделать это, используя классы сетевого провайдера
Вы можете использовать код ниже
AppLocationService.java//Специально для получения текущего местоположения при низком уровне использования батареи (такой же, как режим экономии заряда аккумулятора в 5-й точке связи 5,0)
package coreclass;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
public class AppLocationService extends Service implements LocationListener {
protected LocationManager locationManager;
Location location;
private static final long MIN_DISTANCE_FOR_UPDATE = 10;
private static final long MIN_TIME_FOR_UPDATE = 1000 * 60 * 2;
public AppLocationService(Context context) {
locationManager = (LocationManager) context
.getSystemService(LOCATION_SERVICE);
}
public Location getLocation(String provider) {
if (locationManager.isProviderEnabled(provider)) {
locationManager.requestLocationUpdates(provider,
MIN_TIME_FOR_UPDATE, MIN_DISTANCE_FOR_UPDATE, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(provider);
return location;
}
}
return null;
}
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}
Использование вышеуказанного класса
MainActivity.java
AppLocationService appLocationService;
appLocationService = new AppLocationService(getActivity());
Location nwLocation = appLocationService.getLocation(LocationManager.NETWORK_PROVIDER);
if (nwLocation != null) {
Lat = nwLocation.getLatitude();
Longi = nwLocation.getLongitude();
}
Таким образом, вы можете получить текущее местоположение в режиме GPS в режиме более высокого уровня использования, после того, как вы можете установить синюю точку или что хотите.
Надеюсь, это поможет вам и всем.