Android高版本Google Maps标记不显示问题及动态权限咨询
问题原因分析与解决方案
嘿,这个问题我之前帮同行排查过,核心就是Android高版本的运行时权限机制在搞鬼!咱们一步步拆解:
一、为什么S4正常,S8及以上失效?
三星S4一般搭载Android 5.1或更低版本(API <23),而S8及以上是Android 7.0+(API ≥24)。从Android 6.0开始,谷歌引入了运行时权限机制——对于「危险权限」(比如位置权限、存储权限),仅在AndroidManifest.xml里静态声明根本不够,必须在代码里主动向用户申请并获得授权才能使用。
你的情况大概率是:
- 自定义标记的加载依赖了危险权限(比如从本地存储读取图标,或者地图需要位置权限才能正常渲染标记);
- 低版本系统(S4)不需要动态申请,所以一切正常;
- 高版本系统(S8+)因为权限未授权,直接阻止了标记加载和点击监听的相关操作,导致功能失效。
另外还要注意高版本的额外限制:比如Android 10+的存储权限范围缩小,Android 12+的位置权限拆分得更细,这些都可能间接影响标记显示。
二、Google Maps运行时权限配置全步骤
1. 先在Manifest里静态声明权限
打开AndroidManifest.xml,添加必要的权限:
<!-- 地图基础权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 位置权限(如果标记依赖定位服务,或者地图需要定位) --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 存储权限(如果自定义标记图标存在本地存储) --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- Android 13+请用READ_MEDIA_IMAGES替代 -->
划重点:Android 13(API 33)及以上,存储权限被拆成了
READ_MEDIA_IMAGES、READ_MEDIA_VIDEO等,要根据你的资源类型替换。
2. 代码里动态申请权限
在初始化地图和标记之前,必须先检查权限是否授权:
第一步:定义需要申请的权限数组
根据你的实际需求选,比如位置+存储权限:
private static final String[] REQUIRED_PERMISSIONS = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_EXTERNAL_STORAGE // 不需要的话可以删掉 }; private static final int PERMISSION_REQUEST_CODE = 100;
第二步:检查权限并发起申请
在onCreate或者地图准备前的逻辑里加这段:
// 检查权限是否已授权 boolean hasFineLocation = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; boolean hasStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; if (!hasFineLocation || !hasStorage) { // 权限没给,弹框申请 ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, PERMISSION_REQUEST_CODE); } else { // 权限都有了,放心初始化地图和标记 initMapAndMarkers(); }
第三步:处理权限申请结果
重写onRequestPermissionsResult方法,根据用户的选择执行逻辑:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_REQUEST_CODE) { boolean allGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (allGranted) { // 所有权限授权成功,开始加载地图和标记 initMapAndMarkers(); } else { // 权限被拒,提示用户去设置里开 Toast.makeText(this, "需要相关权限才能显示标记,请在应用设置中开启", Toast.LENGTH_LONG).show(); } } }
3. 高版本系统的额外适配
- Android 10+存储适配:如果你的标记图标是从外部存储拿的,建议把图标放到
res/drawable目录下(完全避开存储权限),或者用MediaStore获取文件Uri,别直接用路径读取。 - Android 12+位置权限:如果应用在后台还需要定位,得额外申请
ACCESS_BACKGROUND_LOCATION权限,而且申请时要跟用户说明为啥需要后台定位,不然用户大概率会拒绝。
三、其他可能的排查点
如果权限配好后标记还是不显示,再检查这几点:
- 自定义标记的图标资源是否有效?比如高版本系统对矢量图、分辨率的兼容性有没有问题?
- 标记的经纬度是不是正确?有没有在当前地图的可视范围内?
- 是不是在
onMapReady回调之后才添加的标记?地图没初始化完就加标记肯定显示不出来。
内容的提问来源于stack exchange,提问作者Darshi Patel
相关产品推荐
相关产品推荐

