Android设备经纬度获取求助:已编写LocationListener及基站定位代码
解决Android设备获取经纬度的问题
首先得明确:你当前用的http://www.google.com/glm/mmap接口早就被Google废弃了,这就是这个基站定位方案完全无效的核心原因。别再死磕这个旧接口了,咱们改用Android官方推荐的现代定位方案,结合你已经写好的LocationListener来实现,步骤如下:
一、迁移到Fused Location Provider(官方推荐)
Fused Location Provider是Google Play Services提供的定位库,它会自动整合GPS、基站、WiFi等多种定位源,精度和稳定性都远胜旧方案,也是现在Android开发的标准做法。
1. 添加依赖
在你的app模块的build.gradle(注意是Module级别的,不是Project级)里添加定位库依赖:
dependencies { implementation 'com.google.android.gms:play-services-location:21.0.1' }
2. 处理运行时权限
从Android 6.0(API 23)开始,ACCESS_FINE_LOCATION这类定位权限属于危险权限,必须在运行时主动申请,只在Manifest里声明是没用的。在MainActivity里加上权限申请逻辑:
private static final int REQUEST_LOCATION_PERMISSION = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 记得绑定你的布局文件 // 先检查定位权限是否已获取 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // 权限未获取,发起申请 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION); } else { // 权限已就绪,开始获取定位 startLocationUpdates(); } } // 处理权限申请的回调结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_LOCATION_PERMISSION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { startLocationUpdates(); } else { Toast.makeText(this, "需要授予定位权限才能获取位置信息", Toast.LENGTH_SHORT).show(); } } }
3. 整合你的LocationListener实现定位更新
把你写的LocationListener和Fused Location Provider结合起来,实现真正的定位逻辑:
private FusedLocationProviderClient mFusedLocationClient; private LocationRequest mLocationRequest; // 保留你原来的LocationListener,补充逻辑 private final LocationListener mLocationListener = new LocationListener() { @Override public void onLocationChanged(final Location location) { // 在这里拿到精准的经纬度(double类型,保留小数精度) double latitude = location.getLatitude(); double longitude = location.getLongitude(); Log.e(TAG, "当前纬度:" + latitude + ",当前经度:" + longitude); // 如果只需要一次定位结果,拿到后可以停止更新 mFusedLocationClient.removeLocationUpdates(mLocationListener); } @Override public void onStatusChanged(String s, int i, Bundle bundle) {} @Override public void onProviderEnabled(String s) {} @Override public void onProviderDisabled(String s) {} }; private void startLocationUpdates() { mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); // 配置定位请求参数 mLocationRequest = LocationRequest.create(); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // 高精度模式(优先GPS) mLocationRequest.setInterval(5000); // 定位更新间隔(毫秒) mLocationRequest.setFastestInterval(2000); // 最快更新间隔(应对紧急情况) // 检查设备定位设置是否符合要求 LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() .addLocationRequest(mLocationRequest); SettingsClient client = LocationServices.getSettingsClient(this); Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build()); task.addOnSuccessListener(this, locationSettingsResponse -> { // 定位设置正常,开始请求位置更新 try { mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationListener, Looper.getMainLooper()); } catch (SecurityException e) { e.printStackTrace(); } }); task.addOnFailureListener(this, e -> { if (e instanceof ResolvableApiException) { // 定位设置未开启,引导用户跳转到系统设置打开 try { ResolvableApiException resolvable = (ResolvableApiException) e; resolvable.startResolutionForResult(MainActivity.this, 101); } catch (IntentSender.SendIntentException sendEx) { sendEx.printStackTrace(); } } else { Toast.makeText(this, "无法获取定位,请检查系统定位设置", Toast.LENGTH_SHORT).show(); } }); } // 处理定位设置跳转的结果 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 101) { if (resultCode == RESULT_OK) { startLocationUpdates(); } else { Toast.makeText(this, "未开启定位设置,无法获取位置", Toast.LENGTH_SHORT).show(); } } }
二、你原有代码的其他明显问题
就算暂时不想用官方方案,你原来的代码还有两个致命问题:
myLatitude和myLongitude定义成了int类型,但经纬度是带小数的数值(比如39.9042),用int会直接丢失精度,必须改成double类型。- 旧的Google mmap接口已经彻底失效,没有任何办法再通过它获取基站定位数据,必须放弃。
三、Manifest配置补充
除了你已经添加的权限,还可以加上定位特性声明(可选,但能帮助Google Play过滤不支持定位的设备):
<uses-feature android:name="android.hardware.location.gps" android:required="false" /> <uses-feature android:name="android.hardware.location.network" android:required="false" />
最后提醒:测试定位功能一定要用真机,模拟器的定位数据要么不准确,要么根本无法获取。
内容的提问来源于stack exchange,提问作者user9240225
相关产品推荐
相关产品推荐

