You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

安卓应用无法获取位置求助:需等待一天才能获取当前/已知位置(附代码)

Fixing Your Location Fetching Issue for the Used Goods App

Hey Edson, let's break down why your app is taking a full day to get location data and fix it right away—your code has a few critical bugs that are blocking location updates, plus some easy tweaks to make it more reliable.

First, Let's Spot the Critical Bugs in Your Current Code

  • Reversed Permission Check in onLocationChanged: This is the biggest problem! You wrote:
    if (PermissionsUtils.hasPermissions(this, locationPermissions)) {
        return;
    }
    
    This means if the user has granted permissions, you immediately exit the method without processing the location data. That's why you never get any location updates at all!
  • No Fallback for Empty getLastKnownLocation: If there's no saved location, you request updates but don't handle cases where the device can't get a fix quickly.
  • Overly Aggressive Update Parameters: requestLocationUpdates(provider, 1000, 0, this) asks for updates every 1 second and every 0 meters—this is too frequent, drains battery, and might cause the system to throttle your requests.

Fixed Version of Your Code

Let's rewrite the location logic with these fixes, plus add proper permission handling:

// MARK: - GET CURRENT LOCATION ------------------------------------------------------
protected void getCurrentLocation() {
    // First, check if permissions are granted—if not, request them
    if (!PermissionsUtils.hasPermissions(this, locationPermissions)) {
        ActivityCompat.requestPermissions(this, locationPermissions, 1001);
        return;
    }

    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_COARSE); // Use coarse for faster fixes, switch to fine if needed
    criteria.setPowerRequirement(Criteria.POWER_LOW);
    criteria.setAltitudeRequired(false);
    criteria.setBearingRequired(false);

    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    assert locationManager != null;
    String provider = locationManager.getBestProvider(criteria, true);

    // Try last known location first
    currentLocation = locationManager.getLastKnownLocation(provider);
    if (currentLocation != null) {
        getCityCountryNames();
        queryAds(); // Don't forget to trigger your ad query here
    } else {
        // Request a single location update (not continuous) with a timeout
        locationManager.requestSingleUpdate(provider, this, Looper.getMainLooper());
        
        // Add a timeout in case location takes too long
        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            if (currentLocation == null) {
                // Fallback to default location if no fix after 10 seconds
                Configs.simpleAlert(getString(R.string.get_location_failure), AdsListActivity.this);
                currentLocation = new Location("provider");
                currentLocation.setLatitude(Configs.DEFAULT_LOCATION.latitude);
                currentLocation.setLongitude(Configs.DEFAULT_LOCATION.longitude);
                cityCountryTV.setText(getString(R.string.not_available_text_placeholder));
                queryAds();
            }
        }, 10000); // 10-second timeout
    }
}

@Override
public void onLocationChanged(Location location) {
    // Now, only return if permissions are NOT granted
    if (!PermissionsUtils.hasPermissions(this, locationPermissions)) {
        return;
    }

    // Stop listening for updates since we only need one fix
    if (locationManager != null) {
        locationManager.removeUpdates(this);
    }

    currentLocation = location;
    if (currentLocation != null) {
        getCityCountryNames();
        queryAds(); // Trigger your ad query once location is found
    } else {
        // Fallback to default
        Configs.simpleAlert(getString(R.string.get_location_failure), AdsListActivity.this);
        currentLocation = new Location("provider");
        currentLocation.setLatitude(Configs.DEFAULT_LOCATION.latitude);
        currentLocation.setLongitude(Configs.DEFAULT_LOCATION.longitude);
        cityCountryTV.setText(getString(R.string.not_available_text_placeholder));
        queryAds();
    }
}

// Handle permission request result
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 1001) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Permissions granted—try getting location again
            getCurrentLocation();
        } else {
            // User denied permissions—use default location
            Configs.simpleAlert("Location permissions are required to show local ads", AdsListActivity.this);
            currentLocation = new Location("provider");
            currentLocation.setLatitude(Configs.DEFAULT_LOCATION.latitude);
            currentLocation.setLongitude(Configs.DEFAULT_LOCATION.longitude);
            cityCountryTV.setText(getString(R.string.not_available_text_placeholder));
            queryAds();
        }
    }
}

Key Improvements Made

  1. Fixed the Permission Check: Now onLocationChanged only exits if permissions are missing, so valid location data gets processed.
  2. Added Permission Request Flow: If the user hasn't granted permissions, the app asks for them and retries location fetching once granted.
  3. Single Location Update: Used requestSingleUpdate instead of continuous updates—we only need one location fix, not ongoing tracking.
  4. Timeout Fallback: If no location is found after 10 seconds, the app switches to your default location immediately instead of waiting indefinitely.
  5. Triggered queryAds(): Ensured your ad query runs as soon as a valid location (or default) is set.

Bonus: Use Fused Location Provider (More Reliable for Modern Android)

The old LocationManager works but is less reliable on Android 10+. For better results, use Google's Fused Location Provider. Here's a quick snippet to get you started:

First, add this to your app-level build.gradle dependencies:

implementation 'com.google.android.gms:play-services-location:21.0.1'

Then update your location logic:

private FusedLocationProviderClient fusedLocationClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ... your existing onCreate code
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}

protected void getCurrentLocation() {
    if (!PermissionsUtils.hasPermissions(this, locationPermissions)) {
        ActivityCompat.requestPermissions(this, locationPermissions, 1001);
        return;
    }

    // Get last known location first
    fusedLocationClient.getLastKnownLocation()
            .addOnSuccessListener(this, location -> {
                if (location != null) {
                    currentLocation = location;
                    getCityCountryNames();
                    queryAds();
                } else {
                    // Request a single high-priority location update
                    LocationRequest locationRequest = LocationRequest.create();
                    locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
                    locationRequest.setNumUpdates(1);
                    locationRequest.setInterval(0);
                    locationRequest.setFastestInterval(0);

                    fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());

                    // Timeout fallback
                    new Handler(Looper.getMainLooper()).postDelayed(() -> {
                        if (currentLocation == null) {
                            Configs.simpleAlert(getString(R.string.get_location_failure), AdsListActivity.this);
                            // Set default location
                            currentLocation = new Location("provider");
                            currentLocation.setLatitude(Configs.DEFAULT_LOCATION.latitude);
                            currentLocation.setLongitude(Configs.DEFAULT_LOCATION.longitude);
                            cityCountryTV.setText(getString(R.string.not_available_text_placeholder));
                            queryAds();
                        }
                    }, 10000);
                }
            });
}

private final LocationCallback locationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(LocationResult locationResult) {
        super.onLocationResult(locationResult);
        if (locationResult == null) {
            return;
        }
        for (Location location : locationResult.getLocations()) {
            if (location != null) {
                currentLocation = location;
                getCityCountryNames();
                queryAds();
                fusedLocationClient.removeLocationUpdates(this);
            }
        }
    }
};

Final Notes

  • Add Permissions to AndroidManifest.xml: Make sure you have these lines:
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location.gps" android:required="false" />
    
  • Test with Location Enabled: Ensure the device's location services are turned on (GPS or Wi-Fi-based location).

内容的提问来源于stack exchange,提问作者Edson Francis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:54:37