Пытаюсь разобраться и запустить код для приложения, в котором отображается карта и моё текущее местоположение. При этом всё это выполняется через запрос на разрешение доступа к геолокации, который нужно одобрить.
Код запускаю на своём устройстве через студию (на девайсе API 28), и сразу после запуска приложение крэшится. В логкате получаю ошибку:
java.lang.SecurityException: my location requires permission ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION
Как можно разрешить эту проблему? Погуглив, использовал разные решения, но пока безрезультатно. Поэтому решил и написать свой вопрос. Может быть есть нюансы в самой версии андроида, которые не дают приложению работать?
В манифесте:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="####.########.mygooglemap">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<uses-library android:name="org.apache.http.legacy" android:required="false" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="AIza#################hmkAg" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
</manifest>
Сам код:
public class MainActivity extends AppCompatActivity implements LocationListener {
private GoogleMap myMap;
private ProgressDialog myProgress;
private static final String MYTAG = "MYTAG";
public static final int REQUEST_ID_ACCESS_COURSE_FINE_LOCATION = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myProgress = new ProgressDialog(this);
myProgress.setTitle("Map Loading ...");
myProgress.setMessage("Please wait...");
myProgress.setCancelable(true);
myProgress.show();
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
mapFragment.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap googleMap) {
onMyMapReady(googleMap);
}
});
}
private void onMyMapReady(GoogleMap googleMap) {
myMap = googleMap;
myMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
@Override
public void onMapLoaded() {
myProgress.dismiss();
askPermissionsAndShowMyLocation();
}
});
myMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
myMap.getUiSettings().setZoomControlsEnabled(true);
myMap.setMyLocationEnabled(true);
}
private void askPermissionsAndShowMyLocation() {
if (Build.VERSION.SDK_INT >= 23) {
int accessCoarsePermission =
ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
int accessFinePermission =
ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if (accessCoarsePermission != PackageManager.PERMISSION_GRANTED
|| accessFinePermission != PackageManager.PERMISSION_GRANTED) {
String[] permissions = new String[] {
Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION
};
ActivityCompat.requestPermissions(this, permissions, REQUEST_ID_ACCESS_COURSE_FINE_LOCATION);
return;
}
}
this.showMyLocation();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_ID_ACCESS_COURSE_FINE_LOCATION: {
if (grantResults.length > 1
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission granted!", Toast.LENGTH_LONG).show();
this.showMyLocation();
} else {
Toast.makeText(this, "Permission denied!", Toast.LENGTH_LONG).show();
}
break;
}
}
}
private String getEnabledLocationProvider() {
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
String bestProvider = locationManager.getBestProvider(criteria, true);
boolean enabled = locationManager.isProviderEnabled(bestProvider);
if (!enabled) {
Toast.makeText(this, "No location provider enabled!", Toast.LENGTH_LONG).show();
Log.i(MYTAG, "No location provider enabled!");
return null;
}
return bestProvider;
}
private void showMyLocation() {
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
String locationProvider = this.getEnabledLocationProvider();
if (locationManager == null) {
return;
}
final long MIN_TIME_BW_UPDATES = 1000;
final float MIN_DISTANCE_CHANGE_FOR_UPDATES = 1;
Location myLocation = null;
try {
locationManager.requestLocationUpdates(
locationProvider,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES,
(LocationListener)this);
myLocation = locationManager.getLastKnownLocation(locationProvider);
} catch (SecurityException e) {
Toast.makeText(this, "Show My Location Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
Log.e(MYTAG, "Show My Location Error: " + e.getMessage());
e.printStackTrace();
return;
}
if (myLocation != null) {
LatLng latLng = new LatLng(myLocation.getLatitude(), myLocation.getLongitude());
myMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 13));
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLng)
.zoom(15)
.bearing(90)
.tilt(40)
.build();
myMap.animateCamera(CameraUpdateFactory.newCameraPosition((cameraPosition)));
MarkerOptions option = new MarkerOptions();
option.title("My Location");
option.snippet("....");
option.position(latLng);
Marker currentMarker = myMap.addMarker(option);
currentMarker.showInfoWindow();
} else {
Toast.makeText(this, "Location not found!", Toast.LENGTH_LONG).show();
Log.i(MYTAG, "Location not found");
}
}
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
}