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



我所要做的就是让用户获得他喜欢的类型的位置列表。例如,如果输入的是医院,我的应用程序将打开谷歌地图搜索字符串"医院"。但正如文档中建议的那样,使用地理编码(如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();
        }
    }
}
}

问题是always和always location返回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权限,这会导致我的应用程序总是返回null

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

保证您实际获得位置的唯一方法是请求一个,这是通过调用requestLocationUpdates()来完成的。

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

只是要注意,整个时间你的应用程序注册的位置更新,它会造成额外的电池消耗,所以一定要取消注册的位置更新尽快。这里看起来你可以在第一个位置出现时取消注册。

另外,你可能想要考虑在这个活动中显示一个进度对话框,而它等待一个位置锁定,以便给用户一些反馈,应用程序正在等待的东西。

下面是你的代码的一般结构:
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) {
 ...
}

你写的代码得到你的当前位置(latlng),这个错误是因为你的gps(位置)在你真正的android设备上没有打开。我打开了它,它对我有效。希望对大家有所帮助

这里有另一种方法可以做到这一点,你的保险丝位置概念我已经使用了这个,并成功地对我mFusedLocationClient = locationservices . getfusedlocationprovider (this);

是声明融合位置

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

空指针异常发生,因为你的应用程序不请求当前位置,而是使用最后找到的位置,只是检查你已经打开了你的位置,并运行任何其他应用程序使用你的当前位置。之后再试着运行你的项目。

正如Yash所说,你的应用程序不请求当前位置,而是使用最后发现的位置,一个简单的工作,为我工作的这个错误是,打开你的GPS,在你的手机或模拟器上打开你的谷歌地图应用程序,看到你当前的位置,然后关闭它。现在,当你打开你的当前应用程序(你正在工作)或运行它,它不会给出这个错误。

我使用.getLastLocation()也遇到了同样的问题。然后我使用mMap.setMyLocationEnabeled(true),并使用.setMyLocationEnabeled(true)启用的地图位置按钮获得GPS位置。在那之后,下一次.getLastLocation()工作良好。我不知道确切的原因,但我认为地图上的位置按钮一旦保存了我的当前位置,下次我使用.getLastLocation()时,它不是空的,因为最后的位置已经在那里了。

相关内容

最新更新