安卓扫描周围基站信息,获取邻小区频段频点
在上一家公司做了一個用安卓手機掃描周圍頻點的功能,雖然在安卓 9.0 能獲取到頻段、頻點,但是也只限于自己手機 sim 卡對應的鄰小區,作用不太大。
不過也是有人做這個,用 root 的手機底層開發,可以切換自身頻點,獲取到想要的鄰小區數據,軟件收費,當時手上還有這么個軟件,可是忘了叫什么名字了,有興趣可以自己找找。
下面記錄下我的代碼:
代碼
import android.Manifest; import android.content.pm.PackageManager; import android.os.Build; import android.telephony.CellInfo; import android.telephony.CellInfoGsm; import android.telephony.CellInfoLte; import android.telephony.CellInfoWcdma; import android.telephony.TelephonyManager; import android.telephony.gsm.GsmCellLocation;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;import static android.content.Context.TELEPHONY_SERVICE;public class LteUtils {private static TelephonyManager telephonymanager =(TelephonyManager) MyApplication.getContext().getSystemService(TELEPHONY_SERVICE);public static List<Map<String, Integer>> getLteInfo() {List<Map<String, Integer>> mapList = new ArrayList<>();try {//權限確認if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (MyApplication.getContext().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {//直接返回return mapList;}}//獲取周圍小區信息List<CellInfo> allCellinfo = telephonymanager.getAllCellInfo();if (allCellinfo != null) {for (CellInfo cellInfo : allCellinfo) {//GSMif (cellInfo instanceof CellInfoGsm) {CellInfoGsm cellInfoGsm = (CellInfoGsm) cellInfo;Map<String, Integer> map = new HashMap<>();map.put("Ci", cellInfoGsm.getCellIdentity().getCid());map.put("Rsrp", cellInfoGsm.getCellSignalStrength().getDbm());map.put("AsuLevel", cellInfoGsm.getCellSignalStrength().getAsuLevel());map.put("Lac", cellInfoGsm.getCellIdentity().getLac());map.put("Tac", cellInfoGsm.getCellSignalStrength().getDbm());mapList.add(map);//WCDMA} else if (cellInfo instanceof CellInfoWcdma) {CellInfoWcdma cellInfoWcdma = (CellInfoWcdma) cellInfo;Map<String, Integer> map = new HashMap<>();map.put("Ci", cellInfoWcdma.getCellIdentity().getCid());map.put("Rsrp", cellInfoWcdma.getCellSignalStrength().getDbm());map.put("Psc", cellInfoWcdma.getCellIdentity().getPsc());map.put("AsuLevel", cellInfoWcdma.getCellSignalStrength().getAsuLevel());map.put("Lac", cellInfoWcdma.getCellIdentity().getLac());mapList.add(map);//Lte} else if (cellInfo instanceof CellInfoLte) {CellInfoLte cellInfoLte = (CellInfoLte) cellInfo;Map<String, Integer> map = new HashMap<>();map.put("Ci", cellInfoLte.getCellIdentity().getCi());map.put("Tac", cellInfoLte.getCellIdentity().getTac());map.put("Rsrp", cellInfoLte.getCellSignalStrength().getDbm());map.put("Pci", cellInfoLte.getCellIdentity().getPci());//在7.0以上才能獲取頻點if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {map.put("Earfcn", cellInfoLte.getCellIdentity().getEarfcn());} else {map.put("Earfcn", 0);}//9.0才能過去頻段if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {map.put("Bandwidth", cellInfoLte.getCellIdentity().getBandwidth());}map.put("Mcc", cellInfoLte.getCellIdentity().getMcc());map.put("Mnc", cellInfoLte.getCellIdentity().getMnc());mapList.add(map);} else {//舊設備mapList.addAll(getServerCellInfoOnOlderDevices());}}}} catch (Exception e) {//舊設備mapList.addAll(getServerCellInfoOnOlderDevices());}return mapList;}/*** 舊設備(低安卓版本)獲取相關信息*/private static List<Map<String, Integer>> getServerCellInfoOnOlderDevices() {List<Map<String, Integer>> mapList = new ArrayList<>();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (MyApplication.getContext().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED&& MyApplication.getContext().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {//直接返回return mapList;}}GsmCellLocation location = (GsmCellLocation) telephonymanager.getCellLocation();Map<String, Integer> map = new HashMap<>();map.put("Ci", location.getCid());map.put("Tac", location.getLac());map.put("Psc", location.getPsc());mapList.add(map);return mapList;}/*** 將獲取到的數據轉成 SweepInfo* @param mapList 數據* @return SweepInfo list*/public static List<SweepInfo> LteMapToInfo(List<Map<String, Integer>> mapList) {List<SweepInfo> datas = new ArrayList<>();int index = 0;for (Map<String, Integer> map : mapList) {SweepInfo info = new SweepInfo();info.setOrder(index);info.setBand(Utils.getBandFromRate("" + map.get("Earfcn")));info.setOprater(Utils.getOpretorFromRate("" + map.get("Earfcn")));info.setCi("" + map.get("Ci"));info.setPci("" + map.get("Pci"));info.setRsrp("" + map.get("Rsrp"));info.setEarfcn("" + map.get("Earfcn"));index++;datas.add(info);}return datas;} }MyApplication 是自己定義的 Application,自己寫一下吧,就是獲取個 context。
- SweepInfo
 
這就是個數據類,用來存放掃描到的頻點信息。
使用
//申請權限 requestRunTimePermission(new String[]{Manifest.permission.READ_PHONE_STATE,Manifest.permission.ACCESS_COARSE_LOCATION}, new BaseActivity.PermissionListener() {@Overridepublic void onGranted() {//較為耗時,移到進程中處理new Thread(() -> {try{ArrayList<SweepInfo> infoTemp = new ArrayList<>(LteUtils.LteMapToInfo(LteUtils.getLteInfo()));//do u want in UI threadrunOnUiThread(new Runnable() {@Overridepublic void run() {}});}catch (Exception e){e.printStackTrace();}}).start();}@Overridepublic void onGranted(List<String> grantedPermission) {}@Overridepublic void onDenied(List<String> deniedPermission) {} });這里需要確認下權限,記得在 manifest 里面加上,這個申請權限的方法是我封裝的,讀者自己申請下,很簡單的。
相關名詞介紹
-  
MCC,Mobile Country Code,移動國家代碼(中國的為460);
 -  
MNC,Mobile Network Code,移動網絡號碼(中國移動為0,中國聯通為1,中國電信為2);
 -  
LAC,Location Area Code,位置區域碼;
 -  
CID,Cell Identity,基站編號;
 -  
BSSS,Base station signal strength,基站信號強度。
 -  
eNB E-UTRAN Node B 為LTE系統中E-UTRAN的組成部分,計算eNB的方式是 ci = eNB*256+cid
 
結語
這里雖然能獲取到一些頻段、頻點信息,可是限制性還剩挺大的,上面代碼也很簡陋。這里也推薦一個軟件,里面有獲取 LTE、WiFi、Gps 相關信息的功能,雖然有廣告,還是不錯的,名字叫 cellular - Z,可以自己去下載。
總結
以上是生活随笔為你收集整理的安卓扫描周围基站信息,获取邻小区频段频点的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 高通搜网流程
 - 下一篇: LTE通讯相关2:频带、信道带宽和频点号