- Как Android запускает MainActivity
- Что происходит при запуске приложения
- 1 Схема запуска приложения
- 2. Класс ActivityThread
- 2.1 Подготовка main looper (Process 2–3)
- 2.2 Вызов Handler’a (Process 4-5)
- 2.3 Вызов метод loop() у Looper’а (Process 6–7)
- 3. Бесконечный loop() в Looper’е (Process 7,8,9)
- 4. Запуск MainActivity (Process 10 to 15)
- Отрисовка первого кадра Android-приложения
- Старт главного потока
- Планируем запуск Activity
- Фактический запуск Activity
- Первый кадр
- Заключение
- Русские Блоги
- Анализ исходного кода основного потока Android (ActivityThread)
Как Android запускает MainActivity
Недавно я провел исследование о main() методе в Java и то, как он служит точкой входа для любого приложения Java. Это заставило меня задуматься, а как насчет Android-приложений? Есть ли у них основной метод? Как они загружаются? Что происходит за кулисами до выполнения onCreate()? Майкл Бэйли очень подробно рассказал о том, как работает Main Thread, так что это быстрый обзор его доклада плюс дополнительная информация из Android Open Source Project (AOSP).
В этой статье мы рассмотрим:
- Что происходит от нажатия на иконку приложения до запуска MainActivity
- Найдем основной метод приложения и узнаем, как основной поток (он же UI, он же Main Thread) получает свое назначение.
- Рассмотрим роль, которую играют Looper & Handler в передаче сообщений, которые в конечном итоге приводят к созданию вашей Activity.
Что происходит при запуске приложения
1 Схема запуска приложения
Между вызовом метода main() и onCreate() в нашем MainActivity примерно 15 шагов, и в этой статье мы пройдем по ним. На рисунке 1 изображена общая схема запуска приложения, показывающая различные классы взаимодействия сверху и соответствующую цепочку методов. Шаги пронумерованы, и когда я обращаюсь к ним, я буду использовать следующие обозначения Process3 или Process14
Рисунок 1: Схема запуска приложения по шагам от вызова main() до onCreate() в MainActivity
2. Класс ActivityThread
В классе ActivityThread чуть более 6500 строк. Для краткости я определил самые важные для нас части. Давайте рассмотрим, что делает этот класс и связанный с ним основной метод, чтобы запустить нашу Activity
Рисунок 2: Метод main() в ActivityThread, который служит точкой входа для запуска вашего приложения.
Как видно в коде: метод main() выполняет три важных дела:
1. Подготавливает основной Looper (MainLooper) (Process 2)
2. Настройка Handler’a (Process 4)
3. Вызов метода Looper.loop() в главном потоке (MainThread) (Process 6)
2.1 Подготовка main looper (Process 2–3)
Основной Looper задается вызовом Looper.prepareMainLooper() (см. Строку 8 в коде). Это отмечает текущий случайный поток, который выполняет всю работу по вызову метода main() в качестве основного потока приложений. Именно так и именно здесь определяется знаменитый главный поток для приложения в Android!
2.2 Вызов Handler’a (Process 4-5)
Внутри класса ActivityThread существует приватный внутренний класс H, да-да, все верно, просто H, который наследуется от класса Handler (см. рис. 4 и 7). В 12й строке экземпляр H-обработчика устанавливается как главный Handler потока. Что очень интересно знать о классе H, как вы сами увидите позже, это то, что он содержит более 50 определений состояния/событий, в которых может находиться ваше приложение, например LAUNCH_ACTIVITY, PAUSE_ACTIVITY, BIND_SERVICE и т.д.
2.3 Вызов метод loop() у Looper’а (Process 6–7)
После назначения главного потока в этом же главном потоке, для того чтоб мы могли в нем что-то выполнять, вызывается метод Looper.loop() (см. Строку 20). Это начинает выполнение сообщений в очереди сообщений Loopers. Теперь главный поток запущен и может начать обработку задач из очереди.
Обратите внимание, что в строке 18, если выполнение кода пойдет дальше чем Looper.loop() в 17 строке вдруг и приложение выйдет из цикла, то будет брошено исключение RuntimeException. Это говорит о том, что метод loop() в идеале никогда преждевременно не заканчивается. Мы увидим как это в следущем разделе.
3. Бесконечный loop() в Looper’е (Process 7,8,9)
Рисунок 3: Код внутри метода loop() в классе Looper’e
Как мы видим в коде, в методе Looper.loop() есть очередь сообщений (строка 10) и внутри цикла вызывается queue.next(). MessageQueue заполняется Handler-‘ом, о котором мы говорили в предыдущем разделе (см. Process 8). Обратите внимание на интересное описание условия в цикле for — здесь нет аргументов, только две точки с запятой говорят что это бесконечный цикл. Поэтому Looper в идеале никогда не заканчивается, если данное сообщение не null.
Итак, теперь мы определили главный поток, выполняемый благодаря Looper, мы также видели, что Handler добавляет сообщения в цикл Looper.loops() и обрабатывает сообщения. Давайте посмотрим, как они вместе вызывают нашу Activity.
4. Запуск MainActivity (Process 10 to 15)
Важно помнить, что этот бесконечный цикл и обработка сообщений выполнялись в main() методе класса ActivityThread, потому что именно там они были вызваны (см. в коде строки с 12 по 17). Мы поверхностно просмотрели Loopers, MessageQueues и Handlers, чтобы вникнуть в контекст. Итак, давайте вернемся к классу ActivityThread, в частности, к внутреннему классу H, о котором мы говорили ранее, который действует как основной Handler главного потока.
Итак, у нас есть Looper, передающий сообщения нашему Handler’у, давайте узнаем, как эти сообщения обрабатываются. Это делается внутри класса H. Этот класс содержит метод handleMessage(Message msg). Помните, что все классы, которые наследуются от Handler, должны переопределить этот метод.
Рисунок 4: Приватный внутренний класс H и его handleMessage() метод
Как видно в коде, в 8й строке есть оператор switch, в котором определяется обработка входящего сообщения по его содержимому.
Один из случаев (cases) включает в себя запуск активности (строка 11), что интересно, так это то, что этот метод предназначен для обработки около 50 случаев, которые варьируются от возобновления, приостановки, запуска Activity, привязки Service’ов, обработки Receiver’ов, предоставления предупреждений lowMemory или trimMemory, когда память устройства заполняется и т. д.
В case LAUNCH_ACTIVITY вызывается метод handleLaunchActivity(), как показано в строке 13, см Process11 на схеме. Затем этот метод вызывает другой метод, называемый performLaunchActivity(), который возвращает объект Activity (см. Рис. 5, строка 7).
Рисунок 5: Метод handleLaunchActivity() в котором создается Activity
Метод performLaunchActivity() добавляет в Activity важную информацию, такую как Instrumentation, Context, Component, а также Intent; а также задает Application. Затем этот метод вызывает Instrumentation.callActivityOnCreate() (Process 13), который является последним этапом перед вызовом метода onCreate() в Activity (Process 14-15, см. Рисунок 5 (код), строки 8-10).
Рисунок 6: Класс Instrumentation наконец запускает Activity
На данный момент ваша Activity загружена c множеством полезных переменных и методов, которые можно использовать для создания вашего нового удивительного приложения для Android! Все это благодаря ActivityThread, умной работе Handler’a и Looper’a, и огромному классу Activity в 7600 строк кода, который позволяет аттачить фрагменты, получить контекст и легко управлять View’s — и много еще чего.
Источник
Отрисовка первого кадра Android-приложения
Всем приветЪ! Этот пост является продолжением поста про глубокое погружение в процесс загрузки-запуска Android-приложения. Сегодня мы пойдем чуть дальше и обсудим момент когда главная Activity приложения запущена и система должна отрисовать первый кадр. Прошу под кат.
Следуя официальной документации запущенный процесс приложения отвечает за выполнение следующих шагов:
- Создание объекта класса Application.
- Запуск основного потока(MainThread aka UiThread).
- Создание стартового Activity, который указан в манифесте.
- Расширение(раздутие, inflating) вьюшек. То есть создание вьюшек, которые прописаны в xml-файле.
- Планировка размеров(View.measure()) и размещения(View.layout()) вьюшек на экране.
- Выполнение начальной отрисовки.
После того как был отрисован первый кадр, системный процесс заменяет отображаемое фоновое окно, заменяя его на Activity приложения. Теперь пользователь может взаимодействовать с приложением.
А теперь давайте поподробнее обо всех шагах.
Старт главного потока
В предыдущем посте мы узнали:
- Когда запускается процесс приложения, он вызывает метод ActivityThread.main(), который делает блокирующий IPC-запрос к методу ActivityManagerService.attachApplication() в процессе system_server.
- system_server делает IPC-вызов в процессе приложения метода ActivityThread.bindApplication(), который ставит в очередь сообщение BIND_APPLICATION в MessageQueue главного потока.
- Когда IPC-вызов метода ActivityManagerService.attachApplication() завершен, ActivityThread.main() вызывает Looper.loop(), который будет зациклен навсегда(пока приложение работает) и будет обрабатывать сообщения поступающие в MessageQueue.
- Первое сообщение, которое будет обработано это BIND_APPLICATION. В этот момент будет вызван метод ActivityThread.handleBindApplication(), который загрузит APK и другие компоненты приложения.
Важный момент: ничего не происходит в главном потоке процесса приложения пока не выполнится IPC-вызов метода ActivityManagerService.attachApplication().
Планируем запуск Activity
Давайте посмотрим что происходит в процессе system_server после вызова метода ActivityThread.bindApplication():
Строка которая релевантна запуску Activity — mAtmInternal.attachApplication(. ). Метод вызывает ActivityTaskManagerService.attachApplication(), который в свою очередь вызывает метод RootActivityContainer.attachApplication():
Код делает следующее:
- Обходит каждый дисплей.
- Получает стек сфокусированных Activity для этого дисплея.
- Проходит по каждому Activity целевого стека Activity.
- Если Activity принадлежит к запущенному процессу, то вызывается метод ActivityStackSupervisor.realStartActivityLocked(). Обратите внимание, что параметр andResume будет иметь значение true если Activity находится на вершине стэка.
Вот как выглядит метод ActivityStackSupervisor.realStartActivityLocked():
Все вызовы методов, которые мы просмотрели происходят в системном процессе system_server. Метод ClientLifecycleManager.scheduleTransaction() делает IPC-вызов ActivityThread.scheduleTransaction() в процессе приложения, который вызывает ClientTransactionHandler.scheduleTransaction(), чтобы положить в очередь сообщение EXECUTE_TRANSACTION:
При обработке сообщения EXECUTE_TRANSACTION происходит вызов метода TransactionExecutor.execute().
Теперь можно обновить диаграмму:
Фактический запуск Activity
Метод TransactionExecutor.execute() вызывает TransactionExecutor.
performLifecycleSequence(), который в свою очередь делает коллбэк в ActivityThread для создания(create), запуска(start) и продолжения(resume) Activity:
Первый кадр
Давайте взглянем на последовательность вызовов методов, которые ведут к отрисовке первого кадра:
- ActivityThread.handleResumeActivity()
- WindowManagerImpl.addView()
- WindowManagerGlobal.addView()
- ViewRootImpl.setView()
- ViewRootImpl.requestLayout()
- ViewRootImpl.scheduleTraversals()
- Choreographer.postCallback()
- Choreographer.scheduleFrameLocked()
Метод Choreographer.scheduleFrameLocked() ставит в очередь сообщение MSG_DO_FRAME:
При обработке сообщения MSG_DO_FRAME происходит вызов метода Choreographer.doFrame(), который в свою очередь вызывает ViewRootImpl.doTraversal(), который осуществляет проходы measure pass и layout pass, и наконец проход the first draw pass по иерархии вьюшек:
Заключение
Мы начали с высокого уровня понимания того, что происходит, когда система создает процесс приложения:
Теперь мы знаем что именно происходит «под капотом»:
А теперь давайте соединим диаграммы из предыдущего поста, с того момента когда пользователь тапает на иконку приложения до момента отрисовки первого кадра:
Теперь, когда у нас есть полная картина, мы можем начать разбираться в том, как правильно контролировать холодный запуск. Следующий пост будет именно об этом! До встречи.
Источник
Русские Блоги
Анализ исходного кода основного потока Android (ActivityThread)
Прежде чем писать этот блог, давайте зададимся вопросом, что является входом в приложение Android? Я думаю, что многие люди могут ответить, что метод приложения onCreate не соответствует действительности. Даже для приложения есть метод, который выполняется перед onCreate. Этот метод является методом attachBaseContext (Context context): в обычных условиях вы можете использовать этот метод в Внедрение мультидексных подпакетов, такое как следующий код:
Конечно, это пример, иллюстрирующий роль этого метода. Этот метод является методом, который будет выполняться сразу после инициализации приложения, после чего следует метод onCreate. Конечно, приложение не является входом в программу Android. Приложение Android используется в качестве управляющей программы. Java-программы похожи, у всех есть вход, и этот вход — ActivityThread, ActiviyThread также имеет основной метод, этот основной метод — реальный вход приложений Android, ниже я подробно проанализирую ActivityThread и некоторые нетрадиционные методы некоторых проблем, сравнение статей Долго, пожалуйста, найдите время, чтобы посмотреть медленно, я думаю, у вас будет новое понимание основной темы Android после прочтения.
Прежде всего, какова роль ActivityThread? ActivityThread имеет много функций, но основная функция заключается в планировании и выполнении операций, широковещательных и других операций в соответствии с AMS (требования ActivityManagerService, через интерфейс IApplicationTHread). В системе Android все четыре основных компонента по умолчанию работают в главном потоке. В следующем анализе кода вы увидите управление этими компонентами.
Во-первых, основной код входа ActivityThread выглядит следующим образом:
Приведенный выше код — всего лишь несколько предложений, но вы можете увидеть важную роль ActivityThread, взаимодействовать с AMS и управлять Activity и Service, а затем задать практический вопрос, как узнать, какие страницы пользователи посетили в приложении? Конечно, есть много способов, но с помощью приведенного выше кода, возможно, вы считаете разумным найти поле mActivities.Да, поскольку в этом поле хранятся все объекты Activity, вы можете узнать, получите ли вы значение этого поля. Какие действия ушли, и эти действия остаются у пользователя, это тоже решение.
ActivityClientRecord является внутренним классом ActivityThread. Этот ActivityClientRecord является знаком, переданным в AMS. Он несет много информации. Приведенный выше код можно увидеть. В нем есть объект Activity. Activity внутри является реальным экземпляром Activity. Или он может знать, на какие страницы переходят пользователи, конечно, это может быть более громоздким, но этот метод осуществим.
Далее основное внимание уделяется анализу ApplicationThread, прежде всего, это не поток, а объект Binder,
Видя это, я думаю, что любой, кто знаком с механизмом Binder, знает, что происходит, да, ApplicationThread становится прокси-объектом ApplicationThreadProxy после упаковки, может быть, вы спросите, откуда вы знаете, что это ApplicationThreadProxy, фактически отладьте его Как вы знаете, вот картинка
Вы видите красное поле, IApplictionThread — это объект ApplicationThreadProxy в AMS, хе-хе
Затем передайте его в AMS, и у AMS будет этот объект, вы можете вызвать метод внутри, schedulePauseActivity. Этот метод — это действие, которое приостановлено и выполнено и показывает взаимодействие между ActivityThread и AMS. Это вызов IPC. Конечно, это должно быть понятно здесь. AMS вызывает ActivityThread через объект ApplicationThreadProxy, а метод вызова ActivityThread AMS — это ActivityManagerProxy. Это также вызов процесса IPC. В конце будет более подробный код. Хорошо, теперь Вы должны понимать, что AMS вызывает метод ActivityThread через объект ApplicationThreadProxy.Внутри методы обычно являются началом расписания, например scheduleDestroyActivity, scheduleReceiver и т. Д. Одна из проблем заключается в том, что первый метод, выполняемый после приостановки Activity, — schedulePauseActivity, а затем распространяемый через сообщение Механизм вызывает метод handlePauseActivity-> executePauseActivity-> callActivityOnPause-> Activity.onPause (), что означает, что метод жизненного цикла внутри Activity на самом деле вызывается позже, по расписанию AMS, и выполняется ActivityThread, Деятельность по себе.
Затем проанализируйте очень важный механизм распределения сообщений в Android в процессе вызова ActivityThread. Механизм распределения сообщений занимает очень важное место во всей системе Android. Система Android также использует механизм распространения сообщений для реализации работы системы. Механизм распределения сообщений Это также необходимый пункт знаний в интервью Android. В ActivityThread H наследует класс Handler. Ниже приведены некоторые переменные:
Можно видеть, что константы внутри представляют значение какой конкретной операции. Конечно, у других операций также есть соответствующие, которые не перечислены один за другим, и затем переписывается метод handMessage. Ниже приведен код:
Конечно, остальные обрабатываются таким образом, а не перечислены один за другим. Вы видели, что LAUNCH_ACTIVITY имеет дело с запуском Activity, а затем вызывает метод handleLaunchActivity, а handleLaunchActivity вызывает метод для создания Activity executeLaunchActivity,
Вы видели, что Activity на самом деле является общим Java-объектом, созданным с использованием отражения, а затем загруженным в него с помощью ClassLoader, а затем вызванным уровнем инфраструктуры, который имеет жизненный цикл и становится компонентом, так что вы также можете знать, что он подключен В этом случае невозможно загрузить Activity, но она должна быть передана на уровень структуры, чтобы иметь жизнеспособность, иначе это бессмысленно, конечно, не только Activity, фактически Service, BroadCase и т. Д. Создаются путем отражения таким образом, а затем загружаются инфраструктурой Вызов уровня без исключения
Видели ли вы, что после создания Activity она вызовет привязку метода присоединения, а затем определит, следует ли установить тему, если да, установите тему, а затем вызовите callActivityOnCreate mInstrumentation, здесь фактически вызывается метод onCreate Activity, создание Activity также Создано Instrumentation. Описание Инструментов смотрите в моей предыдущей статье:
В этот момент вызывается onCreate,
Вы можете видеть выше, что после выполнения метода onCreate выполните метод onStart, а затем выполните метод onPostOnCreate
Возвращаясь к описанному выше вызову метода handleLaunchActivity, после выполнения методов onCreate Activity, onStart, пришли к
метод handleResumeActivity,
Вы видели, что при выполнении onResume он на самом деле невидим в то время, и на самом деле он не виден до тех пор, пока условие r.activity.mVisibleFromClient не станет истинным, и мы также можем видеть из кода, что Activity добавляется View Это просто окно, поэтому Activity по сути является просто окном. На этом этапе Activity действительно видна пользователю. Вы можете видеть, что описанный выше стек вызовов фактически реализуется механизмом распределения сообщений обработчика, шаг за шагом, через IPC для связи с AMS. Считаете ли вы, что система Android широка и глубока? Я думаю, что именно из-за существования механизма Binder Android вызывает удаленные процессы, такие как вызовы локальных процессов. Это бесплатно, чтобы идти вперед и назад, и я должен восхищаться программистами Google, которые обычно существуют. Я не знаю, если вы Как насчет этой идеи? Конечно, вызовы к другим сообщениям распределения обработчика одинаковы. Читатели могут самостоятельно анализировать вызовы других сообщений. Фактически, все жизненные циклы Activity, включая вызовы других компонентов, отвечают за распределение вызовов.
- Приведенные выше четыре метода на самом деле очень полезны, они используются в некоторых особых случаях. Эти методы будут вызваны в следующих вопросах.
Давайте проанализируем вызов Broadcast в ActivityThread. Конечно, трансляция такая же. Сначала она вызывается в AMS через IPC, а затем отправляется AMS и возвращается в ActivityThread. Ниже приведен код:
Как видно из вышесказанного, сущность широковещания та же, что и Activity, которая создается с помощью отражения. Единственное отличие состоит в том, что Activity нужно вызывать на уровне структуры и имеет метод жизненного цикла, в то время как широковещание не имеет концепции жизненного метода, просто вызовите метод onReceive Поэтому, по сравнению с Activity, вещание легче понять. Давайте оставим здесь вопрос. Почему вещание может вызываться между процессами, а EventBus, OTTO и другие шины событий не могут? На самом деле, фундаментальная причина заключается в том, что вещание управляется процессами системы AMS. Процесс отвечает только за выполнение, и обработка EventBus, OTTO и этих шин событий строится между одним и тем же процессом, поэтому они не могут отправлять сообщения между процессами, но широковещание возможно. Конечно, AMS сложнее обрабатывать широковещание. Сегодня Пока не обсуждается.
Давайте проанализируем обработку Сервиса в ActivityThread, код выглядит следующим образом:
Видно, что обработка Сервиса не сильно отличается от предыдущей трансляции. Все они создаются путем отражения, а затем метод обратного вызова, конечно, является последним оставленным ContentProcider. Фактически, эта вещь также создается путем отражения. Конечно, процесс ContentProcider является более сложным.
Можно видеть, что четыре основных компонента создаются путем отражения и выполнения метода жизненного цикла, а планирование выполняется AMS, а основной поток ActivityThread отвечает за выполнение, поэтому AMS является планировщиком, а основной поток — исполнителем, как в компании, Это совет директоров, а ActivityThread — генеральный директор, отвечающий за выполнение конкретных задач и отчетность перед AMS, резервное копирование AMS, чтобы можно было проверить случай.
Хорошо, вышеупомянутое является основной обязанностью ActivityThread. Конечно, процесс остановки и уничтожения Activity аналогичен запуску Activity. Это вызов процесса IPC с AMS. Рабочий процесс ActivityThread приведен ниже (AMS вызывает метод ActivityThread ):
Вот как AMS вызывает ActivityThread. Конечно, ActivityThread вызывает AMS почти так же, но объект заменяется объектом ActivityManagerProxy.
Наконец, в особых случаях есть несколько нетрадиционных методов. Если вам интересно, вы можете посмотреть:
1. В любое время, в любом месте, любая логика, как получить глобальный объект приложения
Для этой проблемы, возможно, многие скажут: определить метод в пользовательском приложении, а затем присвоить значение в onCreate, чтобы вы могли получить его, да, большинство людей Это сделано, и кажется, что оно никогда не пропускалось. Да, этот метод в настоящее время используется большинством людей. Однако этот метод на самом деле ограничен. Конечно, в обычной разработке проблем нет. Однако, если вы не можете прикоснуться к самой логике программы (в особом случае обратного и т. Д.), То вышеприведенный метод недопустим, тогда нет способа сделать это, нет, приведенный выше код однажды сказал, что есть метод :
- Видно, что его можно получить, но ActivityThread является скрытым классом, так что, что делать, рефлексия, следующий код:
Результаты следующие:
Вы видите, что он был успешно получен, и проблема решена!
2. Как получить экземпляр Activity
Некоторые люди могут сказать, что невозможно получить объект getApplication, этот метод получает объект контекста, а не экземпляр реального действия, поэтому как его получить, вот один из методов:
Сначала определите переменную Activity в базовом классе, а затем присвойте значение определенному подклассу в onCreate, чтобы подкласс получил экземпляр Activity.
Этот метод является самым простым и обычно используемым.
Второй метод: используйте метод мониторинга жизненного цикла приложения ActivityLifecycleCallbacks, ниже приведен конкретный код:
Хорошо, я также успешно получил текущий экземпляр ActivityThread.
Третий метод:
Когда мы только что посмотрели на исходный код ActivityThread, мы обнаружили, что есть такой метод:
Вы не ошиблись, есть также метод для непосредственного получения экземпляра Activity, но ошеломленный, параметр должен иметь тип IBinder, который является единственным признаком идентификации активности, так как получить этот IBinder? Что ж, я думаю, что в Казахстане, когда активность началась, мы сказали, что при выполнении onResume он будет сообщен AMS, метод — ActivityResumed, а параметр этого метода просто имеет тип IBinder, этот параметр представляет текущий Ток Activity, если у вас есть этот токен, можете ли вы вызвать приведенный выше код для получения Activity, но AMS выполняет метод activityResumed, но AMS работает в системном процессе, что мне делать? Тогда давайте будем более жестокими. Мы напрямую подключили AMS. Когда мы сказали, что ActivityThread вызывает метод AMS, он также использует механизм Binder. В частности, он использует объект агента с именем ActivitymanagerProxy для вызова, и этот класс — ActivityManagerNative. Подкласс ActivityManagerService является прокси-объектом в локальном процессе (я лично считаю, что механизм Binder хорошо понят на уровне Java, просто нужно помнить, что разные процессы используют для работы прокси-объект другой стороны), слушать Поймите, давайте посмотрим на код ниже:
Нам просто нужно заменить его собственным прокси-объектом для работы, а затем перехватить его в методе activityResumed. Хорошо, просто сделайте это,
IActivityManagerServiceHandler реализует классоподобный динамический прокси-интерфейс InvocationHandler, в котором он перехватывает метод activityResumed. После его перехвата получите токен, а затем вызовите метод отражения, чтобы получить экземпляр Activity. Ниже приведен конкретный код, который является относительно простым.
Затем просто вставьте его в приложение. Хорошо, давайте распечатаем его ниже,
Вы видите, что это удалось, да, да, каково это обманывать систему, кстати, основная идея плагина 360 заключается в том, чтобы спрятаться от неба и обмануть систему, перевернув систему Понимая бесперебойность системы плагинов, конечно, необходимо иметь дело с некоторыми проблемами совместимости. Хорошо, вышеупомянутая проблема также была решена.
3. Есть ли способ помешать активации Activity или других процессов? Нет способа сделать это условно, потому что это планирование уровня структуры. Когда вызывается метод жизненного цикла Activity, на самом деле очень поздно, и нет пути идти дальше. Операция, то есть невозможно вмешиваться в это поведение на прикладном уровне. Конечно, вы можете прервать процесс на полпути при планировании на уровне инфраструктуры. Подробности см. В моей предыдущей статье. :
4. Есть ли способ вызвать всплывающее окно при запуске действия или выполнить другие действия, то есть всплывающее окно или другие действия при запуске метода LaunchActivity?
Сумма, при нормальных обстоятельствах, нет никакой возможности, некоторые люди скажут, что я выскочил в onCreate, хе-хе, это нарушает мое условие, когда LaunchActivity находится в AMS для ActivityThread Отправляя сообщения, чтобы что-то сделать при запуске Activiy, мы все знаем, что этот процесс реализован обработчиком, отправляющим сообщения, но код для обработки сообщений через обработчик на самом деле в порядке, ниже приведен код обработчика для обработки сообщений:
Вы видели, что когда обработчик обрабатывает сообщение, сначала проверьте, реализован ли интерфейс обратного вызова, если он реализован, то метод интерфейса будет выполнен напрямую, затем метод handleMessage и, наконец, переписанный метод handleMessage, мы обычно В большинстве случаев метод handleMessage переписывается, и основной поток ActivityThread использует переписанный метод. Этот метод имеет самый низкий приоритет. Мы можем полностью реализовать интерфейс для замены процедуры обработки системного обработчика. Посмотрите на код:
Конечно, есть также класс CustomHandler, который реализует интерфейс Callback и может также перехватывать методы
После написания просто вставьте его в приложение. Хорошо, вы можете проверить его, чтобы увидеть, будет ли строка привет, я собираюсь запускаться каждый раз при запуске Activity.
Конечно, в дополнение к этим относительно особым проблемам, иногда, особенно когда плагин, часто сталкивается с этой проблемой, эти проблемы часто невозможно перехватить на прикладном уровне, потому что когда достигается прикладной уровень, вызывается цепочка вызовов Нет возможности вмешаться. В настоящее время вы можете рассмотреть эти специальные методы. Конечно, в процессе разработки, какой из них является самым быстрым для решения проблемы?
Я напишу это здесь сегодня. Уровень младшего брата ограничен. Пожалуйста, укажите недостатки. Спасибо за чтение.
Источник