为什么我的 OnLocationChanged() 从未被调用?

15

我想做什么:

我正试图开发一个应用程序,它只需要在一个活动开始时获取用户的位置。因此,仅当用户在活动范围内时,位置才会通过网络或GPS更新。相应地,用户可以选择室内地图。

我的问题是什么:

然而,我发现该应用程序始终使用历史位置,并且从未更新位置。我怀疑我的

location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)

有问题,但我不确定问题出在哪里。

相关代码片段:

在我的Activity中,我有:

    locationDetector = new LocationDetector(MapSelectionActivity.this);
    // try to get the current location
    if (locationDetector.checkLocationServiceAvailability()) {
        location = locationDetector.getLocation();
        if (location != null) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
        }
        Log.d("MapSelectionActivity", latitude + " " + longitude);
        //locationDetector.stopLocalization(); // stop the localization to save the energy
    } else { // if no location service, requires the user to turn GPS on
        locationDetector.showSettingsAlert();
    }

我的LocationDetector类如下:

public final class LocationDetector implements LocationListener {

    private final Context mContext;

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

    private Location location;
    private String providerUsed;

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 0 meters
    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = (long) (1000 * 60 * 0.5); // 0.5 minute

    // Declaring a Location Manager
    protected LocationManager locationManager;

    // constructor
    public LocationDetector(Context context) {

        this.mContext = context;

        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
    }

    // NOTE call  checkLocationServiceAvailability(); first before calling this!
    public Location getLocation() {
// I SUSPECT SOMETHING IS WRONG HERE
        if (isNetworkEnabled) { // use network

            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
            Log.d("LocationDetector", "Using Network");
            if (locationManager != null) {
                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }

            providerUsed = "Network";

        } else if (isGPSEnabled) { // use GPS

            if (location == null) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                Log.d("LocationDetector", "Using GPS");
                if (locationManager != null) {
                    location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                }
            }

            providerUsed = "GPS";

        } else { // neither the network nor the GPS is on

            providerUsed = null;

            Toast.makeText(mContext, "Location service is unavaliable", Toast.LENGTH_SHORT).show();
        }

        return location;
    }

    // call this to restart requesting the detecting
    public void startLocalization() {

        if (locationManager != null) {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
        }
    }

    // call this to stop the detecting to save power
    public void stopLocalization() {

        if (locationManager != null) {
            locationManager.removeUpdates(LocationDetector.this);
        }
    }

    // check location service availability
    public boolean checkLocationServiceAvailability() {

        // check GPS on or off
        isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        // check Internet access
        ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnected()) {
            isNetworkEnabled = true;
        } else {
            isNetworkEnabled = false;
        }

        if (isGPSEnabled || isNetworkEnabled) {
            canGetLocation = true;
        } else {
            canGetLocation = false;
        }

        return canGetLocation;
    }

    public String getLocationProvider() {

        return providerUsed;
    }

    // show alert dialog to direct the users to the settings
    public void showSettingsAlert() {

        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

        // make it uncancellable
        alertDialog.setCancelable(false);

        // Setting Dialog Title
        alertDialog.setTitle("Forgot to turn GPS on?");

        // Setting Dialog Message
        alertDialog.setMessage("Currently there is no Internet access.\n\nLocalization requires GPS when Internet is unavailiable.\n\nDo you want to enable GPS so as to proceed?");

        // On pressing Settings button
        alertDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);

                Toast.makeText(mContext, "After enabling GPS, press the physical 'Back' button to return", Toast.LENGTH_LONG).show();
            }
        });

        // on pressing cancel button
        alertDialog.setNegativeButton("No", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();

                Toast.makeText(mContext, "No location service, please choose map manually", Toast.LENGTH_LONG).show();
            }
        });

        // Showing Alert Message
        alertDialog.show();
    }

    @Override
    public void onLocationChanged(Location _location) {
// IT NEVER GETS CALLED
        location = _location;

        // update the text view
        MapSelectionActivity.coordinatesTextView.setText("(" + Math.round(location.getLatitude() * 1000) / 1000.0 + ", " + Math.round(location.getLongitude() * 1000) / 1000.0 + ")");

        // update the marker on Google Maps
        MapSelectionActivity.googleMap.clear();
        MapSelectionActivity.googleMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(), location.getLongitude())).title("I am here!"));
        MapSelectionActivity.googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 15)); // 15 is the approporiate zooming level

        // re-suggest the map
        int recommendedMapSequenceNumber = MapSelectionActivity.mapDatabase.getMapSequenceNumber(location.getLatitude(), location.getLongitude());
        MapSelectionActivity.recommendedMapTextView.setTextColor(Color.parseColor("red"));
        if (recommendedMapSequenceNumber == -1) { // the so-called nearest is still too far

            Toast.makeText(mContext, "Please manually select one to proceed", Toast.LENGTH_LONG).show();
            MapSelectionActivity.recommendedMapTextView.setText("No recommended maps");
            MapSelectionActivity.autoSelectButton.setEnabled(false);
        } else { // suggest a map

            Toast.makeText(mContext, "One suitable map found", Toast.LENGTH_SHORT).show();
            MapSelectionActivity.recommendedMapTextView.setText(MapSelectionActivity.mapDatabase.getMapName(recommendedMapSequenceNumber));
        }

        Toast.makeText(mContext, "New location detected", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

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

    }

}

