Виклик startActivity () за межами активності?


196

Я використовую, AlarmManagerщоб викликати наміри, які передають сигнал. Мій код:

AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(this, Wakeup.class);
try
{
    PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
    Long elapsed +=  // sleep time;
    mgr.set(AlarmManager.RTC_WAKEUP, elapsed, pi);
}
catch(Exception r)
{
    Log.v(TAG, "RunTimeException: " + r);
}

Я дзвоню цей код з Activity, тому я не знаю, як я міг отримати наступну помилку ...

ERROR/AndroidRuntime(7557): java.lang.RuntimeException: Unable to start receiver com.wcc.Wakeup: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

Відповіді:


494

якщо ваша версія Android знаходиться нижче Android - 6, вам потрібно додати цю лінію, інакше вона буде працювати над Android - 6.

...
Intent i = new Intent(this, Wakeup.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...

8
так, це працює. але якщо ви хочете запустити кілька примірників однієї діяльності, це не працює. Оскільки FLAG_ACTIVITY_NEW_TASK відновить ту саму діючу діяльність
Ovidiu Latcu

7
Додайте прапор FLAG_ACTIVITY_Multiple_TASKS, щоб вирішити свою проблему
Pavankumar Vijapur

Остерігайтеся, вам це потрібно і на Android 9+, дивіться цю відповідь для роз'яснень
Вадим Котов

55

Для декількох екземплярів однієї і тієї ж діяльності використовуйте наступний фрагмент,

Примітка . Цей фрагмент я використовую поза своїм Activity. Переконайтеся, що ваш AndroidManifestфайл не містить android:launchMode="singleTop|singleInstance". якщо потрібно, ви можете змінити його на android:launchMode="standard".

Intent i = new Intent().setClass(mActivity.getApplication(), TestUserProfileScreenActivity.class);  
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);

// Launch the new activity and add the additional flags to the intent
mActivity.getApplication().startActivity(i);

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


5
Будь ласка, зрозумійте різницю між методами setFlags () та addFlag (). Все, що ви зараз робите, - це запустити діяльність з FLAG_ACTIVITY_NEW_TASK. Як у коді, розміщеному Крістіаном нижче.
JehandadK

-------------------------------------------------- ----------------- i.addFlag (Намір.FLAG_ACTIVITY_MULTIPLE_TASK); i.addFlag (Намір.FLAG_ACTIVITY_NEW_TASK); -------------------------------------------------- ----------------- i.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
JehandadK

42

Android Doc каже -

Тепер вимога FLAG_ACTIVITY_NEW_TASK виконується

За допомогою Android 9 ви не можете розпочати діяльність з контексту бездіяльності, якщо не передасте прапор наміру FLAG_ACTIVITY_NEW_TASK. Якщо ви намагаєтеся розпочати діяльність, не передаючи цей прапор, діяльність не запускається, і система друкує повідомлення в журнал.

Примітка: вимога прапора завжди була задуманою поведінкою та застосовувалася у версіях, нижчих за Android 7.0 (рівень API 24). Помилка в Android 7.0 заважала виконувати вимогу прапорця.

Це означає, (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)що це обов'язково додавати Intent.FLAG_ACTIVITY_NEW_TASKпід час дзвінка startActivity()поза Activityконтекстом.

Тож краще додати прапор для всіх версій -

...
Intent i = new Intent(this, Wakeup.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...

12

Ви не вставили ту частину, куди дзвоните startActivity, це цікава частина.

Ви можете дзвонити startActivityв Serviceконтексті або в Applicationконтексті.

Надрукуйте "це", щоб увійти до кота перед тим, як здійснити startActivityдзвінок, і подивіться, на що він посилається, іноді буває випадково використання внутрішнього "цього".


1
Ймовірно, це проблема, яка є в ОП. Я зіткнувся з тим же. Запуск діяльності з getApplicationContext () замість існуючої діяльності призведе до цієї помилки.
Програмне забезпечення Hazen Hills

NICE :) Я повністю впевнений, що це була помилка, яку я намагаюся помітити цілий вечір. Спасибі, пане.
Мартін Пфеффер

9

Іноді ця помилка може статися без явного дзвінка на startActivity(...). Наприклад, деякі з вас, можливо, побачили такий слід стека в програмі Crashlytics:

