Вызов 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 возобновит ту же существующую активность
Овидиу Латку

7
Добавьте флаг FLAG_ACTIVITY_Multiple_TASKS, чтобы решить
вашу

Осторожно, это нужно и на 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 (Intent.FLAG_ACTIVITY_MULTIPLE_TASK); i.addFlag (Intent.FLAG_ACTIVITY_NEW_TASK); -------------------------------------------------- ----------------- i.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
JehandadK

42

Док Android говорит -

Требование 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контексте.

Напечатайте «this», чтобы войти в cat перед тем, как сделать startActivityвызов, и посмотреть, к чему это относится, иногда случается случайное использование внутреннего «this».


1
Вероятно, это проблема ОП. Я сталкивался с тем же. Запуск действия с getApplicationContext () вместо существующего действия вызовет эту ошибку.
Hazen Hills Software

Ницца :) Я совершенно уверен, что это была ошибка, которую я пытаюсь обнаружить весь вечер. Спасибо, мистер.
Мартин Пфеффер

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: - 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.