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
相关产品推荐
相关产品推荐

