代码只会返回 0.0, 0.0 GPS 坐标,同时抛出 NullPointerException

2022-01-22 00:00:00 gps android java

这是我对 Android Location API 的第 n 次尝试,但我似乎无法让它正常工作.本教程似乎是最有前途的,但我似乎只能让这段代码返回 0.0、0.0 的 GPS 坐标,这不是很有用......

getLocation() 返回 java.lang.NullPointerException 错误似乎有一个线索,但我什至不确定应该从哪里开始寻找它.

这是错误:

 W/System.err: java.lang.NullPointerExceptionW/System.err:在 android.content.ContextWrapper.checkPermission(ContextWrapper.java:557)

我尝试制作一个新的权限块,粘贴在底部,但它给出了同样的错误.

任何人都可以在这里指出正确的方向吗?

代码分为两个类文件:MainActivity.java 和 GPSTracker.java.

GPSTracker.java

 包com.tutorial.android.location.api;//http://www.androidhive.xyz/2016/07/android-gps-location-manager-tutorial.html//进行了一些修改,尤其是对于新权限导入android.Manifest;导入android.app.Activity;导入 android.app.AlertDialog;导入android.app.Service;导入android.content.Context;导入 android.content.DialogInterface;导入android.content.Intent;导入 android.content.pm.PackageManager;导入android.location.Location;导入 android.location.LocationListener;导入 android.location.LocationManager;导入android.os.Bundle;导入android.os.IBinder;导入android.provider.Settings;导入 android.support.annotation.Nullable;导入android.support.v4.app.ActivityCompat;导入android.util.Log;公共类 GPSTracker 扩展服务实现 LocationListener {私有字符串 TAG = "¤¤";私有最终上下文 mContext;公共 GPSTracker(上下文 mContext){this.mContext = mContext;this.getLocation();}布尔 isGPSEnabled = false;布尔 isNetworkEnabled = false;boolean canGetLocation = false;位置位置;双纬度;双经度;私有静态最终长 MIN_DISTANCE_CHANGE_FOR_UPDATE = 10;//10 米私有静态最终 long MIN_TIME_BW_UPDATES = 1000 * 60 * 1;//30 秒受保护的位置管理器位置管理器;公共位置 getLocation() {尝试 {如果(位置管理器 == 空){locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);}if(isGPSEnabled != true) {isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);}如果(isNetworkEnabled != true){isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}if (!isGPSEnabled && !isNetworkEnabled) {//未启用提供程序:pLog.e(TAG, "getLocation() 没有提供者:(");} 别的 {this.canGetLocation = true;//获取网络位置如果(isNetworkEnabled){//权限块:if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {//TODO: 考虑调用//ActivityCompat#requestPermissions//这里请求丢失的权限,然后覆盖//public void onRequestPermissionsResult(int requestCode, String[] 权限,//int[] grantResults)//处理用户授予权限的情况.请参阅文档//对于 ActivityCompat#requestPermissions 了解更多详细信息.//返回待办事项;} 别的 {Log.e(TAG, "getLocation() 权限被拒绝");}locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATE,这个);如果(位置管理器!= null){位置 = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);如果(位置!= null){纬度 = location.getLatitude();经度 = location.getLongitude();}}}//获取GPS位置如果(是GPS启用){如果(位置 == 空){locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATE,这个);Log.d(TAG, "getLocation() GPS 已启用");如果(位置管理器!= null){位置 = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);如果(位置!= null){纬度 = location.getLatitude();经度 = location.getLongitude();}}}}}} 捕捉(异常 e){Log.e(TAG, "getLocation() 错误...:" + e);e.printStackTrace();}返回位置;}公共双getLatitude(){如果(位置!= null){纬度 = location.getLatitude();}返回纬度;}公共双getLongitude(){如果(位置!= null){经度 = location.getLongitude();}返回经度;}@Nullable@覆盖公共IBinder onBind(意图意图){返回空值;}@覆盖公共无效onLocationChanged(位置位置){}@覆盖public void onStatusChanged(String provider, int status, Bundle extras) {}@覆盖公共无效onProviderEnabled(字符串提供者){//GPS 开启Log.d(TAG, "GPS 开启");}@覆盖公共无效onProviderDisabled(字符串提供者){//GPS 关闭Log.d(TAG, "GPS 关闭");}//GPS 对话框公共布尔canGetLocation(){返回 this.canGetLocation;}//测试时不需要这个公共无效 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});//嗯...}});alertDialog.show();}公共无效停止使用GPS(){如果(位置管理器!= null){locationManager.removeUpdates(GPSTracker.this);}}}

