Android:Google 低电量情况下的地图位置

Android: Google Maps location with low battery usage

我的应用目前正在使用 Google Play Services

的地图

具体说明:

mMap.setMyLocationEnabled(true);

我每次在我的应用程序中显示地图时都意识到:

但是,我可以看到有些应用程序使用地图并仍然显示位置蓝点,但位置图标没有出现在顶部栏中并且它们的电池使用率很低。

我的应用目前授予这两种权限:

我的问题是:

如何在低电量时显示位置蓝点?

是否可以通过代码指定 accuracy/battery 用法?

更新

实际上我意识到这样做的方法是使用 GoogleApiClientFusedLocationApi

    mGoogleApiClient = new GoogleApiClient.Builder(context)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

我已经在 Activity 中配置了 GoogleApiClient,调用:

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 的片段时,我的应用程序仍然高电量使用在 Settings/Location 屏幕上!

MapView 似乎忽略了这些低功耗标准!

您可以使用网络提供商 classes 您可以使用以下代码 AppLocationService.java // 专门用于在电池使用率低的情况下获取当前位置(与 nexus 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;
}

}

上面的用法class 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模式获取当前位置,之后你可以设置蓝点或任何你想要的

希望对大家有帮助

据说 here

FusedLocationProviderApi provides improved location finding and power usage and is used by the "My Location" blue dot.

所以 "My Location" 地图上的点是由 FusedLocationProviderApi 提供的。当您授予权限 android.permission.ACCESS_FINE_LOCATION 时,您允许 FusedLocationProviderApi 您的应用从 GPS 获取数据,这可能会导致电池使用率过高。

所以只添加 android.permission.ACCESS_COARSE_LOCATION 权限来显示并且 Android 不应该因为电池使用而责怪你。

您需要让您的 activity(或为此目的更好的单独对象)实现 LocationSource 接口。

很简单,您需要存储传入 activate() 方法的侦听器,并在位置更新时调用它,而在调用 deactivate() 时忘记它。有关示例,请参阅 this answer,您可能希望将其更新为使用 FusedLocationProvider

完成此设置后,您可以将 activity 作为地图的 LocationSource 传递,例如 mMap.setLocationSource(this) (documentation).

这将阻止地图使用其默认设置 LocationSource,后者使用高电量使用定位服务。

终于找到了解决方案!!! 感谢特里斯坦的回答!

默认情况下,GoogleMap 使用其本地位置提供程序,而不是融合位置提供程序。为了使用 Fused Location Provider(允许您控制位置精度和功耗),您需要使用 GoogleMap.setLocationSource() (documentation)

明确设置地图位置源

我在这里报告了一个示例 activity 来做到这一点:

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's current position).
        return false;
    }

    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        mMapLocationListener = onLocationChangedListener;
    }

    @Override
    public void deactivate() {
        mMapLocationListener = null;
    }
}