Android 6 上的 setMyLocationEnabled() 错误
setMyLocationEnabled() error on Android 6
我正在努力做到这一点,当我加载我的地图 activity 时,会出现一个 "my location" 按钮。这是我的代码,但没有出现使 activity 放大到我当前位置的按钮。我需要更改我的代码中的哪些内容才能使其正常工作?
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private static final String FIREBASE_URL="https://********.firebaseio.com/";
private Firebase firebaseRef;
private LocationManager locationManager;
private GoogleMap mMap;
SupportMapFragment mapFrag;
boolean bPermissionGranted;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps2);
Firebase.setAndroidContext(this);
firebaseRef = new Firebase(FIREBASE_URL);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
bPermissionGranted = checkLocationPermission();
}
// 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);
}
private void setUpMapIfNeeded() {
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
if (mMap != null) {
CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(32.065483, 34.824550));
CameraUpdate zoom = CameraUpdateFactory.zoomTo(10);
mMap.moveCamera(center);
mMap.animateCamera(zoom);
}
}
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission(){
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
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.
// TODO: Prompt with explanation!
//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, yay!
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
}
}
@Override
public void onMapReady(final GoogleMap googleMap) {
mMap=googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (bPermissionGranted) {
//User has previously accepted this permission
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
}
}
}
else {
//Not in api-23, no need to prompt
mMap.setMyLocationEnabled(true);
}
firebaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.child("users").getChildren()) {
String rightLocation = child.child("location_right").getValue().toString();
String leftLocation = child.child("location_left").getValue().toString();
double location_left = Double.parseDouble(leftLocation);
double location_right = Double.parseDouble(rightLocation);
String party_title = child.child("party/party_title").getValue().toString();
LatLng cod = new LatLng(location_left, location_right);
googleMap.addMarker(new MarkerOptions().position(cod).title(party_title));
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
}
您在 if 和 else 两个块中使用了相同的条件。
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED)
因此,如果您的上述条件不成立,那么相同的条件如何在您的 else 块中变为真。这就是原因
mMap.setMyLocationEnabled(true);
永远不会被执行,因为你的条件是错误的。
我猜你想在 else 块中做的是请求权限,如果它不存在的话。所以会变成这样-
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
} else{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, <request_code>);
}
并实施onRequestPermissionsResult
回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case <request_code>:
if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
}
break;
}
}
这是我的 的简化版本。
关键是在你调用setMyLocationEnabled()
之前确保用户已经授予你权限。
也有可能在调用 onMapReady()
时用户尚未接受权限提示(很可能是在应用程序首次启动时),因此在onRequestPermissionsResult()
用户接受权限时的回调。
首先,确保您拥有 AndroidManifest.xml(应用程序标签之外)的权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
这里有一个完整的 Activity class 适合您:
public class MapLocationActivity extends AppCompatActivity
implements OnMapReadyCallback {
GoogleMap mGoogleMap;
SupportMapFragment mapFrag;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFrag.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//User has previously accepted this permission
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mGoogleMap.setMyLocationEnabled(true);
}
} else {
//Not in api-23, no need to prompt
mGoogleMap.setMyLocationEnabled(true);
}
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
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.
// TODO: Prompt with explanation!
//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, yay!
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mGoogleMap.setMyLocationEnabled(true);
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
}
}
}
如果您撤销权限:
会再次提示:
请在Build.VERSION_CODES后写N而不是M。
在您的代码的这一行中:
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
对我有用
我正在努力做到这一点,当我加载我的地图 activity 时,会出现一个 "my location" 按钮。这是我的代码,但没有出现使 activity 放大到我当前位置的按钮。我需要更改我的代码中的哪些内容才能使其正常工作?
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private static final String FIREBASE_URL="https://********.firebaseio.com/";
private Firebase firebaseRef;
private LocationManager locationManager;
private GoogleMap mMap;
SupportMapFragment mapFrag;
boolean bPermissionGranted;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps2);
Firebase.setAndroidContext(this);
firebaseRef = new Firebase(FIREBASE_URL);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
bPermissionGranted = checkLocationPermission();
}
// 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);
}
private void setUpMapIfNeeded() {
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
if (mMap != null) {
CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(32.065483, 34.824550));
CameraUpdate zoom = CameraUpdateFactory.zoomTo(10);
mMap.moveCamera(center);
mMap.animateCamera(zoom);
}
}
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission(){
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
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.
// TODO: Prompt with explanation!
//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, yay!
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
}
}
@Override
public void onMapReady(final GoogleMap googleMap) {
mMap=googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (bPermissionGranted) {
//User has previously accepted this permission
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
}
}
}
else {
//Not in api-23, no need to prompt
mMap.setMyLocationEnabled(true);
}
firebaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.child("users").getChildren()) {
String rightLocation = child.child("location_right").getValue().toString();
String leftLocation = child.child("location_left").getValue().toString();
double location_left = Double.parseDouble(leftLocation);
double location_right = Double.parseDouble(rightLocation);
String party_title = child.child("party/party_title").getValue().toString();
LatLng cod = new LatLng(location_left, location_right);
googleMap.addMarker(new MarkerOptions().position(cod).title(party_title));
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
}
您在 if 和 else 两个块中使用了相同的条件。
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED)
因此,如果您的上述条件不成立,那么相同的条件如何在您的 else 块中变为真。这就是原因
mMap.setMyLocationEnabled(true);
永远不会被执行,因为你的条件是错误的。
我猜你想在 else 块中做的是请求权限,如果它不存在的话。所以会变成这样-
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
} else{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, <request_code>);
}
并实施onRequestPermissionsResult
回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case <request_code>:
if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
}
break;
}
}
这是我的
关键是在你调用setMyLocationEnabled()
之前确保用户已经授予你权限。
也有可能在调用 onMapReady()
时用户尚未接受权限提示(很可能是在应用程序首次启动时),因此在onRequestPermissionsResult()
用户接受权限时的回调。
首先,确保您拥有 AndroidManifest.xml(应用程序标签之外)的权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
这里有一个完整的 Activity class 适合您:
public class MapLocationActivity extends AppCompatActivity
implements OnMapReadyCallback {
GoogleMap mGoogleMap;
SupportMapFragment mapFrag;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFrag.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//User has previously accepted this permission
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mGoogleMap.setMyLocationEnabled(true);
}
} else {
//Not in api-23, no need to prompt
mGoogleMap.setMyLocationEnabled(true);
}
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
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.
// TODO: Prompt with explanation!
//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, yay!
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mGoogleMap.setMyLocationEnabled(true);
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
}
}
}
如果您撤销权限:
会再次提示:
请在Build.VERSION_CODES后写N而不是M。
在您的代码的这一行中:
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
对我有用