Activity launcher как пользоваться
Перейти к содержимому

Activity launcher как пользоваться

  • автор:

5 скрытых фишек смартфонов Xiaomi

Xiaomi оснащает свои смартфоны достаточно функциональной оболочкой MIUI. Большинство ее функций легко доступны всем желающим, и их включение лежит на поверхности. Но случается и так, что действительно полезные вещи необходимо искать в недрах самой системы и активировать обходными путями. В одном из наших материалов мы уже разбирали, как откалибровать датчик приближения и отключить всплывающие уведомления, которые работают некорректно уже не одну версию MIUI.

5 скрытых фишек смартфонов Xiaomi. MIUI удобная система, но зачем прятать эти функции так глубоко совсем непонятно. Фото.

MIUI удобная система, но зачем прятать эти функции так глубоко совсем непонятно.

❗️ПОДПИСЫВАЙСЯ НА НАШ КАНАЛ В ЯНДЕКС.ДЗЕН И ЧИТАЙ ЭКСКЛЮЗИВНЫЕ СТАТЬИ БЕСПЛАТНО

Теперь давайте посмотрим, как определить остаточную емкость аккумулятора, включить и отслеживать историю уведомлений, можно ли измерить пульс с помощью смартфона, как активировать экранное время и настроить пользовательские эффекты для наушников.

Xiaomi — емкость аккумулятора

Xiaomi — емкость аккумулятора. Раньше емкость аккумулятора в MIUI можно было посмотреть без этих ухищрений. Фото.

Раньше емкость аккумулятора в MIUI можно было посмотреть без этих ухищрений.

Для всех действий, представленных в этой статье, нам понадобится Activity Launcher. Скачайте его по ссылке и установите на свой смартфон. Раньше это приложение было доступно для загрузки из Google Play, но с весны этого года его можно скачать только с аккаунтов, зарегистрированных не в России.

Рано или поздно, в зависимости от стиля использования, наши смартфоны начинают держать заряд меньше по времени. В такой ситуации надо принимать решение о замене аккумулятора или самого устройства. Но что, если произошел какой-то программный сбой, например, криво встала прошивка при обновлении, а емкость аккумулятора позволяет работать в прежнем режиме или близком к нему? Чтобы это понять, необходимо проверить износ батареи. Самое главное, что это можно сделать практически штатными средствами, не используя сторонние программы по оценке состояния аккумулятора.

Xiaomi — емкость аккумулятора. Хоть это меню и на китайском языке, но суть понять можно. Фото.

Хоть это меню и на китайском языке, но суть понять можно.

  • Откройте установленный ранее Activity Launcher.
  • Введите в поиске «powertools.module.batterylife».
  • Нажмите на результат поиска, и перед вами откроется приложение с данными аккумулятора.
  • В правом верхнем окошке будет емкость батареи с учетом износа, а в левом — изначальная.

Благодаря этой информации вы сможете понять, пришло ли время менять аккумулятор или смартфону необходим cброс до заводских настроек с перепрошивкой. Если емкость снизилась более чем на 20%, то ваш путь лежит в сервисный центр.

Как настроить наушники на Xiaomi

Как настроить наушники на Xiaomi. Персонализация звука применяется даже к AirPods Pro. Фото.

Персонализация звука применяется даже к AirPods Pro.

Следующей скрытой функцией, которая может вам помочь повысить качество звучания ваших наушников — это пользовательские эффекты. Сразу стоит отметить, что лучше всего они работают с наушниками фирмы Xiaomi и Redmi. При их использовании в этом разделе будет даже отображаться изображение с соответствующими «ушами». Для открытия меню «Пользовательские эффекты» потребуется:

Как настроить наушники на Xiaomi. Обязательно прослушайте все представленные образцы и выберите лучший для вас. Фото.

Обязательно прослушайте все представленные образцы и выберите лучший для вас.

  • Откройте установленный ранее Activity Launcher.
  • Введите в поиске «пользовательские эффекты».
  • Нажмите на результат поиска, и перед вами откроется меню настройки пользовательских эффектов.

