荣耀9n(Android Oreo)GPS关闭时获取Cell ID与LAC的问题
解决荣耀9n(Android Oreo)GPS关闭时获取Cell ID和LAC的问题
我之前碰到过类似的厂商定制系统权限限制问题,给你梳理下原因和可行的解决思路:
问题根源
Android 8.0(Oreo)开始,系统对位置权限与蜂窝数据获取的关联做了更严格的限制,再加上荣耀这类厂商的定制ROM可能额外加了校验逻辑,导致:
- 主动调用
getAllCellInfo()时直接返回空列表 getCellLocation()仅在GPS开启(即授予ACCESS_FINE_LOCATION且GPS开关打开)时才返回有效数据
解决思路与代码调整
1. 简化权限检查,优先申请ACCESS_COARSE_LOCATION
获取蜂窝小区信息(Cell ID、LAC)只需要ACCESS_COARSE_LOCATION权限,不需要ACCESS_FINE_LOCATION(GPS权限)。你原来的权限判断要求两个权限都授予,这会导致用户只给了网络定位权限时无法执行后续逻辑,调整如下:
TelephonyManager tel = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE); // 只检查COARSE_LOCATION即可,这是获取蜂窝数据的最低要求 if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( getActivity(), new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1001 // 自定义请求码 ); return; }
2. 使用PhoneStateListener监听小区位置变化
主动调用getCellLocation()容易被系统限制,而通过监听回调的方式,能在小区信息更新时主动获取数据,即使GPS关闭也能生效:
// 注册PhoneStateListener监听CellLocation变化 PhoneStateListener cellLocationListener = new PhoneStateListener() { @Override public void onCellLocationChanged(CellLocation location) { super.onCellLocationChanged(location); if (location == null) { Log.e("CellInfo", "获取到的小区位置为空"); return; } // 先判断当前手机网络类型,避免强制转换出错 if (tel.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) { GsmCellLocation gsmLocation = (GsmCellLocation) location; int cellId = gsmLocation.getCid(); int lac = gsmLocation.getLac(); Log.e("CellInfo", "Cell ID: " + cellId + " | LAC: " + lac); } } }; // 启动监听 tel.listen(cellLocationListener, PhoneStateListener.LISTEN_CELL_LOCATION);
3. 确保系统位置开关处于开启状态
即使关闭GPS,也需要打开系统的「位置信息」开关,并选择「仅使用网络定位」模式——这是很多厂商ROM的强制要求,否则蜂窝数据接口会被屏蔽。
4. 关于getAllCellInfo()返回空的补充
如果需要使用getAllCellInfo(),除了上述权限和位置开关的要求,还可以尝试通过监听回调获取(部分厂商在主动调用时会限制,但回调能拿到数据):
PhoneStateListener cellInfoListener = new PhoneStateListener() { @Override public void onCellInfoChanged(List<CellInfo> cellInfo) { super.onCellInfoChanged(cellInfo); if (cellInfo != null && !cellInfo.isEmpty()) { // 遍历处理CellInfo数据 for (CellInfo info : cellInfo) { if (info instanceof CellInfoGsm) { CellInfoGsm gsmInfo = (CellInfoGsm) info; CellIdentityGsm identity = gsmInfo.getCellIdentity(); Log.e("CellInfo", "Cell ID: " + identity.getCid() + " | LAC: " + identity.getLac()); } } } } }; tel.listen(cellInfoListener, PhoneStateListener.LISTEN_CELL_INFO);
注意事项
- 记得在页面销毁时停止监听,避免内存泄漏:
tel.listen(cellLocationListener, PhoneStateListener.LISTEN_NONE); - 部分地区的运营商网络可能不返回完整的LAC/Cell ID,需要做好空值处理
内容的提问来源于stack exchange,提问作者Jeosh Kurian E J
相关产品推荐
相关产品推荐

