Android 从活动外部调用 startActivity()?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3689581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:22:51  来源:igfitidea点击:

Calling startActivity() from outside of an Activity?

androidalarmmanagerandroid-pendingintentruntimeexception

提问by Tom G

I'm using an AlarmManagerto trigger an intent that broadcasts a signal. The following is my code:

我正在使用 anAlarmManager来触发广播信号的意图。以下是我的代码:

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);
}

I'm calling this code from an Activity, so I don't know how I could be getting the following error...

我正在从 调用此代码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?

回答by Cristian

if your android version is below Android - 6 then you need to add this line otherwise it will work above Android - 6.

如果您的 android 版本低于 Android - 6,那么您需要添加此行,否则它将在 Android - 6 以上运行。

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

回答by Nandagopal T

For Multiple Instance of the same activity , use the following snippet,

对于同一活动的多个实例,请使用以下代码段,

Note: This snippet, I am using outside of my Activity. Make sure your AndroidManifestfile doesn't contain android:launchMode="singleTop|singleInstance". if needed, you can change it to android:launchMode="standard".

注意:这个片段,我在我的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);

This works fine for me. Hope, this saves times for someone. If anybody finds a better way, please share with us.

这对我来说很好用。希望,这可以为某人节省时间。如果有人找到更好的方法,请与我们分享。

回答by Hrishikesh Kadam

Android Docsays -

Android Doc说 -

FLAG_ACTIVITY_NEW_TASK requirement is now enforced

With Android 9, you cannot start an activity from a non-activity context unless you pass the intent flag FLAG_ACTIVITY_NEW_TASK. If you attempt to start an activity without passing this flag, the activity does not start, and the system prints a message to the log.

Note: The flag requirement has always been the intended behavior, and was enforced on versions lower than Android 7.0 (API level 24). A bug in Android 7.0 prevented the flag requirement from being enforced.

现在强制执行 FLAG_ACTIVITY_NEW_TASK 要求

在 Android 9 中,除非您传递意图标志 FLAG_ACTIVITY_NEW_TASK,否则您无法从非活动上下文启动活动。如果您在未传递此标志的情况下尝试启动活动,则活动不会启动,并且系统会在日志中打印一条消息。

注意:标志要求一直是预期行为,并在低于 Android 7.0(API 级别 24)的版本上强制执行。Android 7.0 中的一个错误阻止强制执行标志要求。

That means for (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)it is mandatory to add Intent.FLAG_ACTIVITY_NEW_TASKwhile calling startActivity()from outside of an Activitycontext.

这意味着在从上下文外部调用时(Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)必须添加。Intent.FLAG_ACTIVITY_NEW_TASKstartActivity()Activity

So it is better to add flag for all the versions -

所以最好为所有版本添加标志 -

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

回答by marmor

You didn't paste the part where you call startActivity, that's the interesting part.

你没有粘贴你调用的部分startActivity,那是有趣的部分。

You might be calling startActivityin a Servicecontext, or in an Applicationcontext.

您可能startActivityService上下文中或在Application上下文中调用。

Print "this" to log cat before making the startActivitycall, and see what it refers to, it's sometimes a case of using an inner "this" accidentally.

startActivity调用之前打印“this”以记录 cat ,并查看它指的是什么,有时是意外使用内部“this”的情况。

回答by AutonomousApps

Sometimes this error can occur without an explicit call to startActivity(...). For example, some of you may have seen a stack trace like this in Crashlytics:

有时,在没有显式调用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)

And you may wonder what you did wrong, since the trace only includes framework code. Well, here's an example of how this can happen. Let's say we're in a fragment.

您可能想知道自己做错了什么,因为跟踪只包含框架代码。嗯,这是一个如何发生的例子。假设我们处于一个片段中。

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!!

Now, when a user clicks on that text view, your app will crash with the stack trace above. This is because the layout inflaterhas a reference to the application context, and so therefore your text viewhas an application context. Clicking on that text view implicitlycalls appContext.startActivity(...).

现在,当用户单击该文本视图时,您的应用程序将因上面的堆栈跟踪而崩溃。这是因为布局充气器引用了应用程序上下文,因此您的文本视图具有应用程序上下文。单击该文本视图会隐式调用appContext.startActivity(...).

Final note: I tested this on Android 4, 5, 6, and 7 devices. It only affects 4, 5, and 6. Android 7 devices apparently have no trouble calling appContext.startActivity(...).

最后说明:我在 Android 4、5、6 和 7 设备上对此进行了测试。它只影响 4、5 和 6。Android 7 设备显然没有问题调用appContext.startActivity(...).

I hope this helps someone else!

我希望这对其他人有帮助!

回答by Puneet Kumar

This same error I have faced in case of getting Notification in latest Android devices 9 and 10.

在最新的 Android 设备 9 和 10 中收到通知时,我遇到了同样的错误。

It depends on Launch mode how you are handling it. Use below code:- android:launchMode="singleTask"

这取决于您如何处理启动模式。使用以下代码:- android:launchMode="singleTask"

Add this flag with Intent:- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

用 Intent 添加这个标志:- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

回答by Fartab

I just want to notice that startActivityfrom outside an activity is valid in some android versions (between N and O-MR1) and the interesting point is that it is a bug in android source code!

我只想注意到,startActivity从外部来看,活动在某些 android 版本(N 和 O-MR1 之间)中是有效的,有趣的是它是 android 源代码中的一个错误!


This is the comment above startActivityimplementation. See here.


这是上面startActivity实现的注释。见这里

Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is generally not allowed, except if the caller specifies the task id the activity should be launched in. A bug was existed between N and O-MR1 which allowed this to work.

通常不允许从没有 FLAG_ACTIVITY_NEW_TASK 的活动外部调用开始活动,除非调用者指定了应在其中启动活动的任务 ID。N 和 O-MR1 之间存在一个错误,允许它工作

回答by Luís Ledebour

Try changing to this line:

尝试更改为这一行:

PendingIntent pendingIntent = PendingIntent.getBroadcast(getContext(), 0, i, 0);

回答by Md. Shafiqur Rahman

When you want to open an activity within your app then you can call the startActivity() method with an Intent as parameter. That intent would be the activity that you want to open. First you have to create an object of that intent with first parameter to be the context and second parameter to be the targeted activity class.

当您想在您的应用程序中打开一个活动时,您可以使用 Intent 作为参数调用 startActivity() 方法。该意图将是您要打开的活动。首先,您必须创建该意图的对象,其中第一个参数是上下文,第二个参数是目标活动类。

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

Hope this will help.

希望这会有所帮助。