В этом разделе можно отрегулировать громкость в зависимости от возраста и иных настроек. Но отдельно следует отметить персонализацию звука. Здесь вам будет предложено прослушать несколько образцов воспроизведения и выбрать тот, который придется вам больше по душе. После этого система будет применять такие же параметры к вашей музыке.

История уведомлений — Xiaomi

История уведомлений — Xiaomi. Просмотр истории уведомлений, к сожалению, доступен только из этого же меню. Фото.

Просмотр истории уведомлений, к сожалению, доступен только из этого же меню.

Иногда бывают ситуации, когда может потребоваться просмотреть историю приходящих на смартфон уведомлений. Хранить их в центре уведомлений не всегда хорошая идея, просто из-за того, что можно случайно одним нажатием все их удалить. Для этого в смартфоне есть возможность фиксации истории уведомлений. Для этого необходимо:

  • Открыть установленный ранее Activity Launcher.
  • В поиске ввести «уведомления».
  • Развернуть «Настройки» и выбрать там раздел «Уведомления».
  • В появившемся разделе открыть пункт «История уведомлений» и включить ее.

❗️ПОДПИШИСЬ НА НАШ ЧАТИК В ТЕЛЕГРАМЕ. ТАМ СОБРАЛАСЬ ТОЛЬКО ИЗБРАННАЯ АУДИТОРИЯ

Просмотреть все недавние и отложенные уведомления можно будет в этом же разделе. Жаль, что до него не добраться более быстрым способом.

Как измерить пульс на Xiaomi

Как измерить пульс на Xiaomi. Слабо представляю ситуации, когда понадобится подобный замер пульса, но знать, что такая функция есть необходимо. Фото.

Слабо представляю ситуации, когда понадобится подобный замер пульса, но знать, что такая функция есть необходимо.

Все современные умные часы могут измерять пульс, а некоторые из них еще и насыщенность крови кислородом. Но может сложиться так, что часов или пульсометра под руками нет, а срочно произвести замер необходимо. Тут вас может выручить ваш мобильный телефон. С помощью камеры можно заставить смартфоны Xiaomi определить частоту сердечных сокращений. В определенной ситуации подобный замер поможет принять необходимые решения. Для замера пульса с помощью смартфона выполните следующие действия:

  • Откройте Activity Launcher.
  • В поиске введите «пульс».
  • Откройте результат поиска.
  • Нажмите кнопку «начать» и следуйте инструкциям на экране.

❗️ПОДПИСЫВАЙСЯ НА ТЕЛЕГРАМ-КАНАЛ СУНДУК АЛИБАБЫ. РЕБЯТА ЗНАЮТ ТОЛЬКО В ОТЛИЧНЫХ ТОВАРАХ С АЛИЭКСПРЕСС

Следует иметь в виду, что полагаться на результаты этого замера как на медицинский прибор не стоит. Ведь при отсутствии специального датчика может быть погрешность в измерениях. Однако, произведя тестовый замер на Xiaomi Mi 10T Pro и Amazfit GTR 2 в условиях полного покоя, смартфон показал 77 ударов в минуту, а часы — 78. Показатели оказались очень близки.

Экранное время — Xiaomi

Экранное время — Xiaomi. Можно установить суточный лимит экранного времени и проводить свободное время с большей пользой, чем в телефоне. Фото.

Можно установить суточный лимит экранного времени и проводить свободное время с большей пользой, чем в телефоне.

При первичной настройке смартфонов Xiaomi всегда предлагается активировать замер экранного времени. Эта функция позволяет отслеживать, сколько времени вы провели в вашем гаджете и в каком приложении. Но если не включить его сразу, то в дальнейшем найти этот параметр в настройках будет очень непросто. Если вы решили, что вам необходимо отслеживать экранное время, то сделайте следующее:

  • Откройте Activity Launcher.
  • В поиске введите «UsageStatsMainActivity».
  • Откройте результат поиска.
  • Нажмите кнопку «Согласиться» и экранное время в вашем смартфоне заработает.

Это очень полезная функция для контроля за временем, проведенным детьми в смартфонах. Но пригодится она и взрослым, чтобы не просиживать все свободное время в социальных сетях.

