Вы когда-нибудь задумывались, сколько приложений на вашем телефоне на самом деле имеют доступ к сети? А главное — получали ли они этот доступ с вашего согласия? Я знаю, что многие ставят крестик на этом вопросе: «Ну, интернет-то почти всем нужен, что тут такого». Но проблема в другом: приложение, которое при установке не имело разрешения INTERNET, после очередного обновления может его получить. И вы об этом даже не узнаете.
Почему это плохо? Представьте себе офлайн-игру или простой таймер. Вы дали ему разрешения на уведомления и, может быть, на доступ к хранилищу (чтобы сохранять рекорды). Интернет ему вроде бы ни к чему. Но в какой-то момент разработчик решает «добавить аналитику» или «отправлять отчёты о падениях» — и включает в манифесте разрешение INTERNET. Обычно ОС Android не станет показывать пользователю диалог о новом разрешении, если оно считается «неопасным» (а INTERNET относится к low-risk). В итоге вы получаете приложение, которое теперь может тихо отправлять ваши данные куда-то в сеть, а вы этого даже не заметили.
Чтобы решить эту проблему, я написал небольшое приложение AppWatcher, которое отслеживает, когда какое-либо приложение получает доступ к интернету после обновления, и бьёт тревогу. В этой статье я расскажу, как оно устроено изнутри, почему такой мониторинг важен и как вы можете его использовать или даже улучшить.
Что делает AppWatcher
Приложение работает в фоне и слушает системные события об установке, обновлении и удалении пакетов. Как только происходит обновление приложения, AppWatcher проверяет: имеет ли это приложение разрешение INTERNET и было ли оно в «белом списке» — тех приложениях, которые уже имели интернет на момент первого запуска монитора.
Если приложение новое (раньше не имело INTERNET, а теперь имеет) — генерируется Alert (тревога). Пользователь получает push-уведомление и может увидеть полный список всех тревог в приложении с указанием имени приложения, пакета и времени события.
Кроме того, AppWatcher постоянно обновляет свой «слепок» известных интернет-приложений, чтобы корректно отслеживать изменения при следующих обновлениях.
Как это реализовано на Android
Разберём ключевые компоненты кода.
1. Сохранение состояния — класс Prefs
Для хранения простых данных используется SharedPreferences. Вот что мы храним:
enabled – включён ли мониторинг.
known_inet – множество пакетов (Set), которые уже имели INTERNET при последнем сканировании.
alerts – JSON-массив событий (максимум 50 последних тревог).
Каждое событие — это объект с полями pkg, name и timestamp. Метод addAlert() добавляет запись и автоматически обрезает список до 50 элементов, чтобы не раздувать хранилище.
2. Сканирование всех приложений с INTERNET
При первом запуске или при включении мониторинга мы обходим все установленные пакеты и для каждого проверяем разрешение INTERNET:
kotlin
val pm = context.packageManager
val known = mutableSetOf()
runCatching {
val apps = pm.getInstalledPackages(PackageManager.GET_PERMISSIONS)
for (info in apps) {
if (pm.checkPermission(android.Manifest.permission.INTERNET, info.packageName)
== PackageManager.PERMISSION_GRANTED) {
known.add(info.packageName)
}
}
}
prefs.knownInternetApps = known
Этот код выполняется в MainActivity при первом запуске и при включении мониторинга, а также в BootReceiver после перезагрузки устройства (на случай, если во время сна телефона какие-то приложения обновились).
3. Слушатель событий пакетов — PackageReceiver
Самый интересный компонент. Он подписан на Intent.ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REPLACED (обновление) и ACTION_PACKAGE_REMOVED. Именно здесь происходит основная логика.
Алгоритм работы:
Получаем имя пакета из intent.data.
Если мониторинг отключён (prefs.enabled == false) — выходим.
Проверяем, имеет ли приложение INTERNET прямо сейчас (через PackageManager.checkPermission).
Смотрим, было ли это приложение в сохранённом наборе knownInternetApps.
Если имеет интернет сейчас, но не было в known → тревога!
Для этого извлекаем красивое имя приложения (getApplicationLabel) и вызываем prefs.addAlert(), а также показываем уведомление через NotificationManager.
После этого обновляем наш known-набор: добавляем пакет, если у него есть интернет, или удаляем, если интернет отозвали (такое тоже бывает при обновлении).
Обратите внимание на обработку исключений: мы используем runCatching, потому что после удаления приложения мы всё равно можем получить событие, а попытка получить информацию из PackageManager для удалённого пакета выбросит исключение.
4. Загрузка при перезагрузке — BootReceiver
Чтобы после перезагрузки телефона known-набор оставался актуальным (ведь за время выключения могли произойти обновления через Google Play), мы пересобираем его при старте системы. Только одно действие: заново сканируем все пакеты с INTERNET и сохраняем в Prefs. Никаких лишних тревог на этом этапе не генерируется — только синхронизация базового состояния.
5. Пользовательский интерфейс
Главный экран (MainActivity) содержит:
Переключатель для включения/выключения мониторинга.
Кнопку для очистки истории тревог.
RecyclerView со списком тревог, где каждая строка показывает имя приложения, имя пакета и время события.
Адаптер простой, с использованием SimpleDateFormat для форматирования времени.
Почему это не работает для всех разрешений?
В Android существует разделение на «опасные» и «нормальные» разрешения. INTERNET относится к нормальным. Приложения не запрашивают его у пользователя во время работы — оно просто прописывается в манифесте, и система разрешает его автоматически. Именно поэтому наши тревоги так полезны: вы не получите стандартный запрос, а значит, никак не узнаете о новом INTERNET у старого приложения.
Если бы мы хотели следить за такими разрешениями, как CAMERA или LOCATION, то механизм был бы сложнее — нужно было бы отслеживать изменения в onRequestPermissionsResult и т.д. Но для INTERNET наш подход идеален.
Заключение
AppWatcher — это небольшой, но полезный инструмент для контроля над приватностью на Android. Он не требует root-прав и работает на любом устройстве с Android 5.0 и выше. Код проекта полностью открыт (вы можете найти его на GitHub по ссылке ниже), и я приглашаю всех желающих поучаствовать в его развитии.
Потратьте 5 минут, чтобы установить AppWatcher и включить мониторинг. Через пару недель вы удивитесь, сколько приложений тихо получают доступ к интернету при обновлениях. И, возможно, захотите удалить некоторые из них.
Берегите свои данные — они стоят дороже, чем кажется.
Исходный код: доступен по запросу
Скачать APK: ссылка в релизах
Вопросы и предложения пишите в комментариях или в телеграм-канал @tech_prog_grodno_2s2_by