web-dev-qa-db-ja.com

nullオブジェクト参照の仮想メソッド 'double Android.location.Location.getLatitude()'の呼び出しエラー

私がやろうとしているのは、好きなタイプの場所のリストをユーザーに取得させることです。たとえば、入力が病院の場合、アプリケーションは検索文字列「病院」でGoogleマップを開きます。しかし、ドキュメントで示唆されているように、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)

また、location!= nullの確認には、ACCESS_FINE_LOCATION権限が必要です。これにより、アプリが台無しになり、常にnullとして返されます。

10
KISHORE_ZE

Jon Skeetがコメントで言及したように、getLastKnownLocation()メソッドはnullを返すことができます。主な問題は、新しいロケーションロックの要求をOSに要求せず、代わりに、他のアプリのロケーションリクエストから最後の既知のロケーションがあったかどうかを確認することです。他のアプリが最近位置情報リクエストを行っていない場合、null位置情報が返されます。

実際に場所を取得することを保証する唯一の方法は、場所を要求することであり、これは requestLocationUpdates() への呼び出しで行われます。

onLocationChanged()コールバックメソッドに渡される場所は、コールバックが成功した場所ロックでのみ発生するため、nullにはなりません。

ただ、アプリが位置情報の更新のために登録されている間は、バッテリーの消耗を引き起こすため、できるだけ早く位置情報の更新の登録を解除してください。ここでは、最初の場所が入ったらすぐに登録を解除できるようです。

また、アプリが何かを待っているというフィードバックをユーザーに提供するために、ロケーションロックを待機している間、このアクティビティに進行状況ダイアログを表示することを検討することもできます。

コードの外観の一般的な構造は次のとおりです。

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

現在の位置(latlng)を取得するコードを書いたのですが、このエラーは、実際のAndroidデバイスの電源が入らないため、gps(location)が原因です。役に立つことを願っています

1
Mosayeb Masoumi

getLocationメソッドでこれを変更します

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

これを行う別の方法があります。これは私がこれを使用して成功したFuseロケーションコンセプトですmFusedLocationClient = LocationServices.getFusedLocationProviderClient(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();
    }
}
0
Qasim

Nullポインター例外は、アプリが現在の場所を要求せず、最後に見つかった場所を使用し、現在の場所をオンにし、現在の場所を使用する他のアプリを実行するだけであるために発生します。その後、プロジェクトを再度実行してください。これで問題が解決することを願っています。

0
Yash Patel