Оставить комментарий в Telegram. Поделитесь мнением в чате читателей Androidinsider.ru

Теги

  • Операционная система MIUI
  • Смартфоны Xiaomi

Как скачать и использовать приложение Activity Launcher в MIUI 11 на Xiaomi (Redmi)

Как бы нам ни нравились смартфоны Xiaomi (Redmi) опытным пользователям очевидно, что многие настройки системы от нас скрыты производителем. Это значит, что они живут где-то внутри телефона и доступа к ним нет, хотя они оказывают своё действие на работоспособность аппарата.

Возможно ли найти скрытые меню в MIUI 11, не меняя глобальную прошивку и не копаясь в дебрях программного кода?

Такая возможность есть с помощью приложения Activity Launcher для MIUI 11.

Где скачать Activity Launcher?

Программа находится в общем доступе в магазине приложений Google Play. Запустите его, в строке поиска наберите «Activity» и нажмите на подсказку с цветной иконкой.
Запуск Google Play МаркетПоиск приложения activity launcher
Вы попадёте на страницу приложения в Play Маркет. Скачайте его обычным способом.
Страница приложения activity launcher в Play Маркет

Как пользоваться Activity Launcher?

Приложение не требует ROOT прав или иного вмешательства в режим работы Xiaomi, достаточно его запустить. Вы увидите список приложений и функций, которые обнаружила программа во время сканирования при запуске.

Введите в строку поиска функцию, которую хотите найти. Для примера введём запрос «Максимально», в поисковой выдаче увидим 2 параметра. Нажмите на второй.
Поиск скрытой функции максимальной экономии
Вы попадёте в скрытые настройки максимальной экономии энергии, в которые не попасть их обычного меню MIUI. Почему этот режим скрыт – загадка, но он работает.
Скрытая функция максимальной экономии
Чтобы каждый раз не искать нужную функцию для неё возможно создать иконку на рабочий стол. Удерживайте нажатие на интересующей функции 2 секунды и появится всплывающее меню. Выберите пункт «Создать ярлык». Если приложение попросит дать ему права на создание – соглашайтесь.
Создание ярлыка для запуска скрытой функции в Activity Launcher в MIUI 11
После чего на рабочем столе появится иконка для мгновенного перехода к требуемой функции.

Релевантная информация:
  1. Где найти хранилище в MIUI 12 на Xiaomi (Redmi) и как создать его ярлык на рабочем столе
  2. Как включить максимальную экономию батареи на Xiaomi (Redmi)
  3. Как скачать и установить суперобои Марс из MIUI 12 на Xiaomi (Redmi)
  4. TWS – True Wireless Stereo Xiaomi
  5. Как включить работу поверх других приложений на Xiaomi (Redmi)

Как работает Activity. Часть 1

Мобильные операционные системы имеют свою специфику. Когда мы пользуемся смартфонами, создается впечатление, что мы находимся в одном приложении и переход между ними происходит практически незаметно. Например, мы можем из нашего приложения вызвать приложение почты, и это будет выглядеть так, будто мы встроили экран приложения почты в наше.

Вся эта магия происходит благодаря тому, что Android предоставляет фреймворк с базовыми компонентами. Мы не управляем этими компонентами, а лишь можем реагировать на колбэки, которые есть во фреймворке. Процессом приложения управляет система.

В первой части совсем немного расскажу про Binder, про то, как происходит запуск Activity, как стартует процесс приложения и как на вызов Activity влияют флаги и launch mode. Во второй части будет про то, как вызываются методы жизненного цикла Activity, что происходит при сворачивании приложения, и более подробно расскажу про старт первой Activity.

Все начинается с Binder

Binder — фреймворк для построения межпроцессной коммуникации. Сам Binder работает на уровне ядра системы. Он использует набор низкоуровневых функций ОС, позволяющих обмениваться данными между процессами так, будто у них есть общая память.

Фишка в том, что он позволяет описать интерфейсы на специальном языке AIDL, Android Interface Definition Language, — что-то вроде суперурезанной Java. А потом при помощи кодогенерации сгенерировать классы Java. Дальше вызываются сгенеренные методы Java-классов, как будто все происходит в одном процессе. На самом деле данные будут ходить между процессами

