Вопрос или проблема
Как получить данные о сотовой башне, к которой подключена SIM-карта на Android 10?
Я пробовал несколько вариантов, и ни один из них не сработал. Все права предоставлены (Permission.INTERNET, Permission.ACCESS_NETWORK_STATE, Permission.ACCESS_COARSE_LOCATION, Permission.ACCESS_FINE_LOCATION, Permission.READ_PHONE_STATE
). Геолокация включена. Но цикл for cell_info in cell_info_list
не выполняется
from kivy.app import App
if (platform == 'android'):
import android
from android.permissions import request_permissions, Permission
from jnius import autoclass, cast
request_permissions([
Permission.INTERNET,
Permission.ACCESS_NETWORK_STATE,
Permission.ACCESS_COARSE_LOCATION,
Permission.ACCESS_FINE_LOCATION,
Permission.READ_PHONE_STATE,
])
def get_cell_location():
try:
PythonActivity = autoclass('org.kivy.android.PythonActivity')
android_context = PythonActivity.mActivity
TelephonyManager = autoclass('android.telephony.TelephonyManager')
tel_manager = cast('android.telephony.TelephonyManager',
android_context.getSystemService(android_context.TELEPHONY_SERVICE))
cell_info_list = tel_manager.getAllCellInfo()
for cell_info in cell_info_list:
if isinstance(cell_info, autoclass('android.telephony.CellInfoGsm')):
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMcc()
mnc = cell_identity.getMnc()
lac = cell_identity.getLac()
cid = cell_identity.getCid()
network_type = TelephonyManager.NETWORK_TYPE_GSM
elif isinstance(cell_info, autoclass('android.telephony.CellInfoCdma')):
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getSystemId()
mnc = cell_identity.getNetworkId()
lac = cell_identity.getBasestationId()
cid = cell_identity.getBasestationId()
network_type = TelephonyManager.NETWORK_TYPE_CDMA
elif isinstance(cell_info, autoclass('android.telephony.CellInfoLte')):
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMccString()
mnc = cell_identity.getMncString()
lac = cell_identity.getTac()
cid = cell_identity.getCi()
network_type = TelephonyManager.NETWORK_TYPE_LTE
elif isinstance(cell_info, autoclass('android.telephony.CellInfoWcdma')):
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMcc()
mnc = cell_identity.getMnc()
lac = cell_identity.getLac()
cid = cell_identity.getCid()
network_type = TelephonyManager.NETWORK_TYPE_UMTS
elif isinstance(cell_info, autoclass('android.telephony.CellInfoNr')):
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMccString()
mnc = cell_identity.getMncString()
lac = cell_identity.getTac()
cid = cell_identity.getNci()
network_type = TelephonyManager.NETWORK_TYPE_NR
else:
mcc = ""
mnc = ""
lac = ""
cid = ""
network_type = ""
continue
print(f"{mcc}\n{mnc}\n{lac}\n{cid}\n{str(network_type)}")
except Exception as e:
print(str(e))
class MyApp(MDApp):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.screen = Builder.load_string(KV)
def build(self):
get_cell_location()
return self.screen
if __name__ == "__main__":
MyApp().run()
дальнейшие варианты для функции получения
def get_cell_location():
try:
PythonActivity = autoclass('org.kivy.android.PythonActivity')
android_context = PythonActivity.mActivity
TelephonyManager = autoclass('android.telephony.TelephonyManager')
tel_manager = cast('android.telephony.TelephonyManager',
android_context.getSystemService(android_context.TELEPHONY_SERVICE))
cell_info_list = tel_manager.getAllCellInfo()
for cell_info in cell_info_list:
cell_type = cell_info.get_cell_type()
if cell_type == autoclass('android.telephony.CellInfo$CellType').GSM:
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMcc(),
mnc = cell_identity.getMnc()
lac = cell_identity.getLac()
cid = cell_identity.getCid()
network_type = autoclass('android.telephony.TelephonyManager').NETWORK_TYPE_GSM
elif cell_type == autoclass('android.telephony.CellInfo$CellType').CDMA:
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getSystemId()
mnc = cell_identity.getNetworkId()
lac = cell_identity.getBasestationId()
cid = cell_identity.getBasestationId()
network_type = autoclass('android.telephony.TelephonyManager').NETWORK_TYPE_CDMA
elif cell_type == autoclass('android.telephony.CellInfo$CellType').LTE:
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMccString()
mnc = cell_identity.getMncString()
lac = cell_identity.getTac()
cid = cell_identity.getCi()
network_type = autoclass('android.telephony.TelephonyManager').NETWORK_TYPE_LTE
elif cell_type == autoclass('android.telephony.CellInfo$CellType').WCDMA:
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMcc()
mnc = cell_identity.getMnc()
lac = cell_identity.getLac()
cid = cell_identity.getCid()
network_type = autoclass('android.telephony.TelephonyManager').NETWORK_TYPE_UMTS
elif cell_type == autoclass('android.telephony.CellInfo$CellType').NR:
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMccString()
mnc = cell_identity.getMncString()
lac = cell_identity.getTac()
cid = cell_identity.getNci()
network_type = autoclass('android.telephony.TelephonyManager').NETWORK_TYPE_NR
else:
mcc = ""
mnc = ""
lac = ""
cid = ""
network_type = ""
continue
print(f"{mcc}\n{mnc}\n{lac}\n{cid}\n{str(network_type)}")
except Exception as e:
print(str(e))
def get_cell_location():
try:
PythonActivity = autoclass('org.kivy.android.PythonActivity')
android_context = PythonActivity.mActivity
TelephonyManager = autoclass('android.telephony.TelephonyManager')
tel_manager = cast('android.telephony.TelephonyManager',
android_context.getSystemService(android_context.TELEPHONY_SERVICE))
cell_info_list = tel_manager.getAllCellInfo()
for cell_info in cell_info_list:
cell_type = cell_info.getClass().getSimpleName()
if cell_type == "CellInfoGsm":
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMcc()
mnc = cell_identity.getMnc()
lac = cell_identity.getLac()
cid = cell_identity.getCid()
network_type = TelephonyManager.NETWORK_TYPE_GSM
elif cell_type == "CellInfoCdma":
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getSystemId()
mnc = cell_identity.getNetworkId()
lac = cell_identity.getBasestationId()
cid = cell_identity.getBasestationId()
network_type = TelephonyManager.NETWORK_TYPE_CDMA
elif cell_type == "CellInfoLte":
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMccString()
mnc = cell_identity.getMncString()
lac = cell_identity.getTac()
cid = cell_identity.getCi()
network_type = TelephonyManager.NETWORK_TYPE_LTE
elif cell_type == "CellInfoWcdma":
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMcc()
mnc = cell_identity.getMnc()
lac = cell_identity.getLac()
cid = cell_identity.getCid()
network_type = TelephonyManager.NETWORK_TYPE_UMTS
elif cell_type == "CellInfoNr":
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMccString()
mnc = cell_identity.getMncString()
lac = cell_identity.getTac()
cid = cell_identity.getNci()
network_type = TelephonyManager.NETWORK_TYPE_NR
else:
mcc = ""
mnc = ""
lac = ""
cid = ""
network_type = ""
continue
print(f"{mcc}\n{mnc}\n{lac}\n{cid}\n{str(network_type)}")
except Exception as e:
print(str(e))
def get_cell_location():
try:
service_state = tel_manager.getServiceState()
cell_location = tel_manager.getCellLocation()
if isinstance(cell_location, autoclass('android.telephony.gsm.GsmCellLocation')):
gsm_cell_location = cell_location
mcc = gsm_cell_location.getMobileCountryCode()
mnc = gsm_cell_location.getMobileNetworkCode()
lac = gsm_cell_location.getLac()
cid = gsm_cell_location.getCid()
network_type = TelephonyManager.NETWORK_TYPE_GSM
elif isinstance(cell_location, autoclass('android.telephony.cdma.CdmaCellLocation')):
cdma_cell_location = cell_location
mcc = service_state.getSystemId()
mnc = service_state.getNetworkId()
lac = cdma_cell_location.getBaseStationId()
cid = cdma_cell_location.getBaseStationId()
network_type = TelephonyManager.NETWORK_TYPE_CDMA
elif isinstance(cell_location, autoclass('android.telephony.CellIdentityLte')):
lte_cell_identity = cell_location
mcc = lte_cell_identity.getMccString()
mnc = lte_cell_identity.getMncString()
lac = lte_cell_identity.getTac()
cid = lte_cell_identity.getCi()
network_type = TelephonyManager.NETWORK_TYPE_LTE
elif isinstance(cell_location, autoclass('android.telephony.CellIdentityWcdma')):
wcdma_cell_identity = cell_location
mcc = wcdma_cell_identity.getMcc()
mnc = wcdma_cell_identity.getMnc()
lac = wcdma_cell_identity.getLac()
cid = wcdma_cell_identity.getCid()
network_type = TelephonyManager.NETWORK_TYPE_UMTS
elif isinstance(cell_location, autoclass('android.telephony.CellIdentityLte')):
nr_cell_identity = cell_location
mcc = nr_cell_identity.getMccString()
mnc = nr_cell_identity.getMncString()
lac = nr_cell_identity.getTac()
cid = nr_cell_identity.getNCi()
network_type = TelephonyManager.NETWORK_TYPE_NR
else:
mcc = ""
mnc = ""
lac = ""
cid = ""
network_type = ""
continue
print(f"{mcc}\n{mnc}\n{lac}\n{cid}\n{str(network_type)}")
except Exception as e:
print(str(e))
def get_cell_location():
try:
PythonActivity = autoclass('org.kivy.android.PythonActivity')
android_context = PythonActivity.mActivity
cell_info_manager = cast('android.telephony.CellInfoManager', android_context.getSystemService(android_context.CELL_INFO_SERVICE))
# Или попробуйте вместо первых строк
# android_context = android_activity.get_context()
# cell_info_manager = cast('android.telephony.CellInfoManager', context.getSystemService(context.CELL_INFO_SERVICE))
cell_info_list = cell_info_manager.getCellInfo()
print(len(cell_info_list))
for cell_info in cell_info_list:
cell_type = type(cell_info)
if cell_type == autoclass('android.telephony.CellInfoGsm'):
gsm_cell_info = cell_info.getCellIdentity()
mcc = gsm_cell_info.getMcc()
mnc = gsm_cell_info.getMnc()
lac = gsm_cell_info.getLac()
cid = gsm_cell_info.getCid()
network_type="GSM"
elif cell_type == autoclass('android.telephony.CellInfoCdma'):
cdma_cell_info = cell_info.getCellIdentity()
mcc = cdma_cell_info.getSystemId()
mnc = cdma_cell_info.getNetworkId()
lac = cdma_cell_info.getBasestationId()
cid = cdma_cell_info.getBasestationId()
network_type="CDMA"
elif cell_type == autoclass('android.telephony.CellInfoLte'):
lte_cell_info = cell_info.getCellIdentity()
mcc = lte_cell_info.getMccString()
mnc = lte_cell_info.getMncString()
lac = lte_cell_info.getTac()
cid = lte_cell_info.getCi()
network_type="LTE"
elif cell_type == autoclass('android.telephony.CellInfoWcdma'):
wcdma_cell_info = cell_info.getCellIdentity()
mcc = wcdma_cell_info.getMcc()
mnc = wcdma_cell_info.getMnc()
lac = wcdma_cell_info.getLac()
cid = wcdma_cell_info.getCid()
network_type="WCDMA"
elif cell_type == autoclass('android.telephony.CellInfoNr'):
nr_cell_info = cell_info.getCellIdentity()
mcc = nr_cell_info.getMccString()
mnc = nr_cell_info.getMncString()
lac = nr_cell_info.getTac()
cid = nr_cell_info.getNci()
network_type="NR"
else:
mcc = ""
mnc = ""
lac = ""
cid = ""
network_type = ""
continue
print(f"{mcc}\n{mnc}\n{lac}\n{cid}\n{str(network_type)}")
except Exception as e:
print(str(e))
Я прочитал документацию Android. С версии 10 необходимо вызывать обратный вызов, но из-за нехватки знаний я не знаю, как это реализовать.
UPD:
У меня также отключено обновление данных о башнях в инженерном меню. Включение ничего не изменило. Но из документации нужно как-то реализовать запрос на обновление, а затем обратный вызов
Ответ или решение
Чтобы получить данные о сотовых вышках, к которым подключена SIM-карта на Android 10 и выше, вам нужно выполнить несколько шагов и использовать подходящие методы для получения информации с учетом новых ограничений, связанных с доступом к данным о местоположении. В вашем коде отсутствует правильная реализация обратного вызова для получения данных о вышках.
Вот исправленный пример кода, который должен помочь вам получить данные о сотовых вышках:
from kivy.app import App
from kivy.clock import Clock
from jnius import autoclass, cast
from android.permissions import request_permissions, Permission
class MyApp(App):
def build(self):
self.request_permissions()
Clock.schedule_once(self.get_cell_location, 1) # Запускаем получение данных через 1 секунду после запуска приложения
return None # Здесь можно добавить ваш GUI, если нужно
def request_permissions(self):
request_permissions([
Permission.INTERNET,
Permission.ACCESS_NETWORK_STATE,
Permission.ACCESS_FINE_LOCATION,
Permission.READ_PHONE_STATE,
])
def get_cell_location(self, *args):
try:
PythonActivity = autoclass('org.kivy.android.PythonActivity')
android_context = PythonActivity.mActivity
TelephonyManager = autoclass('android.telephony.TelephonyManager')
tel_manager = cast('android.telephony.TelephonyManager',
android_context.getSystemService(android_context.TELEPHONY_SERVICE))
# Проверка разрешений
if not self.check_permissions():
print("Необходимы разрешения.")
return
cell_info_list = tel_manager.getAllCellInfo()
if cell_info_list:
for cell_info in cell_info_list:
self.process_cell_info(cell_info)
else:
print("Нет информации о сотовых вышках.")
except Exception as e:
print(f"Ошибка: {str(e)}")
def check_permissions(self):
# Проверка разрешений (вы можете добавить проверку статуса разрешений)
return True
def process_cell_info(self, cell_info):
TelephonyManager = autoclass('android.telephony.TelephonyManager')
if isinstance(cell_info, autoclass('android.telephony.CellInfoGsm')):
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMcc()
mnc = cell_identity.getMnc()
lac = cell_identity.getLac()
cid = cell_identity.getCid()
network_type = TelephonyManager.NETWORK_TYPE_GSM
elif isinstance(cell_info, autoclass('android.telephony.CellInfoCdma')):
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getSystemId()
mnc = cell_identity.getNetworkId()
lac = cell_identity.getBasestationId()
cid = cell_identity.getBasestationId()
network_type = TelephonyManager.NETWORK_TYPE_CDMA
elif isinstance(cell_info, autoclass('android.telephony.CellInfoLte')):
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMccString()
mnc = cell_identity.getMncString()
lac = cell_identity.getTac()
cid = cell_identity.getCi()
network_type = TelephonyManager.NETWORK_TYPE_LTE
elif isinstance(cell_info, autoclass('android.telephony.CellInfoWcdma')):
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMcc()
mnc = cell_identity.getMnc()
lac = cell_identity.getLac()
cid = cell_identity.getCid()
network_type = TelephonyManager.NETWORK_TYPE_UMTS
elif isinstance(cell_info, autoclass('android.telephony.CellInfoNr')):
cell_identity = cell_info.getCellIdentity()
mcc = cell_identity.getMccString()
mnc = cell_identity.getMncString()
lac = cell_identity.getTac()
cid = cell_identity.getNci()
network_type = TelephonyManager.NETWORK_TYPE_NR
else:
return # Неподдерживаемый тип вышки
print(f"MCC: {mcc}, MNC: {mnc}, LAC: {lac}, CID: {cid}, Network Type: {network_type}")
if __name__ == "__main__":
MyApp().run()
Важные моменты:
-
Проверка разрешений: Убедитесь, что ваше приложение имеет все необходимые разрешения, чтобы получить доступ к информации о сотовых вышках. Вы можете использовать функции для проверки и запроса разрешений.
-
Используйте
Clock.schedule_once
: Это гарантирует, что ваш код для получения данных о сотовых вышках будет запущен после того, как ваше приложение инициализируется. -
Обработка информации о вышках: Убедитесь, что вы обрабатываете данные, полученные из
cell_info
, и выводите их для отладки. -
Проверка состояния сети: Убедитесь, что ваше устройство подключено к сети и может получать данные о вышках. Если данные отключены из меню инженера, попробуйте включить их.
-
Обратный вызов: Если вы хотите использовать обратный вызов (например, слушателя для обновления данных), вам нужно будет реализовать соответствующий механизм, чтобы ваше приложение могло получать обновления в фоновом режиме.
Если проблемы сохраняются, убедитесь, что ваш код работает на реальном устройстве с поддержкой необходимых функций, так как эмуляторы могут не предоставлять правильную информацию о сотовых вышках.