Android API26下仅用GPS无网络获取经纬度及代码问题排查
Hey there! Let's break down the issues in your code and fix it to meet your requirement of getting location only via GPS (no internet/GPRS) for API 26.
Key Issues in Your Current Code
Unwanted Network Location Logic
YourGPSTrackerstill includes code forNETWORK_PROVIDER(checking network status, requesting network updates, getting network-based last known location). This goes against your "no network" requirement and might prioritize network over GPS.Missing Runtime Permission Handling
API 26 (Android 8.0) falls under the API 23+ range whereACCESS_FINE_LOCATIONis a dangerous permission. You need to request this permission at runtime—your current code skips this, which will cause location requests to fail silently.Incomplete GPS Location Handling
You only fetchgetLastKnownLocation()for GPS, which can benull(e.g., first app launch with no prior GPS fix). Also, youronLocationChanged()method is empty, so you won't receive real-time GPS updates when they become available.Unnecessary Service Inheritance
GPSTrackerextendsService, but you're only using it within an Activity. This adds unnecessary system overhead and redundant lifecycle code that you don't need for foreground GPS requests.
Fixed Code Implementation
1. Updated MainActivity.java (with Permission Handling)
import android.Manifest; import android.content.pm.PackageManager; import android.location.Location; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; public class MainActivity extends AppCompatActivity { private Button GetLocation; private TextView coor; private GPSTracker gps; private static final int REQUEST_LOCATION_PERMISSION = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); GetLocation = findViewById(R.id.GetLocation); coor = findViewById(R.id.text); // Initialize GPS tracker with callback for real-time updates gps = new GPSTracker(MainActivity.this, new GPSTracker.GPSLocationListener() { @Override public void onLocationReceived(Location location) { double latitude = location.getLatitude(); double longitude = location.getLongitude(); coor.append("\n" + latitude + ", " + longitude); } @Override public void onGPSDisabled() { gps.showSettingsAlert(); } }); GetLocation.setOnClickListener(view -> { // Check for location permission first if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION); } else { // Permission granted, start GPS fetch if (gps.canGetLocation()) { Location lastKnownLocation = gps.getLastKnownLocation(); if (lastKnownLocation != null) { double latitude = lastKnownLocation.getLatitude(); double longitude = lastKnownLocation.getLongitude(); coor.append("\n" + latitude + ", " + longitude); } else { coor.append("\nWaiting for GPS fix..."); } gps.startGPSUpdates(); } else { gps.showSettingsAlert(); } } }); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_LOCATION_PERMISSION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Retry location fetch after permission is granted if (gps.canGetLocation()) { Location lastKnownLocation = gps.getLastKnownLocation(); if (lastKnownLocation != null) { double latitude = lastKnownLocation.getLatitude(); double longitude = lastKnownLocation.getLongitude(); coor.append("\n" + latitude + ", " + longitude); } gps.startGPSUpdates(); } else { gps.showSettingsAlert(); } } else { coor.append("\nLocation permission is required to get GPS data"); } } } @Override protected void onDestroy() { super.onDestroy(); // Stop GPS updates to save battery gps.stopUsingGPS(); } }
2. Rewritten GPSTracker.java (GPS-Only Logic)
import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.provider.Settings; import android.app.AlertDialog; import android.content.DialogInterface; public class GPSTracker implements LocationListener { private final Context mContext; private GPSLocationListener gpsCallback; private LocationManager locationManager; private Location lastKnownLocation; private boolean isGPSEnabled; private boolean canGetLocation; // Minimum distance to trigger update (10 meters) private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // Minimum time between updates (30 seconds) private static final long MIN_TIME_BW_UPDATES = 1000 * 30; // Callback to notify Activity of location changes public interface GPSLocationListener { void onLocationReceived(Location location); void onGPSDisabled(); } public GPSTracker(Context context, GPSLocationListener callback) { this.mContext = context; this.gpsCallback = callback; initLocationManager(); } private void initLocationManager() { locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); checkGPSStatus(); } private void checkGPSStatus() { isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); canGetLocation = isGPSEnabled; if (!isGPSEnabled) { gpsCallback.onGPSDisabled(); } } public void startGPSUpdates() { if (isGPSEnabled && locationManager != null) { try { locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); } catch (SecurityException e) { e.printStackTrace(); } } } public Location getLastKnownLocation() { return lastKnownLocation; } public boolean canGetLocation() { return canGetLocation; } public void stopUsingGPS() { if (locationManager != null) { locationManager.removeUpdates(this); } } public void showSettingsAlert() { AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext); alertDialog.setTitle("GPS Settings"); alertDialog.setMessage("GPS is disabled. Do you want to enable it?"); alertDialog.setPositiveButton("Settings", (dialog, which) -> { Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); mContext.startActivity(intent); }); alertDialog.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel()); alertDialog.show(); } @Override public void onLocationChanged(Location location) { // Update last known location and notify Activity lastKnownLocation = location; if (gpsCallback != null) { gpsCallback.onLocationReceived(location); } } @Override public void onProviderDisabled(String provider) { if (provider.equals(LocationManager.GPS_PROVIDER)) { isGPSEnabled = false; canGetLocation = false; gpsCallback.onGPSDisabled(); } } @Override public void onProviderEnabled(String provider) { if (provider.equals(LocationManager.GPS_PROVIDER)) { isGPSEnabled = true; canGetLocation = true; startGPSUpdates(); } } @Override public void onStatusChanged(String provider, int status, Bundle extras) { // Optional: Handle GPS status changes (e.g., out of service) } }
3. Required Permissions in AndroidManifest.xml
Add these lines inside the <manifest> tag:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-feature android:name="android.hardware.location.gps" android:required="true" />
Key Improvements
- GPS-Only Logic: All network provider code is removed, ensuring no internet/GPRS is used.
- Runtime Permissions: Proper handling of
ACCESS_FINE_LOCATIONfor API 23+. - Real-Time Updates:
onLocationChanged()is implemented to receive live GPS fixes. - Battery Optimization: GPS updates are stopped in
onDestroy()to save power. - User Feedback: Clear alerts for disabled GPS and permission denial.
内容的提问来源于stack exchange,提问作者Rameshkumar

