使用更新版本的Android ...您应该在使用其位置信息之前检查用户是否已经授予您许可。我已经浏览了android文档,这是我提出的代码。
我正在检查用户是否已经给予了许可,如果还没有...那么我们会询问,然后会对结果进行回调功能,依此类推。
我已经多次执行代码并且一切似乎都正常工作除了:当我最终尝试以编程方式使用fusedLocationApi.getLastLocation获取用户的位置时......它返回NULL !! < / p>
我重新上传了我的代码。
任何能够解决这个问题但实际上对我有用的人,你可以拥有我所有的代表得分......
package com.example.greg.rightnow;
import android.content.pm.PackageManager;
import android.location.Location;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.Manifest;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.Api;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.plus.Plus;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, ConnectionCallbacks {
private GoogleApiClient mGoogleApiClient;
private GoogleMap mMap;
private Location mLastLocation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
// Create an instance of GoogleAPIClient.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addApi(Plus.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
// .addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
@Override
public void onConnected(@Nullable Bundle bundle) {
}
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
* Manifest.permission.ACCESS_FINE_LOCATION
*/
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == grantResults[0]) {
mMap.setMyLocationEnabled(true);
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
LatLng myLat = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(myLat));
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== 0) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}
else if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) ==-1) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
LatLng myLat = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(myLat));
}
}
@Override
public void onConnectionSuspended(int i) {
}
}
你会注意到我必须注释掉这一行:
// .addOnConnectionFailedListener(this)
如果我取消注释......这个&#39;这个&#39;用红色加下划线我得到一个错误说&#34; ...在Builder中不能应用于com.example.greg.MapsActivity等&#34;
答案 0 :(得分:8)
使用ContextCompat.checkSelfPermission
检查权限后,如果未授予权限,您可以申请。来自the documentation:
此外,您需要在使用GoogleApiClient
(documentation)时处理连接失败。在您的代码中,连接失败,您无法在onConnectionFailed
上进行管理。
最后,我从您的代码中删除了以下内容(这导致连接失败,无需使用LocationServices
并获取最后一个位置):
.addApi(Drive.API)
.addApi(Plus.API)
.addScope(Drive.SCOPE_FILE)
这是一个有效的例子:
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final int FINE_LOCATION_PERMISSION_REQUEST = 1;
private static final int CONNECTION_RESOLUTION_REQUEST = 2;
private GoogleApiClient mGoogleApiClient;
private GoogleMap mMap;
private Location mLastLocation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
buildGoogleAPIClient();
}
@Override
protected void onResume() {
super.onResume();
buildGoogleAPIClient();
}
private void buildGoogleAPIClient() {
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
findLocation();
}
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
}
@Override
public void onConnectionSuspended(int i) {
Toast.makeText(this, "Connection suspended", Toast.LENGTH_SHORT).show();
}
@Override
public void onConnectionFailed(@NonNull final ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(this, CONNECTION_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect();
}
} else {
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(), this, 1);
dialog.show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CONNECTION_RESOLUTION_REQUEST && resultCode == RESULT_OK) {
mGoogleApiClient.connect();
}
}
private void findLocation() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
FINE_LOCATION_PERMISSION_REQUEST);
} else {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
LatLng myLat = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(myLat));
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case FINE_LOCATION_PERMISSION_REQUEST: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
findLocation();
}
}
}
}
}
答案 1 :(得分:1)
在获得最后一个已知位置之前,您需要检查四件事:
我建议对每件事使用状态机或布尔值,并且只有当所有四个都为真时才询问位置。例如:
protected void getLastKnownLocationIfReady(){
if(isGoogleApiConnected && isPermissionGranted && isLocationEnabled && isGoogleMapReady){
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
LatLng myLat = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(myLat));
}
}
每次更改其中一个布尔变量时,都会调用getLastKnownLocationIfReady()函数。
所以你的onConnected
就像是这样的:
@Override
public void onConnected(@Nullable Bundle bundle) {
isGoogleApiConnected = true;
getLastKnownLocationIfReady();
}
检查权限,如:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, FINE_LOCATION_PERMISSION_REQUEST);
} else {
isPermissionGranted = true;
getLastKnownLocationIfReady();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case FINE_LOCATION_PERMISSION_REQUEST: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
isPermissionGranted = true;
getLastKnownLocationIfReady();
}
}
}
}
您可以要求启用以下位置:
public void requestLocationAccess(){
if(mLocationRequest == null) createLocationRequest();
final LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true); //this is the key ingredient
com.google.android.gms.common.api.PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>(){
@Override
public void onResult(@NonNull LocationSettingsResult result){
final Status resultStatus = result.getStatus();
switch(resultStatus.getStatusCode()){
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied.
isLocationEnabled = true;
getLastKnownLocationIfReady();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user a dialog. You need to override OnActivityResult if you want to handle the user's interaction with the dialog.
resultStatus.startResolutionForResult(this, REQUEST_LOCATION);
break;
default:
break;
}
}
});
}
修改您的onMapReady
,如:
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
isGoogleMapReady = true;
getLastKnownLocationIfReady();
}
答案 2 :(得分:1)
我遇到了和你一样的错误。为了节省电池,我想使用 lastKnownLocation 而不是一直轮询。有时, lastKnownLocation 无效,无论我之前检查过什么。
如果您查看文档,可以说:
getLastLocation()方法返回一个Location对象,您可以从中检索地理位置的纬度和经度坐标。 在位置不可用的极少数情况下,返回的位置对象可能为null 。
要解决此问题,我实施了使用 lastKnownLocation 的组合,并轮询新位置作为后备。
我的基本结构是
这种方法就像一个魅力。到目前为止,我还没有设法找到更好的解决方案,但我建议你试一试。
答案 3 :(得分:0)
此外,检查您是否拥有权限并实际请求它是两回事。
正如android developer blog建议您需要以这样的方式请求权限:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_RESULT_CODE);
然后通过覆盖onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
来处理请求的结果。
答案 4 :(得分:0)
这就是问题所在: Android Emulator
向下滚动到&#34;使用扩展控件,设置和帮助&#34;。
长话短说:如果你正在使用仿真器,你必须伪造你的位置数据!!!!!模拟器不支持wifi(或者据我所知,GPS数据也是如此)。
点击你的电话&#34; (您的模拟器)确保选中它,然后按ctrl + shift + L键入您想要的任何位置,然后单击&#34;发送&#34;和中提琴......你有一个位置。当我的模拟器上的GoogleMaps甚至无法工作时,我知道有些事情发生了。我会搜索方向,它会说&#34;等待位置&#34;什么都不会发生
好吓人的挣脱。