使用Geocoder获取当前位置地址 开启GPS后出现空指针异常问题
问题根源
- 你在
RESOLUTION_REQUIRED分支调用弹窗请求用户开启GPS后,没有处理用户操作完成后的系统回调,用户同意开启GPS后代码不会自动执行getCurrentLocation方法,仅在GPS原本就处于开启状态时才会调用该方法。 fusedLocationProviderClient.getLastLocation()本身允许返回null:尤其是GPS刚开启的场景下,系统还没有生成最近的定位缓存,此时task.getResult()拿到的Location对象为空,你没有做非空校验就直接调用getLatitude(),就会触发空指针异常。- 额外风险:
Geocoder.getFromLocation也可能返回空列表,直接取下标为0的元素也存在崩溃风险。
修复方案
步骤1:处理GPS开启结果回调
在HomeActivity中重写onActivityResult方法,接收用户对GPS开启弹窗的操作结果,用户确认开启后主动调用getCurrentLocation:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CHECK_SETTINGS) { // 用户确认开启GPS if (resultCode == RESULT_OK) { getCurrentLocation(); } else { // 用户拒绝开启GPS,可做对应提示 Toast.makeText(this, "需要开启GPS才能获取位置", Toast.LENGTH_SHORT).show(); } } }
步骤2:优化getCurrentLocation方法,增加空校验
对Location对象做非空判断,拿不到缓存定位时主动请求一次实时定位,同时增加地址列表的空校验:
@RequiresApi(api = Build.VERSION_CODES.M) private void getCurrentLocation() { if (!checkLocationFinePermission() || !checkLocationCoarsePermission() ) { requestLocationPermission(); return; } // 先尝试拿缓存定位 fusedLocationProviderClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() { @Override public void onComplete(@NonNull Task<Location> task) { Location location = task.getResult(); if (location != null) { // 缓存定位不为空,直接转地址 parseLocationToAddress(location); } else { // 缓存为空,主动请求一次实时定位 fusedLocationProviderClient.getCurrentLocation(LocationRequest.PRIORITY_HIGH_ACCURACY, null) .addOnCompleteListener(new OnCompleteListener<Location>() { @Override public void onComplete(@NonNull Task<Location> task) { Location realTimeLocation = task.getResult(); if (realTimeLocation != null) { parseLocationToAddress(realTimeLocation); } else { Toast.makeText(HomeActivity.this, "获取位置失败,请稍后重试", Toast.LENGTH_SHORT).show(); } } }); } } }); } // 抽离公共的地址转换方法 private void parseLocationToAddress(Location location) { Geocoder geocoder = new Geocoder(HomeActivity.this, Locale.getDefault()); try { List<Address> addresses = geocoder.getFromLocation( location.getLatitude(), location.getLongitude(), 1 ); if (addresses != null && !addresses.isEmpty()) { adresseEditText.setText(addresses.get(0).getAddressLine(0)); } else { adresseEditText.setText("无法解析当前位置地址"); } } catch (IOException e) { e.printStackTrace(); adresseEditText.setText("地址解析失败"); } }
内容的提问来源于stack exchange,提问作者Android dev mrbt
相关产品推荐
相关产品推荐

