类Pokemon Go安卓App模拟器定位正常 真机无法显示位置问题求助
问题原因及解决方案
核心问题1:定位Provider单一,室内环境无法获取位置
你当前代码仅注册了GPS_PROVIDER的位置监听,GPS仅在室外开阔环境能正常搜星返回位置,真机在室内测试时无法获取位置,导致currentLocation长期停留在初始值(0.0, 0.0),相机直接移动到大西洋海域,看起来就像没有显示用户位置。
解决方案:
- 新增网络定位Provider监听,同时注册
LocationManager.NETWORK_PROVIDER的位置更新回调 - 优先使用谷歌融合定位服务(FusedLocationProvider),比原生LocationManager兼容性、稳定性高很多
// 修改getLocation方法,同时注册两个Provider fun getLocation() { var myLocation=MyLocation() var locationManager=getSystemService(Context.LOCATION_SERVICE) as LocationManager // 先判断定位服务是否开启 if(!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { Toast.makeText(this, "请先开启定位服务", Toast.LENGTH_LONG).show() return } if (ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { checkPermission() return } // 同时注册GPS和网络定位 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 3f, myLocation) locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 3f, myLocation) // 先拿最后一次缓存的位置,避免首次等待太久 val lastKnownGps = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) val lastKnownNetwork = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) currentLocation = lastKnownGps ?: lastKnownNetwork ?: currentLocation var myThread=updateThread() myThread.start() }
核心问题2:权限配置不全,高版本安卓系统兼容问题
- 你的Manifest仅配置了
ACCESS_FINE_LOCATION,缺少ACCESS_COARSE_LOCATION权限,安卓12及以上系统如果用户选择授予近似位置权限,应用无法正常获取位置 - 缺少
ACCESS_NETWORK_STATE权限,Google地图需要该权限检查网络状态加载地图瓦片
解决方案:
在AndroidManifest.xml中新增两个权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
同时修改权限请求逻辑,同时申请两个定位权限:
// 修改checkPermission方法 fun checkPermission() { if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED) { requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION),accessLocation) return } getLocation() }
核心问题3:异步初始化时序问题,可能出现空指针崩溃
你在onCreate中同时触发地图初始化和权限校验,两个流程都是异步执行,若权限校验先完成,定位线程启动时地图还未初始化完成,调用mMap相关方法会触发空指针崩溃。
解决方案:
调整逻辑,等地图初始化完成后再执行权限校验和位置获取:
override fun onMapReady(googleMap: GoogleMap) { mMap = googleMap // 地图初始化完成后再检查权限拿位置 checkPermission() } // onCreate中删除checkPermission()调用 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) usr_name=intent.getStringExtra(Data.usr_name).toString() binding = ActivityDisplayBinding.inflate(layoutInflater) setContentView(binding.root) val mapFragment = supportFragmentManager .findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) // 删掉这里的checkPermission()调用 }
核心问题4:API签名不匹配导致地图加载异常
模拟器运行时用的是debug签名对应的Google地图API key,如果你真机安装的是release包,没有配置release签名对应的API key,会导致地图加载失败、位置无法显示。
解决方案:
在Google Cloud控制台中添加release签名的SHA1值到API key的白名单中,同时在项目的release资源目录下配置对应的API key。
内容的提问来源于stack exchange,提问作者Nebula
相关产品推荐
相关产品推荐

