在我的应用的活动(MapsActivity
)中,会显示一个地图供用户选择他想要的地方。我使用的是ACCES_FINE_LOCATION
和ACCES_COARSE_LOCATION
权限。
我创建了PermissioUtils class
来验证MapsActivity class
中的权限。
访问MapsActicity
时,应用会以FATAL EXCEPTION
logcat错误
11-28 13:18:50.053 12496-12496/luizugliano.com.br.lugaresfavoritos E/AndroidRuntime: FATAL EXCEPTION: main
Process: luizugliano.com.br.lugaresfavoritos, PID: 12496
java.lang.RuntimeException: Unable to start activity ComponentInfo{luizugliano.com.br.lugaresfavoritos/luizugliano.com.br.lugaresfavoritos.MapsActivity}: java.lang.IllegalArgumentException: invalid provider: null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalArgumentException: invalid provider: null
at android.location.LocationManager.checkProvider(LocationManager.java:1704)
at android.location.LocationManager.requestLocationUpdates(LocationManager.java:459)
at luizugliano.com.br.lugaresfavoritos.MapsActivity.setUpMap(MapsActivity.java:205)
at luizugliano.com.br.lugaresfavoritos.MapsActivity.setUpMapIfNeeded(MapsActivity.java:171)
at luizugliano.com.br.lugaresfavoritos.MapsActivity.onCreate(MapsActivity.java:104)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
PermissionUtils类
public class PermissionUtils {
/**
* Solicita as permissões
*/
public static boolean validate(Activity activity, int requestCode, String... permissions) {
List<String> list = new ArrayList<String>();
for (String permission : permissions) {
// Valida permissão
boolean ok = ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED;
if (! ok ) {
list.add(permission);
}
}
if (list.isEmpty()) {
// Tudo ok, retorna true
return true;
}
// Lista de permissões que falta acesso.
String[] newPermissions = new String[list.size()];
list.toArray(newPermissions);
// Solicita permissão
ActivityCompat.requestPermissions(activity, newPermissions, 1);
return false;
}
}
MapsActivity类
public class MapsActivity extends AppCompatActivity implements GoogleMap.OnMapLongClickListener, LocationListener {
private GoogleMap mMap;
int location = -1;
LocationManager locationManager;
String provider;
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
@Override
public void onMapLongClick(LatLng point) {
Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
String label = new Date().toString();
try {
List<Address> listAddresses = geocoder.getFromLocation(point.latitude, point.longitude, 1);
if (listAddresses != null && listAddresses.size() > 0) {
label = listAddresses.get(0).getAddressLine(0);
}
} catch (IOException e) {
e.printStackTrace();
}
MainActivity.places.add(label);
MainActivity.arrayAdapter.notifyDataSetChanged();
MainActivity.locations.add(point);
mMap.addMarker(new MarkerOptions()
.position(point)
.title(label)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
provider = locationManager.getBestProvider(new Criteria(), false);
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
Intent i = getIntent();
location = i.getIntExtra("locationInfo", -1);
setUpMapIfNeeded();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
// Solicita as permissões
String[] permissoes = new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
};
PermissionUtils.validate(this, 0, permissoes);
}
@Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
if (location == -1 || location == 0) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this,Manifest.permission.ACCESS_FINE_LOCATION) && (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION))) {
// Caso o usuário tenha negado a permissão anteriormente, e não tenha marcado o check "nunca mais mostre este alerta"
// Podemos mostrar um alerta explicando para o usuário porque a permissão é importante.
} else {
// Solicita a permissão
ActivityCompat.requestPermissions(MapsActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0);
ActivityCompat.requestPermissions(MapsActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},0);
}
} else {
//Tudo OK
}
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
}
@Override
protected void onPause() {
super.onPause();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this,Manifest.permission.ACCESS_FINE_LOCATION) && (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION))) {
// Caso o usuário tenha negado a permissão anteriormente, e não tenha marcado o check "nunca mais mostre este alerta"
// Podemos mostrar um alerta explicando para o usuário porque a permissão é importante.
} else {
// Solicita a permissão
ActivityCompat.requestPermissions(MapsActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0);
ActivityCompat.requestPermissions(MapsActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},0);
}
} else {
//Tudo OK
}
locationManager.removeUpdates(this);
}
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();
mMap.setOnMapLongClickListener(this);
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
}
}
}
/**
* This is where we can add markers or lines, add listeners or move the camera. In this case, we
* just add a marker near Africa.
* <p/>
* This should only be called once and when we are sure that {@link #mMap} is not null.
*/
private void setUpMap() {
if (location != -1 && location != 0) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this,Manifest.permission.ACCESS_FINE_LOCATION) && (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION))) {
// Caso o usuário tenha negado a permissão anteriormente, e não tenha marcado o check "nunca mais mostre este alerta"
// Podemos mostrar um alerta explicando para o usuário porque a permissão é importante.
} else {
// Solicita a permissão
ActivityCompat.requestPermissions(MapsActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0);
ActivityCompat.requestPermissions(MapsActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},0);
}
} else {
//Tudo OK
}
locationManager.removeUpdates(this);
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(MainActivity.locations.get(location), 10));
mMap.addMarker(new MarkerOptions().position(MainActivity.locations.get(location)).title(MainActivity.places.get(location)));
} else {
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
for (int result : grantResults) {
if (result == PackageManager.PERMISSION_DENIED) {
// Alguma permissão foi negada
alertAndFinish();
return;
}
}
// Se chegou aqui está OK
}
private void alertAndFinish() {
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.app_name).setMessage("Para utilizar este aplicativo, você precisa aceitar as permissões.");
// Add the buttons
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
});
android.support.v7.app.AlertDialog dialog = builder.create();
dialog.show();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this,Manifest.permission.ACCESS_FINE_LOCATION) && (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION))) {
// Caso o usuário tenha negado a permissão anteriormente, e não tenha marcado o check "nunca mais mostre este alerta"
// Podemos mostrar um alerta explicando para o usuário porque a permissão é importante.
} else {
// Solicita a permissão
ActivityCompat.requestPermissions(MapsActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0);
ActivityCompat.requestPermissions(MapsActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},0);
}
} else {
//Tudo OK
}
locationManager.removeUpdates(this);
this.finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onLocationChanged(Location userLocation) {
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(userLocation.getLatitude(), userLocation.getLongitude()), 10));
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Maps Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://luizugliano.com.br.lugaresfavoritos/http/host/path")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
@Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Maps Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://luizugliano.com.br.lugaresfavoritos/http/host/path")
);
AppIndex.AppIndexApi.end(client, viewAction);
client.disconnect();
}
}
答案 0 :(得分:1)
setUpMap()
间接调用的 onCreate()
需要权限。您还没有要求用户提供这些权限。