You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 16:40:22