简体   繁体   English

代码只会在抛出NullPointerException时返回0.0、0.0 GPS坐标

[英]Code will only return 0.0, 0.0 GPS coordinate while throwing NullPointerException

This is my n-th try with the Android Location API, and I just can't seem to get it to work properly. 这是我对Android Location API的第n次尝试,但我似乎无法使其正常运行。 This tutorial seems like the most promising, but I can only seem to get this code to return a GPS coordinate of 0.0, 0.0 which isn't very useful... 本教程似乎是最有前途的,但我似乎只能让此代码返回GPS坐标0.0、0.0,这不是很有用...

There seems to be a clue in that getLocation() returns a java.lang.NullPointerException error, but I'm not sure where I should even start looking for it. getLocation()返回java.lang.NullPointerException错误似乎有些线索,但是我不确定我应该从哪里开始寻找它。

Here's the error: 这是错误:

 W/System.err: java.lang.NullPointerException
 W/System.err:     at android.content.ContextWrapper.checkPermission(ContextWrapper.java:557)

I tried making a new permissions block, pasted at the bottom, but it just gave the same error. 我尝试制作一个新的权限块(粘贴在底部),但它给出了相同的错误。

Can anyone please point me in the right direction here? 有人可以在这里指出正确的方向吗?

The code is split over two class-files: MainActivity.java and GPSTracker.java. 该代码分为两个类文件:MainActivity.java和GPSTracker.java。

GPSTracker.java GPSTracker.java

    package com.tutorial.android.location.api;

// http://www.androidhive.xyz/2016/07/android-gps-location-manager-tutorial.html
// with some modifications, especially for new permissions

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;

public class GPSTracker extends Service implements LocationListener {
    private String TAG = "¤¤";
    private final Context mContext;

    public GPSTracker(Context mContext) {
        this.mContext = mContext;
        this.getLocation();
    }

    boolean isGPSEnabled = false;
    boolean isNetworkEnabled = false;
    boolean canGetLocation = false;

    Location location;
    double latitude;
    double longitude;

    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATE = 10; // 10 meters
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 30 sec

    protected LocationManager locationManager;

