原生android实现定位java实现

发布于:2025-03-26 ⋅ 阅读:(16) ⋅ 点赞:(0)

1. 完整的LocationUtils工具类实现

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class LocationUtils {
    private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001;
    private static LocationManager locationManager;
    private static LocationListener locationListener;
    
    // 回调接口
    public interface LocationCallback {
        void onLocationResult(Location location);
        void onPermissionDenied();
        void onLocationError(String error);
    }

    /**
     * 检查并获取当前位置
     * @param activity 当前Activity
     * @param callback 位置回调
     * @param requireFineLocation 是否需要高精度定位
     */
    public static void getCurrentLocation(Activity activity, LocationCallback callback, boolean requireFineLocation) {
        String permission = requireFineLocation ? 
                Manifest.permission.ACCESS_FINE_LOCATION : 
                Manifest.permission.ACCESS_COARSE_LOCATION;
                
        if (checkPermission(activity, permission)) {
            startLocationUpdates(activity, callback, requireFineLocation);
        } else {
            requestLocationPermission(activity, callback, requireFineLocation);
        }
    }

    /**
     * 检查权限是否已授予
     */
    private static boolean checkPermission(Context context, String permission) {
        return ContextCompat.checkSelfPermission(context, permission) 
                == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * 请求定位权限
     */
    private static void requestLocationPermission(Activity activity, 
            final LocationCallback callback, final boolean requireFineLocation) {
        
        String permission = requireFineLocation ? 
                Manifest.permission.ACCESS_FINE_LOCATION : 
                Manifest.permission.ACCESS_COARSE_LOCATION;
                
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
            // 解释为什么需要权限
            callback.onLocationError("需要位置权限才能获取当前位置");
        }
        
        ActivityCompat.requestPermissions(activity, 
                new String[]{permission}, 
                LOCATION_PERMISSION_REQUEST_CODE);
    }

    /**
     * 处理权限请求结果
     * 需要在Activity的onRequestPermissionsResult中调用
     */
    public static void onRequestPermissionsResult(int requestCode, 
            String[] permissions, int[] grantResults, 
            Activity activity, LocationCallback callback, 
            boolean requireFineLocation) {
        
        if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && 
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startLocationUpdates(activity, callback, requireFineLocation);
            } else {
                callback.onPermissionDenied();
            }
        }
    }

    /**
     * 开始获取位置更新
     */
    private static void startLocationUpdates(Activity activity, 
            final LocationCallback callback, boolean requireFineLocation) {
        
        locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
        
        if (locationManager == null) {
            callback.onLocationError("无法获取位置服务");
            return;
        }

        // 检查GPS和网络是否可用
        boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        
        if (!isGpsEnabled && !isNetworkEnabled) {
            callback.onLocationError("请打开位置服务");
            return;
        }

        String provider = requireFineLocation ? 
                LocationManager.GPS_PROVIDER : 
                LocationManager.NETWORK_PROVIDER;

        locationListener = new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                // 获取到位置后停止更新并返回结果
                stopLocationUpdates();
                callback.onLocationResult(location);
            }

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

            @Override
            public void onProviderEnabled(String provider) {}

            @Override
            public void onProviderDisabled(String provider) {
                callback.onLocationError("位置服务被禁用");
            }
        };

        try {
            if (ActivityCompat.checkSelfPermission(activity, 
                    requireFineLocation ? 
                            Manifest.permission.ACCESS_FINE_LOCATION : 
                            Manifest.permission.ACCESS_COARSE_LOCATION) 
                    != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            
            // 请求位置更新
            locationManager.requestSingleUpdate(provider, locationListener, Looper.getMainLooper());
            
            // 同时获取最后一次已知位置
            Location lastKnownLocation = locationManager.getLastKnownLocation(provider);
            if (lastKnownLocation != null) {
                callback.onLocationResult(lastKnownLocation);
            }
            
        } catch (SecurityException e) {
            callback.onLocationError("位置权限异常: " + e.getMessage());
        } catch (IllegalArgumentException e) {
            callback.onLocationError("位置提供者不可用: " + e.getMessage());
        }
    }

    /**
     * 停止位置更新
     */
    public static void stopLocationUpdates() {
        if (locationManager != null && locationListener != null) {
            locationManager.removeUpdates(locationListener);
        }
    }
}

