水军大提督 发表于 2025-3-26 07:16:59

原生android实现定位java实现

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 == 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. 工具类功能说明


[*] 权限管理:

[*]自动查抄定位权限
[*]动态哀求缺少的权限
[*]处置惩罚权限哀求结果

[*] 位置获取:

[*]支持高精度(GPS)和低精度(网络)定位
[*]获取单次位置更新
[*]获取最后一次已知位置作为快速响应

[*] 错误处置惩罚:

[*]权限被拒绝
[*]位置服务不可用
[*]其他位置获取错误

[*] 资源管理:

[*]提供制止位置更新的方法
[*]制止内存走漏

4. 高级功能扩展

如果须要更高级的功能,可以思量添加以下内容:

[*]超时处置惩罚:
// 添加超时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);
      // ...原有逻辑
    }
};

[*]背景定位支持:
// 在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) {
      // 请求后台权限
    }
}

[*]位置缓存:
// 添加静态变量缓存位置
private static Location lastLocation;
private static long lastLocationTime;

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 原生android实现定位java实现