Запуск активности из службы после нажатия кнопки HOME без 5-секундной задержки

У меня проблема, описанная в этой проблеме Android: http://code.google.com/p/android/issues/detail?id=4536

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

Я также заметил это (ну, теоретически), имея следующее разрешение:

"android.permission.STOP_APP_SWITCHES"

позволяет вызывать resumeAppSwitches (который определен в ActivityManagerService). Глядя на последнюю версию ActivityManagerService, этот код удален.

Вопрос: Как запустить активность с помощью startActivity без этой 5-секундной задержки?

4 ответа

Решение

Я не думаю, что есть способ сделать это с текущими API. Я думаю, что именно так они и должны были работать, чтобы приложение не могло принудительно открыться, когда пользователь завершает работу нажатием клавиши home. Вы можете добавить намерение home / launcher в фильтр для любого действия, которое вы пытаетесь запустить. Тогда у пользователя будет выбор в основном рассматривать это приложение, как будто оно является домашним экраном. Затем он запускается без задержки, когда пользователь нажимает кнопку "Домой" (ему нужно будет выбрать ее из списка, который спросит, какое приложение он хочет использовать, чтобы выполнить это действие, но он может всегда проверять использование это приложение, чтобы сделать этот шаг в будущем.)

Вот решение, которое я нашел.

Поместите свое намерение немедленно начать в PendingIntent, затем вызовите метод send() для него.

Так что вместо этого

Intent intent = new Intent(context, A.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(intent);

просто сделай это

Intent intent = new Intent(context, A.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                PendingIntent pendingIntent =
                        PendingIntent.getActivity(context, 0, intent, 0);
                try {
                    pendingIntent.send();
                } catch (PendingIntent.CanceledException e) {
                    e.printStackTrace();
                }

Меня также заинтриговала эта "особенность" и то, как ее избежать. Читая пост: http://code.google.com/p/android/issues/detail?id=4536 (прочитайте комментарий № 10).

Я цитирую соответствующую часть ниже:

Обходные пути:

1) Не используйте деятельность, делайте все из службы.

2) Иметь какой-то промежуточный Home (WidgetLocker HomeHelper, QuickDesk, PowerStrip и т. Д.). Они немедленно запускают действие, чтобы запустить "настоящий" Дом, и это обходит правило 5 секунд. Это плохая идея, поскольку Android отдает приоритет хранению системы Home в памяти, а не второстепенному Home, промежуточному набору. Так что это может привести к перезагрузке Launcher, что неинтересно. Плюс это очень запутанно для пользователей.

3) Root может начать деятельность в течение этого периода.

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

Как я уже говорил в своем предыдущем комментарии к вопросу, я бы связался с разработчиком WidgetLocker. Кроме того, вы можете использовать APK Manager, чтобы увидеть, как он это реализовал (он даже рекомендовал использовать APK Manager для создания различных модов для своего приложения, ссылка на ветку xda-developers есть в комментарии выше)

Я использую AlarmManager для немедленного запуска Активности из Сервиса. Активность начинается без задержки, даже если вы нажали кнопку "Домой" раньше.

Протестировано на Android 5.0.1 (Galaxy Alpha).

Не работает на 6.0.1 (Nexus 7 2013):-(

Не работает на 4.1.2 (Galaxy S II):-(

Не работает на 4.3 (ASUS MeMO Pad FHD 10 ME302C):-(

@TargetApi(Build.VERSION_CODES.KITKAT)
private void startActivity() {

    Intent intent = new Intent(this, Main.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    long now = Calendar.getInstance().getTimeInMillis();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, now, pendingIntent);
    else
        alarmManager.set(AlarmManager.RTC_WAKEUP, now, pendingIntent);
}
Другие вопросы по тегам