Fatal Exception: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
       at android.app.ContextImpl.startActivity(ContextImpl.java:1597)
       at android.app.ContextImpl.startActivity(ContextImpl.java:1584)
       at android.content.ContextWrapper.startActivity(ContextWrapper.java:337)
       at android.text.style.URLSpan.onClick(URLSpan.java:62)
       at android.text.method.LinkMovementMethod.onTouchEvent(LinkMovementMethod.java:217)
       at android.widget.TextView.onTouchEvent(TextView.java:9522)
       at android.view.View.dispatchTouchEvent(View.java:8968)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.widget.AbsListView.dispatchTouchEvent(AbsListView.java:5303)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
       at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2559)
       at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1767)
       at android.app.Activity.dispatchTouchEvent(Activity.java:2866)
       at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:67)
       at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:67)
       at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2520)
       at android.view.View.dispatchPointerEvent(View.java:9173)
       at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4706)
       at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4544)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4068)
       at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4121)
       at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4087)
       at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4201)
       at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4095)
       at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4258)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4068)
       at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4121)
       at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4087)
       at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4095)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4068)
       at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6564)
       at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6454)
       at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6425)
       at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6654)
       at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:143)
       at android.os.Looper.loop(Looper.java:130)
       at android.app.ActivityThread.main(ActivityThread.java:5942)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)

І вам може бути цікаво, що ви зробили не так, оскільки слід містить лише рамковий код. Ну ось приклад того, як це може статися. Скажімо, ми знаходимося в фрагменті.

Activity activity = getActivity();
Context activityContext = activity;
Context appContext = activityContext.getApplicationContext();
LayoutInflater inflater = LayoutInflater.from(appContext); // whoops!
View view = inflater.inflate(R.layout.some_layout, parent, false);
TextView tvWithLinks = (TextView) view.findViewById(R.id.tv_with_links);

tvWithLinks.setMovementMethod(LinkMovementMethod.getInstance()); // whoops!!

Тепер, коли користувач натисне на цей текстовий вигляд, ваш додаток перестане працювати зі слідом стека вище. Це відбувається тому, що надувний макет має посилання на контекст програми , і тому ваш текстовий вигляд має контекст програми. Клацання на цьому текстовому перегляді неявно викликає appContext.startActivity(...).

Заключна примітка: я тестував це на пристроях Android 4, 5, 6 та 7. Це впливає лише на 4, 5 та 6. Пристрої Android 7, очевидно, не мають проблем з викликом appContext.startActivity(...).

Я сподіваюся, що це допомагає комусь іншому!


2

З цією ж помилкою я зіткнувся у випадку отримання Повідомлення на останніх пристроях Android 9 та 10.

Від режиму запуску залежить те, як ви обробляєте його. Використовуйте код нижче: - android: launchMode = "singleTask"

Додайте цей прапор за допомогою наміру: - intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);



1

Я просто хочу зауважити, що startActivityзовнішня діяльність діє в деяких версіях для Android (між N та O-MR1), і цікавим є те, що це помилка у вихідному коді Android!


Це коментар вище startActivityреалізації. Дивіться тут .

Здійснення виклику запуску із зовнішньої діяльності без FLAG_ACTIVITY_NEW_TASK, як правило, не дозволено, за винятком випадків, коли абонент вказує ідентифікатор завдання, з якого слід запустити активність. Помилка існувала між N та O-MR1, що дозволило цьому працювати .


яке рішення для цього
dominic_torreto

0

Коли ви хочете відкрити активність у вашій програмі, ви можете викликати метод startActivity () з параметром Intent як параметр. Цей намір був би діяльністю, яку ви хочете відкрити. Спочатку потрібно створити об'єкт цього наміру, перший параметр - це контекст, а другий параметр - це цільовий клас діяльності.

Intent intent = new Intent(this, Activity_a.class);
startActivity(intent);

Сподіваюсь, це допоможе.


3
Я пишу як рецензент, тому що ваша відповідь позначена як низька якість. Недолік цієї відповіді полягає в тому, що немає пояснення того, що робить ваш код, і чому він вирішує проблему, поставлену в питанні. Будь ласка, додайте пояснювальні коментарі, маючи на увазі, що багато програмістів можуть прочитати вашу відповідь у майбутньому для настанови. Дякую!
Білл Белл

Коли ви хочете відкрити активність у вашому додатку, ви можете викликати метод startActivity () з параметром Intent як параметр. Цей намір був би діяльністю, яку ви хочете відкрити. Спочатку потрібно створити об'єкт цього наміру, перший параметр - це контекст, а другий параметр - це цільовий клас діяльності. Сподіваюсь, це допоможе.
Пані Шафікур Рахман

ГАРАЗД. Але замість того, щоб ставити цю інформацію в коментар, ви повинні відредагувати свою відповідь і розмістити її там. Я шкодую про те, що зайнявся цим питанням, але важливо зробити це для кожної відповіді. З найкращими побажаннями.
Білл Белл

Так, будь ласка, додайте пояснення, чому ваша відповідь правильна. Ми вчимося бути кращими програмістами лише тоді, коли вчимось ЧОМУ робимо те, що робимо.
kiwicomb123
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.