Знать про Binder нужно, чтобы разобраться во всем, что будет дальше. Про саму технологию много есть в телеграм-канале Android Easy Notes и на Хабре:

Основы безопасности операционной системы Android. Безопасность на уровне Application Framework. Binder IPC

Вступление После небольшого перерыва я продолжаю объяснять базовые принципы как обеспечивается безоп.

Система Android работает на базе ядра Linux, пусть и сильно изменившегося. Это значит, что так или иначе приложения работают в разных процессах. Мы не контролируем создание процесса приложения и управление им. Вся сложность скрывается за фреймворком, который любезно предоставляет команда Google.

Работа проходит в разных адресных пространствах, нельзя влезть в другой процесс и дернуть методы какого-то класса. Задача сложная, когда появляется много межпроцессных вызовов.

Нужен был инструмент, который позволил бы разработчикам фреймворка легко реализовывать межпроцессное взаимодействие. И разработчики Android создали Binder.

Как стартует первая Activity

Все начинается с лаунчера. Лаунчер — первое приложение, которое запускается системой. Он отличается от обычного приложения тремя вещами:

1️⃣ Главной Activity лаунчера устанавливается категория HOME, благодаря чему система будет вызывать эту Activity при нажатии на кнопку Home.

2️⃣ Всем Activity лаунчера нужно выставить флаг excludeFromRecents, чтобы они не мелькали в recents.

3️⃣ Activity лаунчера пользователь будет видеть чаще всего. То, что приложением будут пользоваться чаще всего, — сказка для эффективных менеджеров. Но цена такого успеха — когда крашится обычное приложение, пользователи пугаются и удаляют лаунчер.

Основная задача лаунчера — вывести красивый список других приложений. Получить список приложений можно несколькими путями, но самый простой — через сервис LauncherApps.

Выводим список, и при нажатии на иконку приложения нужно запустить процесс уже другого приложения либо восстановить, если приложение было свернуто.

Можно запустить Activity приложения через обычный Intent, но хороший лаунчер должен учитывать рабочий профиль. Поэтому запуск первой Activity желательно делать при помощи все того же системного сервиса LauncherApps.