我从onLocationChanged()中无法看到Toast,这意味着它从未被调用!同时,从地图上可以看出位置没有更新。


你在清单文件中授予了足够的权限吗? - Vigbyor
好的,现在请注释此代码 if (locationManager != null) { location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); },然后再尝试执行您的代码。 - Vigbyor
@Vigbyor 刚刚尝试了一下。将其注释掉会导致找不到位置。坐标为(-1,-1),因为我将它们初始化为这样。 - Sibbs Gambling
你的代码是正确的...但是你需要进行真实的测试...我是说如果你正在使用LocationManager.GPS_PROVIDER,那么你需要在开放的地方进行测试。我已经测试过这段代码http://stackoverflow.com/a/17677433/1140237,在我的情况下工作正常...为了获得更准确的位置,请查看http://developer.android.com/about/versions/android-4.2.html#Behaviors。 - user1140237
@perfectionm1ng - 把它改成零只会让情况变得更糟。你需要延长时间并给予提供者刷新数据的机会 - 零毫无用处。 - g00dy
显示剩余5条评论
3个回答

1

由于获取Android位置似乎是一个常见问题,因此我将列出一份常见修复清单:


  1. 检查您的清单文件!

    最常见的问题之一是没有正确授予权限。如果您正在使用GPS(带或不带网络),请使用<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>,否则请使用<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>。Google的FusedLocationApi需要ACCESS_FINE_LOCATION


  1. (对于Android 6+) 检查运行时权限

    检查并请求权限!如果你从未被授予权限,你最终会遇到崩溃或更糟糕的情况(如果你捕获了所有异常),你将毫无任何指示!无论用户在应用程序启动时是否授予你权限,都要始终检查是否拥有所有调用所需的权限。用户可以轻松地进入设置并撤销它们。


  1. 仔细检查你的代码!

    你确定你传递了正确的监听器吗?你是否将那个BroadcastReceiverIntentService添加到了你的清单文件中?你是否在BroadcastReceiver类上使用了PendingIntent.getService(),或者在IntentService类上使用了getBroadcast()?你确定你没有在请求后立即在代码其他地方取消注册监听器吗?


  1. 检查设备设置!

    显然,确保您已经开启了位置服务。

    enter image description here

    如果您正在使用网络服务,您是否开启了“始终可用的扫描”?您的位置模式设置为“最佳”(“高精度”)还是“省电”(“仅限网络”)?

    enter image description here

    如果您正在使用GPS,您是否在位置模式中开启了“最佳”(“高精度”)或“仅设备”?

    enter image description here


  1. 仔细检查你的代码!

    是的,这里有两次。你是否尝试使用 LocationListener 而不是 PendingIntent,或者反过来,以确保你正确地实现了 LocationManager?你确定位置请求没有在 Activity 或 Service 生命周期的某个部分中被删除,而你没有预料到吗?


  1. 检查你的周围环境!

    你是在旧金山市中心一栋楼的一楼测试GPS吗?你是在荒无人烟的地方测试网络位置吗?你在一个没有任何无线电信号的秘密地下掩体工作,想知道为什么设备无法获取位置吗?在尝试解决位置问题时,始终要仔细检查周围环境!


在寻找那些神秘的解决方案之前,可能有许多其他不太明显的原因导致位置无法工作,但请先运行此快速检查表。


0

locationManager.requestLocationUpdates (LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

这行代码的作用是请求位置更新。

其中,MIN_DISTANCE_CHANGE_FOR_UPDATES = 0 米。

MIN_TIME_BW_UPDATES = 1000 秒。

回到你的问题,如果当前位置更新与上次已知位置不匹配,则会调用onLocationChanged()方法。

更新的位置将在每个minTime(在我的情况下为1000毫秒)和设备移动minDistance(在我的情况下为0米)距离时更改。

希望您能理解这些内容。


0

没错,你可能面临着硬件问题。请在设备上安装GPS状态应用程序,以查看你的GPS是否正常工作!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接