Android 高版本兼容的原生定位工具类封装(支持 Android 5.0 到 Android 14)
本文提供了一个完整的 Android 原生定位工具类封装,支持从 Android 5.0 到最新的 Android 14 版本。该工具类基于 LocationManager,实现了定位权限检查、定位开关检测、实时位置更新监听以及获取最后一次已知位置的功能。针对高版本 Android 系统的权限变化和后台定位限制,工具类进行了适配优化,确保在不同系统版本上都能稳定运行。代码简洁易用,可直接集成到项目中,适合需要定位功能的 Android 应用开发者。
完整代码
1. 工具类:NativeLocationHelper.java
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.provider.Settings;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class NativeLocationHelper {
private Context context;
private LocationManager locationManager;
private LocationListener locationListener;
private OnLocationUpdateListener onLocationUpdateListener;
// 定位更新回调接口
public interface OnLocationUpdateListener {
void onLocationUpdate(Location location); // 位置更新回调
void onLocationError(String errorMessage); // 定位失败回调
}
public NativeLocationHelper(Context context) {
this.context = context;
this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
}
/**
* 开始定位
*
* @param minTime 最小更新时间(毫秒)
* @param minDistance 最小更新距离(米)
* @param listener 定位更新回调
*/
public void startLocationUpdates(long minTime, float minDistance, OnLocationUpdateListener listener) {
this.onLocationUpdateListener = listener;
// 检查定位权限
if (!checkLocationPermission()) {
onLocationUpdateListener.onLocationError("Location permission not granted");
return;
}
// 检查定位是否开启
if (!isLocationEnabled()) {
onLocationUpdateListener.onLocationError("Location services are disabled");
return;
}
// 创建定位监听器
locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
if (onLocationUpdateListener != null) {
onLocationUpdateListener.onLocationUpdate(location);
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onProviderDisabled(String provider) {
if (onLocationUpdateListener != null) {
onLocationUpdateListener.onLocationError("Location provider disabled");
}
}
};
// 请求位置更新
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTime, minDistance, locationListener, Looper.getMainLooper());
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, minTime, minDistance, locationListener, Looper.getMainLooper());
}
}
/**
* 停止定位
*/
public void stopLocationUpdates() {
if (locationManager != null && locationListener != null) {
locationManager.removeUpdates(locationListener);
}
}
/**
* 获取最后一次已知位置
*
* @return 最后一次已知位置,如果不存在则返回 null
*/
public Location getLastKnownLocation() {
if (!checkLocationPermission() || !isLocationEnabled()) {
return null;
}
Location lastKnownLocation = null;
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKnownLocation == null) {
lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
}
return lastKnownLocation;
}
/**
* 检查定位服务是否开启
*
* @return true 表示定位服务已开启,false 表示未开启
*/
public boolean isLocationEnabled() {
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|| locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
/**
* 检查定位权限
*
* @return true 表示权限已授予,false 表示未授予
*/
private boolean checkLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED;
} else {
return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
}
/**
* 打开定位设置页面
*/
public void openLocationSettings() {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startActivity(intent);
}
}
2. 在 AndroidManifest.xml 中添加权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
3. 前台服务声明(适用于 Android 14)
如果需要在后台获取位置更新,可以使用前台服务,并在 AndroidManifest.xml 中声明服务类型:
<service
android:name=".LocationForegroundService"
android:foregroundServiceType="location" />
4. 在 Activity 中使用工具类
import android.location.Location;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.pm.PackageManager;
import android.util.Log;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001;
private NativeLocationHelper locationHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化定位工具类
locationHelper = new NativeLocationHelper(this);
// 检查并请求定位权限
if (checkLocationPermission()) {
startLocationUpdates();
} else {
requestLocationPermission();
}
}
/**
* 检查定位权限
*/
private boolean checkLocationPermission() {
return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
/**
* 请求定位权限
*/
private void requestLocationPermission() {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE
);
}
/**
* 开始定位更新
*/
private void startLocationUpdates() {
locationHelper.startLocationUpdates(10000, 10, new NativeLocationHelper.OnLocationUpdateListener() {
@Override
public void onLocationUpdate(Location location) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
Log.d("Location", "Lat: " + latitude + ", Lng: " + longitude);
Toast.makeText(MainActivity.this, "Location: " + latitude + ", " + longitude, Toast.LENGTH_SHORT).show();
}
@Override
public void onLocationError(String errorMessage) {
Log.e("Location", errorMessage);
Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_SHORT).show();
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// 停止定位更新
locationHelper.stopLocationUpdates();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startLocationUpdates();
} else {
Toast.makeText(this, "Location permission denied", Toast.LENGTH_SHORT).show();
}
}
}
}
总结
该工具类已适配到最高 Android 14,支持最新的权限管理和定位功能。
针对 Android 14 的隐私和安全增强,工具类增加了对前台服务和权限请求的适配。
如果你有更多需求或问题,欢迎继续提问!