Android 9设备GPS坐标返回0与INSTALL_LOCATION_PROVIDER权限异常排查
解决Android 9设备获取GPS坐标失败及SecurityException异常问题
问题分析
你的应用在Android 9设备上抛出java.lang.SecurityException: need INSTALL_LOCATION_PROVIDER permission异常并返回0值坐标,核心原因并非需要系统级的INSTALL_LOCATION_PROVIDER权限(该权限仅系统应用可获取),而是缺少必要的位置权限检查与申请逻辑,加上@SuppressLint("MissingPermission")跳过了编译期检查,导致运行时权限校验失败,触发异常。
解决方案
1. 声明Manifest权限
首先在AndroidManifest.xml中添加必要的位置权限:
<!-- 用于精确GPS定位 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 用于网络定位 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 若需后台定位(Android 10+),添加此权限 --> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:maxSdkVersion="33" />
2. 添加权限检查逻辑
移除或慎用@SuppressLint("MissingPermission"),在获取位置前先检查权限是否已授予:
private boolean hasLocationPermissions() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED; } // Android 6.0以下权限在安装时自动授予 return true; }
3. 修改getLocation方法
在getLocation()开头加入权限校验,避免无权限时调用位置API:
public Location getLocation() { // 先检查权限 if (!hasLocationPermissions()) { Log.e("LocationError", "位置权限未授予"); return null; } try { locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE); isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); if (!isGPSEnabled && !isNetworkEnabled) { Log.e("LocationError", "GPS与网络定位均未开启"); return null; } else { this.canGetLocation = true; Location tempLocation = null; if (isNetworkEnabled) { locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); Log.d("Network", "已开启网络定位"); tempLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); } if (isGPSEnabled && tempLocation == null) { locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this); Log.d("GPS Enabled", "已开启GPS定位"); tempLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); } if (tempLocation != null) { latitude = tempLocation.getLatitude(); longitude = tempLocation.getLongitude(); return tempLocation; } } } catch (Exception e) { e.printStackTrace(); } return null; }
4. 动态申请权限
在调用getLocation()的Activity/Fragment中,主动请求位置权限:
private static final int REQUEST_LOCATION_PERM = 1001; // 示例:在Activity中触发位置获取 private void requestLocation() { if (!hasLocationPermissions()) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION_PERM); } else { Location location = getLocation(); handleLocationResult(location); } } // 处理权限申请结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_LOCATION_PERM) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限授予成功,重新获取位置 Location location = getLocation(); handleLocationResult(location); } else { // 权限被拒绝,提示用户开启权限 Toast.makeText(this, "需开启位置权限才能获取坐标", Toast.LENGTH_SHORT).show(); } } } private void handleLocationResult(Location location) { if (location != null) { // 处理有效坐标 double lat = location.getLatitude(); double lng = location.getLongitude(); Log.d("LocationSuccess", "纬度:" + lat + ",经度:" + lng); } else { // 无可用位置,提示用户检查定位设置 Toast.makeText(this, "无法获取位置,请检查GPS/网络定位是否开启", Toast.LENGTH_SHORT).show(); } }
额外注意事项
getLastKnownLocation可能返回null(设备从未定位过或长时间未更新),需依赖LocationListener的onLocationChanged回调获取实时位置。- Android 9(API 28)开始限制后台位置访问,若需后台获取位置,需额外申请
ACCESS_BACKGROUND_LOCATION权限并向用户说明用途。
内容的提问来源于stack exchange,提问作者Moeez
相关产品推荐
相关产品推荐

