错误在null对象引用上调用虚拟方法'double android.location.Location.getLatitude()'

我所要做的就是让用户得到他喜欢的地方的名单。 例如,如果input是医院我的应用程序将打开searchstring“医院”谷歌地图。 但正如使用地理编码的文档中所build议的,例如geo:0,0?q=hospital uri显示坐标0纬度和0经度附近的所有医院。 所以当我试图通过使用下面的代码首先获得用户坐标。

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

问题是总是和总是位置返回null。 而且我知道,另一个应用程序Jarvis只要位置启用就可以轻松完成任务,如果不是,则只需要用户即可。 但在相同的条件下,我的应用程序总是崩溃。

我做了什么:

  1. 用尽日夜试图解决这个问题。
  2. 浏览了许多关于这个话题的网页。
  3. 试了我自己的不同代码。

它仍然发生。 我是Android的初学者。 请,请帮助我。 有没有办法解决我的问题? 甚至认为其他应用程序设法做到这一点。

这是我的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) 

同时检查位置!= null需要ACCESS_FINE_LOCATION权限,它会弄乱我的应用程序,导致它始终返回为空。

正如Jon Skeet在评论中提到的那样, getLastKnownLocation()方法可以并且将返回null。 主要的问题是,它不会提示操作系统请求新的位置locking,而只是检查是否存在来自其他某个应用的位置请求的最后一个已知位置。 如果最近没有其他应用程序发出位置请求,则会返回空位置。

唯一保证你真正获得位置的方法是请求一个位置,这是通过调用requestLocationUpdates()

传递给onLocationChanged()callback方法的位置不会为空,因为callback只发生在成功的位置locking上。

请注意,您的应用程序在注册位置更新的整个过程中,都会造成额外的电量耗尽,因此请务必尽快取消注册位置更新。 在这里,看起来您可以在第一个位置进来时立即取消注册。

此外,您可能需要考虑在此Activity中显示进度对话框,同时等待位置locking,以便为用户提供一些有关应用程序正在等待的反馈。

下面是你的代码的外观的一般结构:

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

改变你的getLocation方法

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