Cada vez que ejecuto la aplicación, se lanza mi SecurityException y el error del depurador se lee así:
java.lang.SecurityException: el proveedor de ubicación "gps" requiere el permiso ACCESS_COARSE_LOCATION o ACCESS_FINE_LOCATION.
Esto parece un simple error, sin embargo, mi archivo de manifiesto es completamente correcto. Aquí está, y aquí está mi código MapActivity también:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="com.dev.cromer.jason.coverme.permission.MAPS_RECEIVE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value= "@string/google_maps_key" />
<activity
android:name=".MapActivity"
android:label="@string/title_activity_map" >
</activity>
</application>
Mi actividad:
package com.dev.cromer.jason.coverme;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
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.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MapActivity extends FragmentActivity implements LocationListener {
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
setUpMapIfNeeded();
}
@Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
//mMap.setMyLocationEnabled(true);
//mMap.setOnMyLocationChangeListener(this);
setUpMap();
}
}
}
private void setUpMap() {
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
mMap.setMyLocationEnabled(true);
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
try {
Location myLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (myLocation != null) {
Log.d("TAG", "Not null");
}
else {
Log.d("TAG", "NULL");
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
}
catch (SecurityException se) {
Log.d("TAG", "SE CAUGHT");
se.printStackTrace();
}
}
@Override
public void onLocationChanged(Location location) {
Log.d("CHANGED", "LOCATION UPDATED");
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
}
Respuestas:
ACCESS_COARSE_LOCATION
,ACCESS_FINE_LOCATION
yWRITE_EXTERNAL_STORAGE
son parte del sistema de permisos en tiempo de ejecución de Android 6.0 . Además de tenerlos en el manifiesto como lo hace, también debe solicitarlos al usuario en tiempo de ejecución (usandorequestPermissions()
) y ver si los tiene (usandocheckSelfPermission()
).Una solución a corto plazo es reducir su nivel
targetSdkVersion
por debajo de 23.Pero, eventualmente, querrá actualizar su aplicación para usar el sistema de permisos de tiempo de ejecución.
Por ejemplo, esta actividad funciona con cinco permisos. Cuatro son permisos de tiempo de ejecución, aunque actualmente solo maneja tres (lo escribí antes de que
WRITE_EXTERNAL_STORAGE
se agregara a la lista de permisos de tiempo de ejecución).(de este proyecto de muestra )
Usaría las constantes definidas en
Manifest.permission
, como se muestra arriba.Eso se le devolverá como el primer parámetro de
onRequestPermissionsResult()
, para que pueda distinguir unarequestPermissions()
llamada de otra.fuente
targetSdkVersion
en 23 o más. En ese momento, deberá adoptar el sistema de permisos en tiempo de ejecución. Hasta que llegue ese momento, puede mantener su niveltargetSdkVersion
por debajo de 23 e ignorar los permisos de tiempo de ejecución.Mi solución simple es esta
o puede abrir el diálogo de permisos en algo así
fuente
CAUSA: "A partir de Android 6.0 (nivel de API 23), los usuarios otorgan permisos a las aplicaciones mientras la aplicación se está ejecutando, no cuando la instalan". En este caso, "ACCESS_FINE_LOCATION" es un "permiso peligroso y por esa razón, obtienes este 'java.lang.SecurityException: el proveedor de ubicación" gps "requiere permiso ACCESS_FINE_LOCATION.' error ( https://developer.android.com/training/permissions/requesting.html ).
SOLUCIÓN: Implementar el código proporcionado en https://developer.android.com/training/permissions/requesting.html bajo los encabezados "Solicite los permisos que necesita" y "Maneje la respuesta de solicitud de permisos".
fuente