launcherApps.startMainActivity( сomponentName, // название пакета приложения userHandle, // пользователь, из которого нужно запустить приложение null, // указание координат иконки нашего приложения options // bundle для всяких допнастроек типа варианта анимации )

У сервиса есть специальный метод для запуска первой Activity. Он заставляет указать пользователя, с которого нужно запустить приложение, а еще передать данные для красивой анимации запуска приложения от иконки до сплеша.

val options = ActivityOptions.makeScaleUpAnimation( view, // изображение иконки приложения 0, // старовая позиция X анимации относительно переданной иконки 0, // старовая позиция Y анимации относительно переданной иконки view.measuredWidth, // изначальная ширина будущей Activity view.measuredHeight // изначальная высота будущей Activity )

Помимо приведенной выше функции, есть еще множества других и при желании можно подсунуть свою. Как видим лаунчер может отображать запуск приложение как ему заблагорассудится.

Все дороги ведут в ActivityStarter

После запуска специального метода через ActivityManagerService приходим в ActivityStarter. По названию очевидно, что класс отвечает за старт Activity. Каждый раз, запуская Activity, мы будем приходить сюда.

ActivityStarter — интересный класс, его API отдаленно напоминает запрос из OkHttp. Очень большой билдер, через который задаются настройки, и все запускается через метод execute.

В ActivityStarter передается куча параметров, и один из них — сам Intent запускаемой Activity. ActivityStarter из этого Intent вытаскивает объект ActivityInfo — класс, который описывает все, что мы прописываем про Activity в Manifest.

class ActivityInfo( val theme: Int, val launchMode: Int, val taskAffinity: Int /*. */ )

На основании ActivityInfo создается ActivityRecord — класс, который является репрезентацией Activity. Он описывает состояние Activity и позволяет системе принимать решения о том, какой метод жизненного цикла нужно вызвать, исходя из этого состояния.

class ActivityRecord( val packageName: String, val activityInfo: ActivityInfo, val task: Task, //Task, в котором запущена (будет запущена) Activity /*. */ )

В классе больше информации, чем в ActivityInfo: например, в каком Task запущена Activity, в каком статусе жизненного цикла она находится и запущен ли вообще процесс этой Activity.

Про ActivityRecord обычно знают, если на собеседовании прилетал вопрос: «А где же хранятся ViewModel?» Это не те ActivityRecord. ViewModel хранятся в ActivityClientRecord, которые создаются только в рамках приложения, что-то вроде локальной версии ActivityRecord, о которых мы сейчас говорим.

Система напрямую не дергает методы Activity, именно о классе Activity система ничего не знает и сама их не создает. Она знает только о ActivityRecord — и уже исходя из информации, полученной из ActivityRecord, принимает решения о том, какой метод жизненного цикла нужно дернуть. Подробнее о том, как это происходит, поговорим дальше.

После того как ActivityStarter создал ActivityRecord, он пытается запустить его. Тут два варианта:

  1. Процесс уже создан, и нужно лишь отправить Activity в этот процесс.
  2. Процесса нет, и для начала нужно создать этот процесс.

Сниппет кода, как это происходит:

fun startSpecificActivity(r: ActivityRecord, andResume: Boolean, checkConfig: Boolean) < // Is this activity's application already running? val wpc = activityTaskManagerService .getProcessController(r.processName, r.info.applicationInfo.uid) /*..*/ if (wpc != null && wpc.hasThread()) < realStartActivityLocked(r, wpc, andResume, checkConfig) /*..*/ >else < /*..*/ activityTaskManagerService.startProcessAsync(r) >>

Через много вложенных методов, с проверками и настройками приходим в статический метод из класса ZygoteProcess — startViaZygote. Используем этот метод, чтобы подать сигнал Zygote о том, что нужно запустить новый процесс.

Краткое описание Zygote и fork

ZygoteInit каждый видел в стеке «вызов функций». Независимо от того, что у вас за приложение, стартовать оно всегда будет отсюда.

Зигота — термин из биологии. Это клетка, которая возникает при слиянии мужской и женской половых клеток. После определенного времени она начинает делиться, клонируя себя. Разработчики назвали этот класс не просто так, потому что, по сути, именно это и происходит каждый раз при старте приложения.

Если погрузиться в череду вызовов системных функций, то при старте системы запускается файл init.rc. В нем описано, как запускать все процессы-демоны, сервисы и остальные элементы системы.

Разработчики Android сделали систему (Android Init Language), которая при помощи специальных инструкций описывает, как именно и в каком порядке нужно запустить все системные сервисы. Этот файл различается для разных версий ОС и напоминает работу с yml-файлами при настройке CI. Там мы тоже описываем команды, а также триггеры, когда эти команды вызывать. Вот конфигурация старта zygote:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main priority -20 …

Service — специальная команда (Android Init Language), которая запускает некоторый сервис. Только это не тот сервис, который в Android Framework, а просто программа на низкоуровневом языке. В нашем примере запускается app_process.

int main(int argc, char* const argv[]) < /*. */ AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); /*. */ if (zygote) < runtime.start("com.android.internal.os.ZygoteInit", args, zygote); >else if (!className.isEmpty()) < runtime.start("com.android.internal.os.RuntimeInit", args, zygote); >else < fprintf(stderr, "Error: no class name or --zygote supplied.\n"); /*. */ >>

app_process — небольшая программа на C++, основная задача которой — запустить JVM и в частности main-функцию ZygoteInit.

С этого начинается работа Zygote. Сначала подгружаются все классы для работы JVM и все Android-зависимости, необходимые для работы

После загрузки классов запускается ZygoteServer, который запускает бесконечный цикл, и начинается самое интересное.

class ZygoteInit < fun main(argv: Array) < var zygoteServer: ZygoteServer? = null; /* Загрузка всех необходимых классов */ var caller: Runnable? = null /* . */ zygoteServer = ZygoteServer(isPrimaryZygote) // Запускаем бесконечный цикл, родительский процесс дальше не двигается // Созданные процессы будут выходить из этого цикла и идти дальше caller = zygoteServer.runSelectLoop(abiList) /* . */ // Тут мы уже находимся в новом созданном процессе и выполняем переданную команду caller.run() >>

Эта магия системного программирования, которую очень редко можно встретить в обычных проектах. Объясню на примере кода на низкоуровневом языке. C++, на мой взгляд, должен отправиться на полку истории, поэтому модно-молодежно черканем пару строк на Rust:

fn main() < let fork_result = unsafe < fork() >; match fork_result < Ok(ForkResult::Parent < child >) => < println!("I'm a parent process, pid: <>, child pid <>", process::id(), child); > Ok(ForkResult::Child) => println!("I'm a new child process, pid: <>", process::id()), Err(_) => println!("Fork failed"), >; >

В Unix есть системный вызов, который называется fork. Он берет ваш процесс, копирует все состояния переменных, потоки, стеки, хип, переносит в отдельное место в оперативной памяти и запускается как отдельный процесс.

Можно вызвать системный метод из любой точки программы. Бывает трудно разобраться в потоках, а тут вообще можно сделать программу, где после определенного вызова функции будет два процесса. Именно это и делает ZygoteServer

/*. */ val command = Os.poll() /*. */ val caller = Zygote.forkUsap(mUsapPoolSocket, sessionSocketRawFDs, isPriorityRefill) /*. */ 

ZygoteServer запускает бесконечный цикл, в этом цикле он ждет команду от системы на запуск нового процесса. Когда система дает команду на создание нового процесса, новый процесс выходит из бесконечного цикла и идет дальше, запуская ActivityThread. Изначальный процесс так и остается в бесконечном цикле в ожидании новых команд от ОС. ZygoteServer буквально живет ради детей.

Android и так не всегда быстрый, а если бы при каждом старте еще нужно было каждый раз подгружать все нужные классы, было бы совсем грустно. Поэтому разработчики придумали копировать инстанс JVM с уже загруженными классами. Отсюда и смесь кода на Java и системных вызовов. Zygote можно воспринимать как кэш с загруженными классами для любого нового процесса приложения.

Зачем нужно вообще на каждый старт приложения запускать новый процесс, почему на одной JVM все приложения не запускать?

Основная причина — безопасность. Когда приложение работает, хочется быть уверенным, что в его память никто не сможет залезть. И если мы работаем в рамках одного процесса, такой безопасности никто гарантировать не может.

Всегда есть возможность чуть-чуть подтюнить JVM под себя или сломать все. Скорее всего, вы были бы сильно недовольны, если бы ваше приложение сломалось по той причине, что другое приложение решило поиграться с настройками этой самой JVM.

Для решения этой проблемы каждое приложение запускается в отдельном процессе, и эта система называется sandbox.

Как подать сигнал Zygote для старта нового процесса ​​

ZygoteServer называется сервером не просто так, он буквально слушает сокет. Тот самый джавовский сокет, только не совсем обычный.

В Unix-системах есть Unix Domain Socket (UDS) — специальная реализация сокета, которая не использует сетевую карту и предназначена именно для передачи данных между двумя процессами на одной машине

UDS работает на базе файловой системы, если интересно узнать подробнее — прочтите статью на Википедии. Через этот сокет общаются все демоны операционной системы. Через него же и подается сигнал о том, что пора бы и новый процесс запустить.

Запуск последующих Activity

Activity запускаются в Task — это стек, в который складываются Activity при запуске. Стек фрагментов делался как копия Task, поэтому работают они примерно одинаково.

Таких Task у приложения может быть несколько. По дефолту все Activity запускаются в одном Task. Но у Activity есть специальный атрибут, который позволяет указать, в каком Task должна запускаться Activity. Этот атрибут называется taskAffinity.

Task, а в ActivityStarter есть метод, который определяет, в какой именно Task будет отправлена Activity, исходя из флага или настройки taskAffinity.

На практике этот флаг красиво использует LeakCanary. Библиотека подсовывает свои Activity таким образом, что кажется, будто вам внедрился целый кусок другого приложения. Подробнее об этом я писал в телеграм-канале.

Еще из интересного, есть атака через этот атрибут, которая называется Android Task Hijacking. Если кратко, можно сделать так, чтобы Activity нашего приложения запускалась в Task другого приложения, ну и, соответственно, можно, например, встроить рекламу ставок на спорт туда, где этого ну вообще не ожидали. Будьте аккуратнее с флагом singleTask!

Теперь обсудим launch mode. Есть четыре основных launch mode и куча различных флагов, которые мы можем передать в Intent. Разбирать, какие есть флаги, нет смысла, потому как их прямо много, а про launch mode можно отдельно прочитать тут.

Работа с ними осуществляется все в том же ActivityStarter, для этого есть отдельный метод. По факту вся работа дальше происходит только с флагами, все launch mode, которые мы указываем в манифесте, дальше превращаются во флаги. В зависимости от флага ActivityStarter настраивает, в какой Task нужно отправить Activity, нужно ли удалять предыдущие и прочее.

После того как запустилась наша первая Activity, последующие Activity мы открываем через интенты, которые отправляем уже сами.

Когда мы хотим показать новую Activity, мы вызываем startActivity. Но он не сразу идет в системный сервис, а сначала вызывает метод mInstrumentation.execStartActivity.

Класс Instrumentation в основном используется в тестах, по сути своей это hook, который позволяет перехватить методы показа Activity и еще много чего.

В обычной реализации execStartActivity передает вызов в ActivityTaskManagerService, который отправляет вызов в уже известный нам ActivityStarter. Как видите, нет особой разницы, запускаем ли мы сами Activity или ее запускает система.

Однажды я встретил вопрос: «Для чего нужно обозначать наши Activity в манифесте? Скажем, вот пример с BroadcastReceiver, мы можем его назначить динамически, можно ли так сделать с Activity?»

Ответ на этот вопрос кроется в логике работы ActivityStarter. Как он может узнать о том, как ему запускать Activity, если приложение еще ни разу не было запущено? ActivityStarter получает данные о том, какую Activity ему нужно запустить и как именно ее нужно запустить, из PackageManager.

PackageManager получает все эти данные из манифеста при установке приложения. Системе нужно знать об Activity не только тогда, когда приложение запущено, но и тогда, когда приложения еще нет в памяти и ни разу не было.

Кроме этого, у нас есть возможность расшарить нашу функциональность другим приложениям, которые будут запускать наши Activity, причем не только главную, но еще и в разных Task.

Вместо заключения

В статье я описал лишь функциональность, которая относится к запуску Activity и приложения, и это лишь бесконечно малая часто того, что делает система. Но уже на этом примере прослеживаются интересные архитектурные паттерны, которые использует Android внутри себя.

Очень многое сделано на базе клиент-серверной архитектуры, в которой запрос отправляется при помощи Binder. Вы наверняка часто встречали, что при помощи метода getSystemService мы почему-то получаем какой-то Manager. Самый банальный пример:

val connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager

И вот, если вдуматься в синтаксис, абсурд же происходит! Вроде достаем сервис, а получаем менеджер. Просто нужно понимать, что этот Manager — это клиент для работы с каким-то системным сервисом.

Системный сервис чем-то похож на привычный нам сервис, только работает он всегда и в другом отдельном процессе.

Manager — это клиент, Service — сервер. Такая архитектура позволяет как угодно менять Service, делать его вложенным классом, затаскивать в другое место — не имеет никакого значения. Главное, что, если не меняется интерфейс AIDL, клиент также не будет меняться.

Эта же концепция действует и при работе с Activity. Мы просто отправляем запрос в приложение посредством Binder, а приложение уже само решает, как именно ему нужно показать Activity.

Если вам понравилась статья и иллюстрации к ней, подписывайтесь на мой телеграм-канал. Я пишу про Android-разработку и Computer Science, на канале есть больше интересных постов про разработку под Android. А еще залетайте на наш ютуб с подборкой про Android и слушайте подкаст «Кем ты стал» о том, как превратить работу в личный бренд.

  • android
  • android internals
  • мобильная разработка
  • android sdk
  • android os
  • Блог компании TINKOFF
  • Разработка под Android

Как просто перенести приложения в MIUI 10 на карту памяти Xiaomi

Перенос приложений на карту памяти в Xiaomi

Без лишних слов поговорим о том, как решить проблему многих пользователей Xiaomi и MIUI 10 и перенести приложения на карту памяти из внутренней.

Дело в том, что ОС китайских разработчиков крайне неэкономично относится к расходованию внутренней памяти устройства. Из-за этого она быстро забивается, а пользователь смартфона начинает регулярно получать соответствующие уведомления о нехватке свободного пространства.

Приступаем к работе

Память андроид смартфона

Нам нужен смартфон, работающий на MIUI 10, так как описываемые ниже шаги сработают только на этой версии оболочки, а на MIUI 9 приведут к краху и вылету приложения “Настройки хранилища”. Версия Android не играет абсолютно никакой роли. Способ не требует наличия root-прав, стороннего рекавери и т.д. Все действия выполняются встроенными средствами мобильной ОС.

Внимание! Перед началом выполнения всех описанных шагов все данные с карты памяти необходимо скопировать на компьютер, ноутбук, выгрузить в облако. Словом, нужно сохранить в безопасное место все данные, хранящиеся на MicroSD, так как они полностью и безвозвратно удалятся.

Шаг 1

Находим приложение “Activity launcher” в Google Play и устанавливаем его. Для противников софта от Google приложение разместили на форуме 4pda под названием «Активатор приложений».

Activity launcher

Шаг 2

Запускаем установленное приложение. На первом экране видим список последних действий в системе. Он нам не интересен, нам нужно выпадающее меню в верхней части экрана, где сейчас фигурирует надпись “Последние действия”. Нажимаем и выбираем “Все действия”.

Последние действия

Шаг 3

Ждем, пока телефон обработает список всех установленных приложений.

Шаг 4

После этого, ищем пункт “Документы”. Стоит заметить, что в некоторых прошивках сторонних локализаторов (например, miuiPro) этот пункт называется “Файлы”.

Нажимаем на него, и в раскрывшемся списке нас интересует пункт “Загрузки” с именем пакета com.android.documentsui.LauncherActivity.

Пункт документы

Шаг 5

Запускаем “Загрузки” (com.android.documentsui.LauncherActivity). Если условия соблюдаются, у вас версия MIUI 10, а не MIUI 9, то запустится приложение “Загрузки”, отличающееся от привычного. Там нас интересует пункт “SD-карта”.

SD карта

Шаг 6

Выбираем пункт “SD-карта”, а в открывшемся окне нажимаем на три точки в правом верхнем углу и выбираем пункт “Память”. В некоторых локализациях этот пункт может называется “Настройки памяти” или “Настройки”. Открывается окно “Настройки хранилища”.

Память

Шаг 7

В окне “Настройки хранилища” выбираем пункт “Внутренняя память”.

Внутренняя память

Шаг 8

В окне “Внутренняя память” отобразится сообщение о том, что перед переносом приложений нужно отформатировать флешку. Выбираем пункт “Очистить и отформатировать” и ждем завершения процедуры.

Отформатировать карту памяти

Шаг 9 – Финальный

На этом подготовка к переносу приложений завершена, а ваш телефон получил возможность освободить забившуюся внутреннюю память.

Теперь для переноса приложения на MicroSD достаточно выполнить следующие действия:

  1. Перейти по пути Настройки/Все приложения.
  2. Выбрать приложение или игру, занимающую много места и нажать на нее.
  3. В появившемся меню выбрать пункт “Хранилище”.
  4. В пункте “Хранилище” выбрать, где будут храниться данные приложения: “Внутренняя память” или “Внешняя память” (“Карта памяти”, “Внешний накопитель”).

На этом все. Надеюсь, статья оказалась полезной.

  • Как перенести музыку на карту памяти?
  • Как перенести фото и видео с телефона на карту памяти?
  • Как переместить файлы с внутренней памяти Android на карту памяти
  • Перенос приложений на карту памяти в Android
  • Как удалить игры и ненужные приложения с телефона?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *