解决 Android 10 获取不到定位信息的问题

1. 前言

最近国内很多手机厂商都推送基于 Android 10 开发的自家系统了。之前其实已经对公司的APP进行适配了,但还是发现了新坑。那就是定位的问题。已经申请了定位权限,但是依旧无法进行定位。我用的是高德的定位,项目工程的 targetSdkVersion 为26。经过不断尝试,最后才发现,竟然要开启手机的定位服务,才能获取到定位信息。

2. 解决方案

方案的流程图如下所示:

如何申请定位权限,这里不展开讲。高德定位是怎么使用的,这里也不展开讲,想了解的直接去高德开放平台看就是了,文档写得很详细的。“判断是否已开启定位服务”和“如何跳转到系统的定位服务页面”,这两块接下来展开讲一讲。

2.1 判断手机定位服务是否开启

/**
  * 判断定位服务是否开启
  *
  * @param context 上下文
  * @return true:开启;false:未开启
  */
public static boolean isLocationEnabled(Context context) {
    int locationMode = 0;
    String locationProviders;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        try {
            locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
            return false;
        }
        return locationMode != Settings.Secure.LOCATION_MODE_OFF;
    } else {
        locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
        return !TextUtils.isEmpty(locationProviders);
    }
}

2.2 跳转到系统的定位服务页面

// 通用版
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));

// 回调版,这个可以在 onActivityResult 里判断是否成功开启定位服务
startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS),
                            REQUEST_CODE_LOCATION);

<think>在Android 10(API级别29)以下,获取定位信息主要使用LocationManager和LocationListener。需要注意的是,从Android 6.0(API级别23)开始,需要在运行时请求权限。 步骤: 1.AndroidManifest.xml中添加权限(如果同时需要粗略和精确定位,则两个都加,但注意在Android 10以下,精确定位权限会同时允许粗略定位): <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 2. 在代码中检查权限,如果没有则请求权限。 3. 使用LocationManager获取位置信息,并注册LocationListener监听位置更新。 注意:由于Android版本不同,这里我们针对Android 10以下(即API<29)的设备,所以不需要后台定位权限(ACCESS_BACKGROUND_LOCATION)的特别处理(该权限是Android 10引入的)。 以下是一个示例代码,展示如何在Activity中获取定位信息(使用LocationManager):</think>### Android 10以下获取定位信息的Java实现 在Android 10(API 29)以下获取定位信息,主要使用`LocationManager`和`LocationListener`。以下是详细实现步骤: #### 1. 添加权限(AndroidManifest.xml) ```xml <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> ``` #### 2. 检查并请求运行时权限(Android 6.0+) ```java // 在Activity中 private static final int LOCATION_PERMISSION_REQUEST_CODE = 100; private void checkLocationPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE); } else { startLocationUpdates(); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { startLocationUpdates(); } else { Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show(); } } } ``` #### 3. 获取位置信息核心代码 ```java private LocationManager locationManager; private LocationListener locationListener; private void startLocationUpdates() { locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); locationListener = new LocationListener() { @Override public void onLocationChanged(Location location) { // 获取到新位置时触发 double latitude = location.getLatitude(); double longitude = location.getLongitude(); Log.d("Location", "Lat: " + latitude + ", Lng: " + longitude); } @Override public void onStatusChanged(String provider, int status, Bundle extras) {} @Override public void onProviderEnabled(String provider) {} @Override public void onProviderDisabled(String provider) {} }; try { // 优先使用GPS,其次网络定位 if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 5000, // 更新间隔:5秒 10, // 最小位移:10locationListener); } else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 5000, 10, locationListener); } else { Toast.makeText(this, "No location provider available", Toast.LENGTH_SHORT).show(); } } catch (SecurityException e) { e.printStackTrace(); } } // 在Activity销毁时移除监听 @Override protected void onDestroy() { super.onDestroy(); if (locationManager != null && locationListener != null) { locationManager.removeUpdates(locationListener); } } ``` ### 代码解释: 1. **权限处理**: - `ACCESS_FINE_LOCATION`:用于GPS定位 - `ACCESS_COARSE_LOCATION`:用于基站/WiFi定位 - Android 6.0+需要动态请求权限 2. **LocationManager核心方法**: - `requestLocationUpdates()`:注册位置监听 - 参数说明:定位源(GPS/网络)、最小时间间隔、最小位移距离、监听器 3. **定位策略**: - 优先使用GPS(精度高但耗电) - 备选网络定位(精度低但响应快) - 通过`isProviderEnabled()`检查可用性 4. **资源释放**: - 在`onDestroy()`中移除监听,避免内存泄漏 ### 注意事项: 1. **设备兼容性检查**: ```java // 检查设备是否支持定位服务 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION)) { Toast.makeText(this, "Device doesn't support location", Toast.LENGTH_SHORT).show(); } ``` 2. **定位超时处理**: 添加备用方案获取最后已知位置: ```java Location lastKnownLocation = null; try { lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (lastKnownLocation == null) { lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); } } catch (SecurityException ignored) {} ``` 3. **Android版本适配**: - 代码兼容Android 5.0+(API 21) - 对于Android 9.0(API 28)及以下,此方法完全适用 ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值