Как не дать холодному запуску Android приложения отпугнуть пользователей

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

Какие виды запуска приложения существуют

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

Холодный старт

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

Холодный запуск приложения.

Когда пользователь нажимает значок приложения,
событие click переводится в startActivity(intent) и направляется в ActivityManagerServiceчерез Binder IPC, а ActivityManagerService выполняет несколько шагов:

Диаграмма с событиями, когда происходит запуск приложения.
Диаграмма сделана с помощью Figma
  1. Первым шагом является сбор информации о цели объекта намерения. Это делается с помощью метода resolveIntent()для объекта PackageManager. Флаги PackageManager.MATCH_DEFAULT_ONLY и PackageManager.GET_SHARED_LIBRARY_FILES используются по умолчанию.
  2. Целевая информация сохраняется обратно в объект intent, чтобы избежать повторного выполнения этого шага.
  3. Следующий важный шаг – проверить, достаточно ли у пользователя привилегий для вызова целевого компонента intent. Это делается путем вызова метода grantUriPermissionLocked().
  4. Если у пользователя достаточно разрешений, ActivityManagerService проверяет, требуется ли целевое действие для запуска в новой задаче. Создание задачи зависит от intent флагов, таких как FLAG_ACTIVITY_NEW_TASK и FLAG_ACTIVITY_CLEAR_TOP.
  5. Теперь пришло время проверить, существует ли уже запись процесса для этого процесса. Если ProcessRecord имеет значение null, ActivityManager должен создать новый процесс для создания экземпляра целевого компонента.

Горячий старт

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

Горячий старт приложения.

Если пользователь возвращает действие с экрана «Недавние» вместо нажатия значка средства запуска, то процесс вызывает TaskSnapshotSurface.create() для создания начального окна, в котором отображается сохраненный снимок действия.

Однако если некоторая память была очищена в ответ на события обрезки памяти, такие как onTrimMemory(), то эти объекты необходимо будет воссоздать в ответ на событие горячего запуска.

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

Как сделать холодный запуск более приятным и не допустить плохой юзер экспириенс?

Каждый пользователь при взаимодействии с приложением ожидает как можно скорее иметь доступ к контенту, и этот “стартовый” контент можно отобразить с заполнителем или же добавить логотип приложения.

Итак , для того чтобы создать свой заполнитель , необходимо создать xml файл в папке drawable и добавить нужные цвета:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

<gradient
android:angle="45"
android:endColor="#87CEEB"
android:centerColor="#768087"
android:startColor="#000"
android:type="linear" />

</shape>

Далее заполнитель необходимо задать в теме приложения (values >themes.xml section) :

<item name="android:windowBackground">@drawable/bg_splash</item>

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

<activity android:name=".SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

В качестве контента можно передать логотип приложения и заполнитель, который добавляли для стартового окна:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_splash"
tools:context=".SplashActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/rokkitt_bold"
android:text="@string/example_app"
android:textColor="@android:color/white"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

В самом активити необходимо обернуть Intent в Handler, который по истечении заданного времени открывает экран взаимодействия:

class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)

Handler(Looper.getMainLooper()).postDelayed({
/* Create an Intent that will start the MainActivity. */
val mainIntent = Intent(this, MainActivity::class.java)
startActivity(mainIntent)
finish()
}, 800)

И наконец, не забудьте в контент экрана взаимодействия добавить цвет, так как иначе он будет отображать заполнитель, который вы задали в теме:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
tools:context=".MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Теперь можно запустить проект и увидеть результат:

Холодный запуск приложения.

Надеюсь вам было полезно и интересно!)

Посмотрите пример проекта на GitHub.

Кибирд.

--

--