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

Android礼拜时间表应用经纬度获取故障排查求助

解决礼拜时间表应用的定位权限与经纬度获取问题

嘿,我帮你仔细排查了这款礼拜时间表应用的定位问题,发现了几个关键的错误点,咱们一步步来修复:

一、先把MainActivity的权限请求逻辑掰正

你原来的代码里有两个明显的问题:一是分开两次调用requestPermissions,会弹出两次权限弹窗,体验极差;二是Activity类名混用(UtamaActivity和MainActivity),还有权限判断的逻辑可以优化。修改后的代码如下:

@Override
public void onClick(View view) {
    // 只要有一个定位权限没授予,就触发请求
    if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            || ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // 一次性请求两个权限,用同一个requestCode
        ActivityCompat.requestPermissions(MainActivity.this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                44);
    } else {
        Intent jadwalSholat = new Intent(MainActivity.this, TimePrayActivity.class);
        startActivity(jadwalSholat);
    }
}

二、别只弹Toast,引导用户直接开GPS

原来的代码只提示用户开GPS,但没给跳转入口,用户得自己找设置,太麻烦了。咱们给checkState方法加个跳转逻辑,让用户一键进入GPS设置页面:

private void checkState(){
    final LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    ConnectivityManager manager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = manager.getActiveNetworkInfo();

    if (networkInfo != null){
        if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI || networkInfo.getType() == ConnectivityManager.TYPE_MOBILE){
            if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
                Toast.makeText(this, "请开启GPS以获取准确的礼拜时间!", Toast.LENGTH_SHORT).show();
                // 跳转至系统GPS设置页面
                Intent gpsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivityForResult(gpsIntent, ACCESS_LOCATION);
            } else {
                getLocation();
            }
        }
    } else {
        Toast.makeText(this, "无网络连接,请检查网络!", Toast.LENGTH_SHORT).show();
    }
}

// 监听用户从设置页面返回的操作,重新检查GPS状态
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == ACCESS_LOCATION) {
        checkState();
    }
}

三、解决getLastLocation返回null的核心问题

你用的getLastLocation()非常不靠谱——如果设备之前没缓存过位置,它直接返回null!咱们换成主动请求实时位置的方式,同时保留getLastLocation作为回退方案:

private void getLocation(){
    // 先检查权限,没权限就主动请求
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                ACCESS_LOCATION);
        return;
    }

    progressBar.setVisibility(View.VISIBLE);

    // 创建位置请求,设置高精度优先级
    LocationRequest locationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(10000)
            .setFastestInterval(5000);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        // Android 12+用getCurrentLocation获取实时位置
        providerClient.getCurrentLocation(locationRequest, null)
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful() && task.getResult() != null) {
                        handleLocationData(task.getResult());
                    } else {
                        // 获取失败就回退到getLastLocation
                        fallbackToLastLocation();
                    }
                });
    } else {
        // 低版本用requestLocationUpdates监听位置变化
        providerClient.requestLocationUpdates(locationRequest, new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                if (locationResult != null && !locationResult.getLocations().isEmpty()) {
                    Location location = locationResult.getLocations().get(0);
                    handleLocationData(location);
                    // 拿到位置后停止更新,节省电量
                    providerClient.removeLocationUpdates(this);
                } else {
                    fallbackToLastLocation();
                }
            }
        }, Looper.getMainLooper());
    }
}

// 统一处理获取到的位置数据
private void handleLocationData(Location location) {
    Geocoder geocoder = new Geocoder(JadwalSholatActivity.this, Locale.getDefault());
    try {
        List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
        if (!addresses.isEmpty()) {
            latitude = addresses.get(0).getLatitude();
            longitude = addresses.get(0).getLongitude();
            jadwalSholat();
        } else {
            Toast.makeText(this, "无法解析当前位置", Toast.LENGTH_SHORT).show();
            progressBar.setVisibility(View.GONE);
        }
    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(this, "位置解析失败,请重试", Toast.LENGTH_SHORT).show();
        progressBar.setVisibility(View.GONE);
    }
}

// 回退方案:尝试获取缓存的位置
private void fallbackToLastLocation() {
    providerClient.getLastLocation()
            .addOnCompleteListener(task -> {
                progressBar.setVisibility(View.GONE);
                if (task.isSuccessful() && task.getResult() != null) {
                    handleLocationData(task.getResult());
                } else {
                    Toast.makeText(JadwalSholatActivity.this, "无法获取位置,请检查GPS和网络是否正常", Toast.LENGTH_SHORT).show();
                }
            });
}

// 处理权限请求的结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == ACCESS_LOCATION) {
        boolean allPermissionsGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allPermissionsGranted = false;
                break;
            }
        }
        if (allPermissionsGranted) {
            getLocation();
        } else {
            Toast.makeText(this, "需要定位权限才能获取准确的礼拜时间", Toast.LENGTH_SHORT).show();
        }
    }
}

四、最后别忘了这些细节

  • 如果你适配的是Android 12及以上版本,记得在AndroidManifest.xml里添加前台服务权限:<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />(如果需要后台定位的话),还有<uses-feature android:name="android.hardware.location.gps" />来声明应用依赖GPS硬件。
  • 提醒用户把设备的定位模式设置为高精度,仅用网络定位可能导致位置不准确或者获取失败。

内容的提问来源于stack exchange,提问作者bbqapps

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:52:30