2015-08-29 17 views
7

Tutto quello che sto cercando di fare è consentire all'utente di ottenere un elenco dei luoghi di tipi che gli piacciono. Ad esempio, se l'input era in ospedale, la mia applicazione apriva google maps con la stringa di ricerca "Hospital". Ma come suggerito nella documentazione usando il geocodice come geo:0,0?q=hospital uri mostra tutti gli ospedali vicino alle coordinate 0 latitudine & 0 longitudine. Quindi, quando ho provato a ottenere le coordinate degli utenti prima usando il seguente codice.Errore richiamare il metodo virtuale 'double android.location.Location.getLatitude()' su un oggetto nullo di riferimento

Luoghi 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(); 
     } 
    } 
} 
} 

Il problema è che sempre e da sempre luogo restituisce null. E so per certo che un'altra applicazione Jarvis svolge facilmente il compito fintanto che la posizione è abilitata, in caso contrario chiede semplicemente all'utente di farlo. Ma alle stesse condizioni la mia applicazione si blocca sempre.

quello che ho fatto:

  1. giornata passata e notte cercando di risolvere questo problema.
  2. Sfogliate numerose pagine sull'argomento.
  3. Ho provato diversi codici personali.

E succede ancora. Sono un principiante in Android. E per favore, per favore aiutatemi. Non c'è un modo per risolvere il mio problema? anche pensato che altre applicazioni in qualche modo riescono a farlo.

Questo mio 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) 

verifica anche per la posizione! = Null richiede l'autorizzazione ACCESS_FINE_LOCATION che scombina la mia app inducendolo a tornare sempre nullo.

+3

Quindi 'getLastKnownLocation' sta tornando null, che è documentato può succedere: " Se il fornitore è attualmente disattivato, viene restituito null" Il tuo codice dovrebbe controllarlo e gestirlo di conseguenza. Dici "alle stesse condizioni" - sono quelle condizioni in cui la posizione è attualmente disabilitata? Perché se così fosse, non c'è altro da spiegare, davvero. –

+0

Come devo fare? Alle stesse condizioni l'altra app lo fa. O potrebbe esserci un modo per risolvere il mio problema senza ottenere la posizione dell'utente. Per favore, aiuto. –

+0

Mi dispiace se sto facendo pressione su di te o qualcosa del genere ma sono davvero frustrato dal fatto che non riesco nemmeno a risolvere qualcosa di così semplice, anche dopo aver setacciato il Web al meglio che posso. Scusate. È già finita la mezzanotte e non riesco ancora a risolvere il problema. –

risposta

12

Come Jon Skeet accennato nei commenti, il metodo getLastKnownLocation() può e vuole restituire null. Il problema principale è che non richiede una richiesta al sistema operativo per un nuovo blocco di posizione, ma controlla solo se c'era un'ultima posizione nota da qualche altra richiesta di posizione dell'app. Se nessun'altra app ha recentemente effettuato una richiesta di posizione, ti viene restituita una posizione nullo.

L'unico modo per garantire che si ottenga effettivamente una posizione è di richiederne uno, e ciò avviene con una chiamata a requestLocationUpdates().

La posizione passata nel metodo di richiamata onLocationChanged() non sarà nullo, poiché la richiamata si verifica solo in un blocco posizione riuscito.

Giusto per notare, per tutto il tempo in cui la tua app è registrata per gli aggiornamenti di posizione, causerà un ulteriore esaurimento della batteria, quindi assicurati di annullare la registrazione per gli aggiornamenti di posizione il prima possibile. Qui sembra che tu possa annullare la registrazione non appena arriva la prima posizione.

Inoltre, potresti voler considerare di mostrare una finestra di avanzamento in questa attività mentre aspetta un blocco di posizione per dare all'utente un po 'di spazio. feedback che l'app è in attesa di qualcosa.

Qui è la struttura generale di ciò che il codice dovrebbe essere simile:

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) { 
     //..... 
    } 
} 
+0

Grazie per la risposta, ci proverò e ti farò sapere. –

+0

Grazie. Sta funzionando! Grazie mille. Finalmente ha funzionato. Ho anche aggiunto una schermata di caricamento o piuttosto una finestra di dialogo di avanzamento e ora funziona perfettamente. Ancora una volta, grazie mille Daniel. –

+0

Pensavo avessi detto che non eri in grado di confrontare 'location' con' null', che è ciò che fa questo codice ... –

1

Modificare questo nel metodo getLocation

if (isLocationEnabled(PlacesDecoder.this) && location != null) { 
... 
} 
+0

Anche il controllo per la posizione! = null richiede il permesso ACCESS_FINE_LOCATION che danneggia la mia app causandone il ritorno sempre come null. –

+0

@KISHORE_ZE: Come ho già detto in altri commenti, non è vero. Sta solo confrontando un riferimento con null - come potrebbe richiedere più autorizzazioni? * Ottenere * la posizione potrebbe (anche se sembra che dovresti solo richiedere quell'autorizzazione comunque) ma non è lo stesso che controllare se è nullo. –

+0

Ma mi sta chiedendo. Se vuoi ti mostrerò il logcat. Non ho il PC ora ma lo compilerò nel telefono e ti farò sapere. –

Problemi correlati

 Problemi correlati