Android Studio获取位置真机失效求助(模拟器正常)
安卓定位真机无法运行的解决方案
1. 补全权限申请的回调处理
当前代码仅在onCreate中发起权限申请,但未处理用户授权后的结果。如果用户拒绝权限,后续点击按钮调用getLocation()时仍会触发权限异常,且无任何提示。
修改步骤:
- 添加权限回调方法,处理用户授权结果:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 100) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限已授予,可正常执行定位 } else { Toast.makeText(this, "需要定位权限才能获取位置信息", Toast.LENGTH_SHORT).show(); } } }
- 在
getLocation()开头再次校验权限,避免无权限时执行定位逻辑:
@SuppressLint("MissingPermission") private void getLocation() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "请先授予定位权限", Toast.LENGTH_SHORT).show(); return; } try { locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,5000,5,MainActivity.this); }catch (Exception e){ e.printStackTrace(); } }
2. 避免仅依赖GPS定位源
真机环境下(尤其是室内)GPS信号可能极弱甚至无信号,仅依赖GPS_PROVIDER会导致无法获取位置。建议同时启用网络定位,或直接使用Google推荐的FusedLocationProviderClient(适配性更强、稳定性更高)。
方案A:同时启用GPS与网络定位
修改getLocation()方法:
@SuppressLint("MissingPermission") private void getLocation() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "请先授予定位权限", Toast.LENGTH_SHORT).show(); return; } try { locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE); // 同时监听GPS和网络定位源 if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,5000,5,this); } if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,5000,5,this); } }catch (Exception e){ e.printStackTrace(); } }
方案B:切换到FusedLocationProviderClient(推荐)
LocationManager是较旧的API,FusedLocationProviderClient整合了多种定位源,适配性更强。
- 在
build.gradle中添加依赖:
implementation 'com.google.android.gms:play-services-location:21.0.1'
- 修改定位实现代码:
private FusedLocationProviderClient fusedLocationClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView_location = findViewById(R.id.text_location); button_location = findViewById(R.id.button_location); fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); // 保留原权限申请逻辑... button_location.setOnClickListener(v -> getLocationWithFused()); } private void getLocationWithFused() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "请先授予定位权限", Toast.LENGTH_SHORT).show(); return; } fusedLocationClient.getLastLocation() .addOnSuccessListener(location -> { if (location != null) { updateLocationUI(location); } else { // 无缓存位置,请求实时更新 LocationRequest locationRequest = LocationRequest.create(); locationRequest.setInterval(5000); locationRequest.setFastestInterval(5000); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()); } }) .addOnFailureListener(e -> { e.printStackTrace(); Toast.makeText(this, "定位失败", Toast.LENGTH_SHORT).show(); }); } private LocationCallback locationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { if (locationResult == null) return; for (Location location : locationResult.getLocations()) { updateLocationUI(location); fusedLocationClient.removeLocationUpdates(this); } } }; private void updateLocationUI(Location location) { Toast.makeText(this, location.getLatitude() + "," + location.getLongitude(), Toast.LENGTH_SHORT).show(); try { Geocoder geocoder = new Geocoder(this, Locale.getDefault()); List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1); if (addresses != null && !addresses.isEmpty()) { String address = addresses.get(0).getAddressLine(0); textView_location.setText(address); } else { textView_location.setText("无法获取地址信息"); } } catch (Exception e) { e.printStackTrace(); textView_location.setText("地址解析失败"); } }
3. 检测并引导用户开启系统位置服务
真机上用户可能未开启系统位置服务,导致定位失败。添加检测逻辑:
private boolean isLocationEnabled() { LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); } // 在getLocation()中调用 if (!isLocationEnabled()) { Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(intent); Toast.makeText(this, "请开启位置服务", Toast.LENGTH_SHORT).show(); return; }
4. 完善Geocoder的空值处理
Geocoder在无网络或部分机型上可能返回null/空列表,直接调用addresses.get(0)会崩溃,需添加判空逻辑(上述FusedLocation方案已包含该处理)。
内容的提问来源于stack exchange,提问作者Sanjith Kumar M
相关产品推荐
相关产品推荐