在 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)) {//解释:pLog.i(TAG, "NOpe...");} 别的 {//请求权限Log.d(TAG, "请求新权限");ActivityCompat.requestPermissions((Activity) mContext, new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, 1);}}

MainActivity.java

包com.tutorial.android.location.api;导入android.support.v7.app.AppCompatActivity;导入android.os.Bundle;导入android.util.Log;公共类 MainActivity 扩展 AppCompatActivity {字符串标签 = "¤";GPSTracker 全球定位系统;@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);gps = new GPSTracker(this);如果(gps.canGetLocation()){Log.i(TAG, "onCreate() GPS 开启");Log.i(TAG, "onCreate() " + gps.getLatitude()+ ", " + gps.getLongitude());} 别的 {Log.d(TAG, "onCreate() GPS 已关闭");}}}

解决方案

这个教程似乎是最有前途的

这真是糟糕的代码.

<块引用>

我似乎只能让这段代码返回 0.0、0.0 的 GPS 坐标,这不是很有用

这是因为只有当 getLastKnownLocation() 碰巧返回一个位置时,它才会有一个位置.不太可能这样做.

<块引用>

在 GPSTracker.java 中重写但仍然不能工作的权限块:

这里有两个问题:

  1. 您不能向服务请求权限.

  2. 这不是真正的服务.此代码的作者选择创建一个扩展 Service 的类,而无需实际实现或正确使用该服务.这就是导致您的 NullPointerException 的原因,因为这不是正确初始化的 Context.

<块引用>

任何人都可以在这里指出正确的方向吗?

把这一切都扔掉.

FWIW,这里是 我的示例应用,用于使用LocationManager API.

配方相当简单:

第 1 步:通过在某些 Context 上调用 getSystemService(Context.LOCATION_SERVICE) 来获取 LocationManager.我碰巧在片段中这样做:

 @Override公共无效 onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);设置保留实例(真);模板=getActivity().getString(R.string.url);经理=(位置管理器)getActivity().getSystemService(Context.LOCATION_SERVICE);}

第 2 步:调用 requestUpdates(),传入实现 LocationListener 的内容.就我而言,这恰好是片段本身:

 @Override@SuppressWarnings({"MissingPermission"})公共无效 onStart() {super.onStart();mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,3600000,1000,这个);}

第 3 步:在 LocationListeneronLocationChanged() 中,对获得的 Location 执行某些操作,在我的例子中是执行 AsyncTask 以获取天气预报:

 @Override公共无效onLocationChanged(位置位置){新的 FetchForecastTask().execute(location);}

第 4 步:完成后调用 removeUpdates():

 @Override@SuppressWarnings({"MissingPermission"})公共无效 onStop() {mgr.removeUpdates(this);超级.onStop();}

就是这样(除了运行时权限的东西,我将其抽象为 AbstractPermissionsActivity).

如果需要,可以使用 getLastKnownLocation() 作为优化,但不要依赖它.

This is my n-th try with the Android Location API, and I just can't seem to get it to work properly. 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...

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.

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.

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:

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

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

That is because it will only ever have a location if getLastKnownLocation() happens to return one. It is unlikely to do so.

Rewritten but still not working permissions block in 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. This is what is causing your NullPointerException, as this is not a properly initialized 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.

The recipe is fairly simple:

Step #1: Get a LocationManager by calling getSystemService(Context.LOCATION_SERVICE) on some Context. 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. 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:

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

Step #4: Call removeUpdates() when you are done:

  @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).

If you want, use getLastKnownLocation() as an optimization, but do not rely upon it.

相关文章