java - Error al invocar el método virtual ''double android.location.Location.getLatitude()'' en una referencia de objeto nulo
google-maps nullpointerexception (5)
Cambie esto en su método
getLocation
if (isLocationEnabled(PlacesDecoder.this) && location != null) {
...
}
Todo lo que intento hacer es dejar que el usuario obtenga una lista de los lugares de los tipos que le gustan.
Por ejemplo, si la entrada era hospital, mi aplicación abriría google maps con la cadena de búsqueda "Hospital".
Pero como se sugiere en la documentación usando el geocódigo como
geo:0,0?q=hospital
uri muestra todos los hospitales cerca de las coordenadas 0 latitud y 0 longitud.
Entonces, cuando intenté obtener las coordenadas de los usuarios primero usando el siguiente código.
Places Decoder.java
package com.kkze.Mappy;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
public class PlacesDecoder extends Activity {
Intent intentThatCalled;
public double latitude;
public double longitude;
public LocationManager locationManager;
public Criteria criteria;
public String bestProvider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
intentThatCalled = getIntent();
String voice2text = intentThatCalled.getStringExtra("v2txt");
getLocation(voice2text);
}
public static boolean isLocationEnabled(Context context)
{
int locationMode = 0;
String locationProviders;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
try
{
locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
return locationMode != Settings.Secure.LOCATION_MODE_OFF;
}
else
{
locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
return !TextUtils.isEmpty(locationProviders);
}
}
public void getLocation(String voice2txt) {
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
criteria = new Criteria();
bestProvider = String.valueOf(locationManager.getBestProvider(criteria, true)).toString();
Location location = locationManager.getLastKnownLocation(bestProvider);
if (isLocationEnabled(PlacesDecoder.this)) {
Log.e("TAG", "GPS is on");
latitude = location.getLatitude();
longitude = location.getLongitude();
Toast.makeText(PlacesDecoder.this, "latitude:" + latitude + " longitude:" + longitude, Toast.LENGTH_SHORT).show();
searchNearestPlace(voice2txt);
}
else
{
AlertDialog.Builder notifyLocationServices = new AlertDialog.Builder(PlacesDecoder.this);
notifyLocationServices.setTitle("Switch on Location Services");
notifyLocationServices.setMessage("Location Services must be turned on to complete this action. Also please take note that if on a very weak network connection, such as ''E'' Mobile Data or ''Very weak Wifi-Connections'' it may take even 15 mins to load. If on a very weak network connection as stated above, location returned to application may be null or nothing and cause the application to crash.");
notifyLocationServices.setPositiveButton("Ok, Open Settings", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent openLocationSettings = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
PlacesDecoder.this.startActivity(openLocationSettings);
finish();
}
});
notifyLocationServices.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
notifyLocationServices.show();
}
}
public void searchNearestPlace(String v2txt) {
Log.e("TAG", "Started");
v2txt = v2txt.toLowerCase();
String[] placesS = {"accounting", "airport", "aquarium", "atm", "attraction", "bakery", "bakeries", "bank", "bar", "cafe", "campground", "casino", "cemetery", "cemeteries", "church", "courthouse", "dentist", "doctor", "electrician", "embassy", "embassies", "establishment", "finance", "florist", "food", "grocery", "groceries", "supermarket", "gym", "health", "hospital", "laundry", "laundries", "lawyer", "library", "libraries", "locksmith", "lodging", "mosque", "museum", "painter", "park", "parking", "pharmacy", "pharmacies", "physiotherapist", "plumber", "police", "restaurant", "school", "spa", "stadium", "storage", "store", "synagog", "synagogue", "university", "universities", "zoo"};
String[] placesM = {"amusement park", "animal care", "animal care", "animal hospital", "art gallery", "art galleries", "beauty salon", "bicycle store", "book store", "bowling alley", "bus station", "car dealer", "car rental", "car repair", "car wash", "city hall", "clothing store", "convenience store", "department store", "electronics store", "electronic store", "fire station", "funeral home", "furniture store", "gas station", "general contractor", "hair care", "hardware store", "hindu temple", "home good store", "homes good store", "home goods store", "homes goods store", "insurance agency", "insurance agencies", "jewelry store", "liquor store", "local government office", "meal delivery", "meal deliveries", "meal takeaway", "movie rental", "movie theater", "moving company", "moving companies", "night club", "pet store", "place of worship", "places of worship", "post office", "real estate agency", "real estate agencies", "roofing contractor", "rv park", "shoe store", "shopping mall", "subway station", "taxi stand", "train station", "travel agency", "travel agencies", "veterinary care"};
int index;
for (int i = 0; i <= placesM.length - 1; i++) {
Log.e("TAG", "forM");
if (v2txt.contains(placesM[i])) {
Log.e("TAG", "sensedM?!");
index = i;
Uri gmmIntentUri = Uri.parse("geo:" + latitude + "," + longitude + "?q=" + placesM[index]);
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
startActivity(mapIntent);
finish();
}
}
for (int i = 0; i <= placesS.length - 1; i++) {
Log.e("TAG", "forS");
if (v2txt.contains(placesS[i])) {
Log.e("TAG", "sensedS?!");
index = i;
Uri gmmIntentUri = Uri.parse("geo:" + latitude + "," + longitude + "?q=" + placesS[index]);
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
startActivity(mapIntent);
finish();
}
}
}
}
El problema es que siempre y siempre la ubicación devuelve nulo. Y sé con certeza que otra aplicación Jarvis realiza fácilmente la tarea siempre que la ubicación esté habilitada, de lo contrario, simplemente se lo pide al usuario. Pero en las mismas condiciones, mi aplicación siempre falla.
Que he hecho:
- Pasé día y noche tratando de resolver este problema.
- Navegado a través de numerosas páginas sobre el tema.
- Intenté diferentes códigos propios.
Y aún sucede. Soy un principiante en Android. Y por favor, por favor, ayúdame. ¿No hay forma posible de resolver mi problema? incluso pensó que otra aplicación de alguna manera logra hacerlo.
Este es mi LogCat.
Process: com.kkze.Mappy, PID: 6742
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.kkze.Mappy/com.kkze.Mappy.PlacesDecoder}: java.lang.NullPointerException: Attempt to invoke virtual method ''double android.location.Location.getLatitude()'' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2658)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2723)
at android.app.ActivityThread.access$900(ActivityThread.java:172)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1422)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5832)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method ''double android.location.Location.getLatitude()'' on a null object reference
at com.kkze.Mappy.PlacesDecoder.getLocation(PlacesDecoder.java:62)
at com.kkze.Mappy.PlacesDecoder.onCreate(PlacesDecoder.java:32)
at android.app.Activity.performCreate(Activity.java:6221)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2611)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2723)
at android.app.ActivityThread.access$900(ActivityThread.java:172)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1422)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5832)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
También verificar la ubicación! = Nulo requiere el permiso ACCESS_FINE_LOCATION, lo que desordena mi aplicación y hace que siempre regrese como nula.
Como Jon Skeet mencionó en los comentarios, el método
getLastKnownLocation()
puede y devolverá nulo.
El principal problema es que no solicita una solicitud al sistema operativo para un nuevo bloqueo de ubicación, sino que solo verifica si hubo una última ubicación conocida de la solicitud de ubicación de otra aplicación.
Si ninguna otra aplicación había realizado recientemente una solicitud de ubicación, entonces se le devuelve una ubicación nula.
La única forma de garantizar que realmente obtenga una ubicación es solicitar una, y esto se hace con una llamada a
requestLocationUpdates()
.
La ubicación pasada al método de devolución de llamada
onLocationChanged()
no será nula, ya que la devolución de llamada solo ocurre en un bloqueo de ubicación exitoso.
Solo para tener en cuenta, todo el tiempo que su aplicación esté registrada para actualizaciones de ubicación, causará una pérdida de batería adicional, así que asegúrese de anular el registro de actualizaciones de ubicación lo antes posible. Aquí parece que puede anular el registro tan pronto como llegue la primera ubicación.
Además, es posible que desee considerar mostrar un cuadro de diálogo de progreso en esta Actividad mientras espera un bloqueo de ubicación para dar al usuario algunos comentarios de que la aplicación está esperando algo.
Aquí está la estructura general de cómo debería verse su código:
public class MainActivity extends Activity
implements LocationListener {
Intent intentThatCalled;
public double latitude;
public double longitude;
public LocationManager locationManager;
public Criteria criteria;
public String bestProvider;
String voice2text; //added
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentThatCalled = getIntent();
voice2text = intentThatCalled.getStringExtra("v2txt");
getLocation();
}
public static boolean isLocationEnabled(Context context)
{
//...............
return true;
}
protected void getLocation() {
if (isLocationEnabled(MainActivity.this)) {
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
criteria = new Criteria();
bestProvider = String.valueOf(locationManager.getBestProvider(criteria, true)).toString();
//You can still do this if you like, you might get lucky:
Location location = locationManager.getLastKnownLocation(bestProvider);
if (location != null) {
Log.e("TAG", "GPS is on");
latitude = location.getLatitude();
longitude = location.getLongitude();
Toast.makeText(MainActivity.this, "latitude:" + latitude + " longitude:" + longitude, Toast.LENGTH_SHORT).show();
searchNearestPlace(voice2text);
}
else{
//This is what you need:
locationManager.requestLocationUpdates(bestProvider, 1000, 0, this);
}
}
else
{
//prompt user to enable location....
//.................
}
}
@Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
}
@Override
public void onLocationChanged(Location location) {
//Hey, a non null location! Sweet!
//remove location callback:
locationManager.removeUpdates(this);
//open the map:
latitude = location.getLatitude();
longitude = location.getLongitude();
Toast.makeText(MainActivity.this, "latitude:" + latitude + " longitude:" + longitude, Toast.LENGTH_SHORT).show();
searchNearestPlace(voice2text);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
public void searchNearestPlace(String v2txt) {
//.....
}
}
La excepción de puntero nulo ocurre porque su aplicación no solicita la ubicación actual, sino que usa la última ubicación encontrada y solo verifica que haya activado su ubicación y ejecute cualquier otra aplicación que use su ubicación actual. Después de eso solo intenta ejecutar tu proyecto nuevamente. Espero que esto resuelva tu problema.
aquí hay otra forma de hacer esto, su concepto de ubicación de fusibles. He usado esto y fue exitoso para mí. mFusedLocationClient = LocationServices.getFusedLocationProviderClient (this);
es la ubicación fusionada de la declaración
@SuppressWarnings( {"MissingPermission"})
private void enableLocationComponent() {
System.out.println("on map click is here in permission///////////////");
// Check if permissions are enabled and if not request
if (PermissionsManager.areLocationPermissionsGranted(this)) {
// Activate the MapboxMap LocationComponent to show user location
// Adding in LocationComponentOptions is also an optional parameter
LocationComponent locationComponent = mapboxMap.getLocationComponent();
locationComponent.activateLocationComponent(this);
locationComponent.setLocationComponentEnabled(true);
// Set the component''s camera mode
locationComponent.setCameraMode(CameraMode.TRACKING);
mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
originLocation=location;
// Got last known location. In some rare situations this can be null.
if (location != null) {
originLocation=location;
System.out.println(" permission granted location is in iff ++///////////////"+location);
}
}
});
//originLocation = locationComponent.getLastKnownLocation();
System.out.println("origin location is that//////////"+originLocation);
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
Toast.makeText(this, "granted", Toast.LENGTH_LONG).show();
}
@Override
public void onExplanationNeeded(List<String> permissionsToExplain) {
Toast.makeText(this, R.string.user_location_permission_explanation, Toast.LENGTH_LONG).show();
}
@Override
public void onPermissionResult(boolean granted) {
if (granted) {
enableLocationComponent();
} else {
Toast.makeText(this, R.string.user_location_permission_not_granted, Toast.LENGTH_LONG).show();``
finish();
}
}
escribió códigos que obtienen su ubicación actual (latlng) y este error se debe a que su gps (ubicación) en su dispositivo Android real no está encendido. Lo encendí y funciona para mí. espero ser útil