使用FusedLocationApi时onLocationChanged()未触发的技术求助
我帮你排查了代码里的几个关键问题,这应该就是导致onLocationChanged()没被调用的核心原因,一步步来修正:
1. onConnected方法中的权限判断逻辑错误
这是最直接的问题!你在onConnected()里的权限判断条件写反了,导致永远无法触发位置更新请求:
// 你原来的错误代码 if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
这里用&&要求同时满足FINE权限已授予,且COARSE权限未授予,但你的Manifest里同时申请了两个权限,用户通常会一起授予,这就导致这个条件永远不成立,自然不会调用requestLocationUpdates()。
修正方案
改成只要有一个位置权限(FINE或COARSE)被授予即可,或者直接检查FINE权限(因为FINE权限包含了COARSE的功能):
// 修正后的权限判断 if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { LocationServices.FusedLocationApi.requestLocationUpdates(mgooogleapiclient, mlocationRequest, this); }
2. onRequestPermissionsResult中的潜在问题
在权限申请通过后,你直接调用了requestLocationUpdates(),但此时mlocationRequest还未初始化(它是在onConnected()里创建的),而且mgooogleapiclient刚调用buildGoogleApiClient(),可能还没完成连接,这会导致请求失败。
修正方案
把位置更新的请求逻辑完全交给onConnected()处理,权限通过后只需要确保GoogleApiClient连接并启用地图的MyLocation功能:
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_LOCATION: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (mgooogleapiclient == null) { buildGoogleApiClient(); } mMap.setMyLocationEnabled(true); // 移除这里的requestLocationUpdates调用,交给onConnected处理 } } else { Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show(); } return; } } }
3. 优化位置请求的优先级与设备设置
你当前使用的PRIORITY_BALANCED_POWER_ACCURACY优先级,在Nougat设备上可能因为功耗优化,在静止状态下不会频繁更新位置。如果需要每秒获取一次位置,建议改成高精确度优先级(注意会增加功耗):
mlocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
同时确保测试设备的:
- 位置服务已开启
- 位置模式设置为「高精确度」(允许使用GPS、WLAN和移动网络)
额外优化:位置更新的生命周期管理
在onStop()中移除位置更新是对的,但如果应用只是暂时退到后台(比如按Home键),可以在onPause()中移除,onResume()中重新注册,避免不必要的位置追踪:
@Override protected void onPause() { super.onPause(); if (mgooogleapiclient != null && mgooogleapiclient.isConnected()) { LocationServices.FusedLocationApi.removeLocationUpdates(mgooogleapiclient, this); } } @Override protected void onResume() { super.onResume(); if (mgooogleapiclient != null && mgooogleapiclient.isConnected()) { if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { LocationServices.FusedLocationApi.requestLocationUpdates(mgooogleapiclient, mlocationRequest, this); } } }
附:你的原始配置文件(供参考)
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" /> <activity android:name=".DriverMapActivity" android:label="@string/title_activity_driver_map"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion 26 defaultConfig { applicationId "com.example.user.vypodriver" minSdkVersion 17 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.google.android.gms:play-services-maps:11.0.4' implementation 'com.google.firebase:firebase-database:11.0.4' testImplementation 'junit:junit:4.12' implementation 'com.google.android.gms:play-services-location:11.0.4' compile 'com.firebase:geofire-android:2.2.0' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' } apply plugin: 'com.google.gms.google-services'
内容的提问来源于stack exchange,提问作者Jennifer26