    public Location getLocation() {
        try {

            if(locationManager == null) {
                locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
            }
            if(isGPSEnabled != true) {
                isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            }
            if(isNetworkEnabled != true) {
                isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            }

            if (!isGPSEnabled && !isNetworkEnabled) {
                // no provider enabled :p
                Log.e(TAG, "getLocation() no provider :(");
            } else {
                this.canGetLocation = true;
                // get network location
                if (isNetworkEnabled) {
                    // permission block:
                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                        //    ActivityCompat#requestPermissions
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.
                        // return TODO;
                    } else {
                        Log.e(TAG, "getLocation() permission DENIED");
                    }
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATE, this);
                    if(locationManager != null) {
                        location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if(location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                // get GPS location
                if(isGPSEnabled) {
                    if(location == null) {
                        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATE, this);
                        Log.d(TAG, "getLocation() GPS Enabled");
                        if(locationManager != null){
                            location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if(location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "getLocation() ERROR...: " + e);
            e.printStackTrace();
        }
        return location;
    }

    public double getLatitude() {
        if(location != null) {
            latitude = location.getLatitude();
        }
        return latitude;
    }

    public double getLongitude() {
        if(location != null) {
            longitude = location.getLongitude();
        }
        return longitude;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onLocationChanged(Location location) {

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderEnabled(String provider) {
        // GPS is ON
        Log.d(TAG, "GPS is ON");
    }

    @Override
    public void onProviderDisabled(String provider) {
        // GPS is OFF
        Log.d(TAG, "GPS is OFF");
    }

    // GPS dialog
    public boolean canGetLocation() {
        return this.canGetLocation;
    }
    // don't really need this when testing
    public void showSettingsAlert() {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

        alertDialog.setTitle(R.string.gps_settings_title);

        alertDialog.setMessage(R.string.gps_settings_msg);
        alertDialog.setPositiveButton(R.string.gps_settings_word, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivities(new Intent[]{intent}); // hm...
            }
        });
        alertDialog.show();
    }

    public void stopUsingGPS() {
        if(locationManager != null) {
            locationManager.removeUpdates(GPSTracker.this);
        }
    }
}

Rewritten but still not working permissions block in GPSTracker.java: 重写了GPSTracker.java中的但仍不起作用的权限块:

int permissionCheck = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if(!(permissionCheck == PackageManager.PERMISSION_GRANTED)) {
    if(ActivityCompat.shouldShowRequestPermissionRationale((Activity) mContext, Manifest.permission.ACCESS_FINE_LOCATION)) {
        // explanation :p
        Log.i(TAG, "NOpe...");
    } else {
        // request permission
        Log.d(TAG, "Requestion new permission");
        ActivityCompat.requestPermissions((Activity) mContext, new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, 1);
    }
}

MainActivity.java MainActivity.java

package com.tutorial.android.location.api;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {
    String TAG = "¤";

    GPSTracker gps;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        gps = new GPSTracker(this);

        if(gps.canGetLocation()) {
            Log.i(TAG, "onCreate() GPS is ON");
            Log.i(TAG, "onCreate() " + gps.getLatitude()+ ", " + gps.getLongitude());
        } else {
            Log.d(TAG, "onCreate() GPS is OFF");
        }

    }
}

This tutorial seems like the most promising 本教程似乎是最有前途的

It is truly awful code. 这确实是糟糕的代码。

I can only seem to get this code to return a GPS coordinate of 0.0, 0.0 which isn't very useful 我似乎只能得到此代码以返回0.0、0.0的GPS坐标,这不是很有用

That is because it will only ever have a location if getLastKnownLocation() happens to return one. 这是因为只有在getLastKnownLocation()恰好返回一个位置时,它才会有位置。 It is unlikely to do so. 不太可能这样做。

Rewritten but still not working permissions block in GPSTracker.java: 重写了GPSTracker.java中的但仍不起作用的权限块:

There are two problems here: 这里有两个问题:

  1. You cannot request permissions from a service. 您不能从服务请求权限。

  2. This is not a real service. 这不是真正的服务。 The author of this code elected to create a class that extends Service without actually implementing or using the service properly. 该代码的作者选择创建一个扩展Service的类,而无需实际实现或正确使用该服务。 This is what is causing your NullPointerException , as this is not a properly initialized Context . 这是导致NullPointerException ,因为这不是正确初始化的Context

Can anyone please point me in the right direction here? 有人可以在这里指出正确的方向吗?

Throw all of this out. 把所有这些扔掉。

FWIW, here is my sample app for using the LocationManager API. FWIW,这是使用LocationManager API的示例应用程序

The recipe is fairly simple: 食谱很简单:

Step #1: Get a LocationManager by calling getSystemService(Context.LOCATION_SERVICE) on some Context . 步骤#1:通过在某些Context上调用getSystemService(Context.LOCATION_SERVICE)来获取LocationManager I happen to do that in a fragment: 我碰巧做了一个片段:

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);

    template=getActivity().getString(R.string.url);
    mgr=(LocationManager)getActivity()
      .getSystemService(Context.LOCATION_SERVICE);
  }

Step #2: Call requestUpdates() , passing in something that implements LocationListener . 步骤#2:调用requestUpdates() ,并传入实现LocationListener东西。 In my case, that happens to be the fragment itself: 就我而言,这恰好是片段本身:

  @Override
  @SuppressWarnings({"MissingPermission"})
  public void onStart() {
    super.onStart();

    mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3600000,
      1000, this);
  }

Step #3: In onLocationChanged() of your LocationListener , do something with the Location that you get, which in my case is to execute an AsyncTask to get a weather forecast: 第3步:在onLocationChanged()你的LocationListener ,做的东西Location ,你得到的,这在我的情况是执行AsyncTask获得天气预报:

  @Override
  public void onLocationChanged(Location location) {
    new FetchForecastTask().execute(location);
  }

Step #4: Call removeUpdates() when you are done: 步骤#4:完成后,调用removeUpdates()

  @Override
  @SuppressWarnings({"MissingPermission"})
  public void onStop() {
    mgr.removeUpdates(this);

    super.onStop();
  }

And that's it (other than runtime permission stuff, which I abstract out into an AbstractPermissionsActivity ). 就是这样(运行时权限的东西除外,我将其抽象为AbstractPermissionsActivity )。

If you want, use getLastKnownLocation() as an optimization , but do not rely upon it. 如果需要,可以使用getLastKnownLocation()作为优化 ,但不要依赖它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM