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 в режиме более высокого уровня использования, после того, как вы можете установить синюю точку или что хотите.

Надеюсь, это поможет вам и всем.