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

addOnCompleteListener未做权限检查致应用崩溃,定位代码求助

修复定位权限检查问题,避免应用崩溃

我来帮你排查并解决这个权限相关的崩溃问题。核心问题是你的代码里权限检查不完整,而且没有处理权限未授予时的分支逻辑,直接去调用FusedLocationClient的API,导致触发SecurityException进而崩溃。下面是完整的修复方案:

第一步:完善权限检查与请求逻辑

先把getDeviceLocation()方法补全,确保只有在权限通过后才执行定位操作,未授权时主动请求权限:

private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001;
private FusedLocationProviderClient mFusedLocationClient;
private static final String TAG = "LocationHelper";

// 应用启动时,使用此方法将我的位置设为默认中心位置
private void getDeviceLocation() {
    Log.d(TAG, "getDeviceLocation: getting the devices current location");
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

    // 完整的权限检查:确认至少有一个定位权限被授予
    boolean hasFineLocation = ActivityCompat.checkSelfPermission(this, 
            Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
    boolean hasCoarseLocation = ActivityCompat.checkSelfPermission(this, 
            Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;

    if (hasFineLocation || hasCoarseLocation) {
        // 权限已授予,执行定位逻辑
        try {
            mFusedLocationClient.getLastLocation()
                    .addOnCompleteListener(this, task -> {
                        if (task.isSuccessful() && task.getResult() != null) {
                            Location currentLocation = task.getResult();
                            // 这里处理获取到的位置,比如设置地图中心
                            Log.d(TAG, "当前位置:" + currentLocation.getLatitude() + ", " + currentLocation.getLongitude());
                            // TODO: 你的业务逻辑,比如 map.moveCamera(CameraUpdateFactory.newLatLngZoom(...))
                        } else {
                            Log.e(TAG, "getDeviceLocation: 无法获取位置,结果为空或任务失败");
                            // 可以在这里处理位置获取失败的情况,比如显示默认位置
                        }
                    });
        } catch (SecurityException e) {
            Log.e(TAG, "getDeviceLocation: 安全异常 - " + e.getMessage());
        }
    } else {
        // 权限未授予,请求定位权限
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                LOCATION_PERMISSION_REQUEST_CODE);
    }
}

第二步:处理权限请求结果

重写onRequestPermissionsResult方法,在用户授权后重新触发定位逻辑:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
        // 检查是否有至少一个权限被授予
        boolean hasFine = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
        boolean hasCoarse = grantResults.length > 1 && grantResults[1] == PackageManager.PERMISSION_GRANTED;
        if (hasFine || hasCoarse) {
            // 用户授权,重新获取位置
            getDeviceLocation();
        } else {
            Log.w(TAG, "用户拒绝了定位权限,无法获取当前位置");
            // 这里可以提示用户开启权限,或者使用默认位置
        }
    }
}

第三步:确保Manifest中声明权限

别忘了在AndroidManifest.xml里添加必要的权限声明:

<!-- 定位权限声明 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

<!-- 如果是Android 12及以上,还需要添加ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION对应的后台权限(如果需要后台定位) -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:maxSdkVersion="32"/>

关键修复点说明

  • 完整的权限检查:确保覆盖了ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION两种权限,只要有一个授权就可以执行定位。
  • 权限未授权分支:不再直接执行定位API,而是主动请求权限,避免触发SecurityException。
  • 异常捕获:即使权限检查通过,也添加了try-catch捕获可能的安全异常(比如权限被用户中途撤销的情况)。
  • 空结果处理:在addOnCompleteListener里处理了位置结果为空的情况,避免空指针崩溃。

这样修改后,你的应用就不会因为权限问题而崩溃了,同时也能正确处理用户授权或拒绝权限的场景。

内容的提问来源于stack exchange,提问作者Henrik Granström

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:51:25