Android - 请求查看用户位置的权限
Posted
技术标签:
【中文标题】Android - 请求查看用户位置的权限【英文标题】:Android - Asking permission to see user location 【发布时间】:2017-08-07 02:29:44 【问题描述】:我正在尝试询问用户是否有权访问他们的位置。这是我的 MainActivity,但运行应用程序时未询问权限。我在活动结束时输入了权限代码。我做错了什么?
package com.example.googlemapsadding;
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.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import android.Manifest;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
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.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.LocationSource;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
public class MapsActivity extends FragmentActivity implements
OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
com.google.android.gms.location.LocationListener
private GoogleMap mMap;
private final String LOG_TAG = "LaurenceTestApp";
private TextView txtOutput;
private TextView latitude;
private TextView longitude;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
Marker curPosMarker;
@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);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
txtOutput = (TextView) findViewById(R.id.txtOutput);
latitude = (TextView) findViewById(R.id.latitude);
longitude = (TextView) findViewById(R.id.longitude);
/**
* 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
*/
@Override
public void onMapReady(GoogleMap googleMap)
mMap = googleMap;
/* Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(10,19);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
*/
@Override
public void onConnected(@Nullable Bundle bundle)
mLocationRequest = LocationRequest.create(); // Another way to write a new object
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(2 * 1000); // Always write in milliseconds
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
return;
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
@Override
public void onConnectionSuspended(int i)
Log.i(LOG_TAG, "GoogleApiClient connection has been suspended");
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult)
Log.i(LOG_TAG, "GoogleApiClient connection has failed");
@Override
public void onLocationChanged(Location location)
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
mMap.setMyLocationEnabled(true);
Log.i(LOG_TAG, location.toString());
double tempLat = location.getLatitude();
double tempLong = location.getLongitude();
// Make a marker
LatLng latlng = new LatLng(tempLat,tempLong);
mMap.moveCamera(CameraUpdateFactory.newLatLng(latlng));
/*
MarkerOptions markerOptions = new MarkerOptions(); // MarkerOptions object to hold marker attributes
markerOptions.position(latlng);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
markerOptions.title("Current Position");
curPosMarker = mMap.addMarker(markerOptions); // Add marker with markerOptions options
mMap.moveCamera(CameraUpdateFactory.newLatLng(latlng));
if (curPosMarker != null) // Keep only one marker for an object and delete past ones
mMap.clear();
curPosMarker = mMap.addMarker(markerOptions);
mMap.moveCamera(CameraUpdateFactory.newLatLng(latlng));
*/
@Override
protected void onStart()
super.onStart();
mGoogleApiClient.connect();
@Override
protected void onStop()
mGoogleApiClient.disconnect();
super.onStop();
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission()
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION))
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(this,
new String[]Manifest.permission.ACCESS_FINE_LOCATION,
MY_PERMISSIONS_REQUEST_LOCATION);
else
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]Manifest.permission.ACCESS_FINE_LOCATION,
MY_PERMISSIONS_REQUEST_LOCATION);
return false;
else
return true;
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults)
switch (requestCode)
case MY_PERMISSIONS_REQUEST_LOCATION:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
// permission was granted. Do the
// contacts-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED)
//if (mGoogleApiClient == null)
// buildGoogleApiClient();
//
mMap.setMyLocationEnabled(true);
else
// Permission denied, Disable the functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
return;
// other 'case' lines to check for other permissions this app might request.
// You can add here other case statements according to your requirement.
【问题讨论】:
我认为你不应该在onConnected()中调用权限。尝试在onCreate()中使用。 @AndroidGeek 还是不行。 检查build.gradle
文件中的目标版本,它应该是23或更高。
【参考方案1】:
我认为您应该请求授予所有位置许可
String mPerms[] = new String[]Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION;
...
if (checkSelfPermission(mPerms[0]) == PackageManager.PERMISSION_DENIED
|| checkSelfPermission(mPerms[1]) == PackageManager.PERMISSION_DENIED)
requestPermissions(mPerms, CODE_PERMISSION_LOCATION);
else
// TODO Location checker
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(resultCallback);
【讨论】:
您能否详细说明您的意思? 我看到了您的代码,您在没有 ACCESS_COARSE_LOCATION 的情况下请求 ACCESS_FINE_LOCATION 的权限。 对不起。我只是尝试过,但仍然没有获得许可框。 抱歉,您测试的是什么操作系统版本? ?此请求权限功能仅适用于 OS.Build.VERSION_CODES.M 以后 我正在使用 API lvl 23 的手机进行测试。【参考方案2】:尝试Google Utilities 库,在获得许可的情况下轻松获取位置..
locationHandler = new LocationHandler(this)
.setLocationListener(new LocationListener()
@Override
public void onLocationChanged(Location location)
// Get the best known location
).start();
有关位置处理程序的更多详细信息,请阅读wiki...
【讨论】:
【参考方案3】:检查build.gradle
文件中的目标版本,它应该是23或更高。
【讨论】:
目标版本设置为25,要不要改成23?【参考方案4】:解决了。我完全删除了我的许可代码并从头开始遵循本教程 - https://www.youtube.com/watch?v=z2JaVke71RY。完美运行。
【讨论】:
以上是关于Android - 请求查看用户位置的权限的主要内容,如果未能解决你的问题,请参考以下文章