2. 使用示例

在Activity中使用

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Button btnGetLocation = findViewById(R.id.btn_get_location);
        btnGetLocation.setOnClickListener(v -> {
            // 获取高精度位置
            LocationUtils.getCurrentLocation(this, new LocationUtils.LocationCallback() {
                @Override
                public void onLocationResult(Location location) {
                    double latitude = location.getLatitude();
                    double longitude = location.getLongitude();
                    // 处理位置信息
                    Log.d("Location", "Lat: " + latitude + ", Lng: " + longitude);
                }

                @Override
                public void onPermissionDenied() {
                    // 处理权限被拒绝
                    Toast.makeText(MainActivity.this, 
                            "需要位置权限才能使用此功能", 
                            Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onLocationError(String error) {
                    // 处理位置错误
                    Toast.makeText(MainActivity.this, error, Toast.LENGTH_SHORT).show();
                }
            }, true); // true表示需要高精度定位
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, 
            @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // 将权限结果转发给工具类处理
        LocationUtils.onRequestPermissionsResult(
                requestCode, permissions, grantResults, 
                this, new LocationUtils.LocationCallback() {
                    @Override
                    public void onLocationResult(Location location) {
                        // 处理位置信息
                    }

                    @Override
                    public void onPermissionDenied() {
                        // 处理权限被拒绝
                    }

                    @Override
                    public void onLocationError(String error) {
                        // 处理错误
                    }
                }, true);
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 停止位置更新
        LocationUtils.stopLocationUpdates();
    }
}

3. 工具类功能说明

  1. 权限管理

    • 自动检查定位权限
    • 动态请求缺少的权限
    • 处理权限请求结果
  2. 位置获取

    • 支持高精度(GPS)和低精度(网络)定位
    • 获取单次位置更新
    • 获取最后一次已知位置作为快速响应
  3. 错误处理

    • 权限被拒绝
    • 位置服务不可用
    • 其他位置获取错误
  4. 资源管理

    • 提供停止位置更新的方法
    • 避免内存泄漏

4. 高级功能扩展

如果需要更高级的功能,可以考虑添加以下内容:

  1. 超时处理
// 添加超时Handler
private static final int LOCATION_TIMEOUT_MS = 30000; // 30秒超时
private static Handler timeoutHandler = new Handler();

private static void startLocationUpdatesWithTimeout(...) {
    // 设置超时任务
    timeoutHandler.postDelayed(() -> {
        stopLocationUpdates();
        callback.onLocationError("获取位置超时");
    }, LOCATION_TIMEOUT_MS);
    
    startLocationUpdates(...);
}

// 在获取到位置后取消超时任务
locationListener = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
        timeoutHandler.removeCallbacksAndMessages(null);
        // ...原有逻辑
    }
};
  1. 后台定位支持
// 在AndroidManifest.xml中添加
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

// 在工具类中检查Android 10+的后台权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    if (ContextCompat.checkSelfPermission(context, 
            Manifest.permission.ACCESS_BACKGROUND_LOCATION) 
            != PackageManager.PERMISSION_GRANTED) {
        // 请求后台权限
    }
}
  1. 位置缓存
// 添加静态变量缓存位置
private static Location lastLocation;
private static long lastLocationTime;

public static Location getCachedLocation() {
    // 如果缓存的位置在有效期内(如5分钟内)则返回
    if (lastLocation != null && 
            System.currentTimeMillis() - lastLocationTime < 300000) {
        return lastLocation;
    }
    return null;
}