从Activity上下文外部调用startActivity()


367

ListView在Android应用程序中实现了。我ListView使用类的自定义子类将此绑定ArrayAdapter。在覆盖的ArrayAdapter.getView(...)方法中,我分配了一个OnClickListener。在的onClick方法中OnClickListener,我要启动一个新活动。我得到了例外:

Calling startActivity() from outside of an Activity  context requires the  
FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

我怎样才能获得ContextListView(目前的Activity)工作下?


1
我认为Alex的回答应该是对您的问题的“可接受”解决方案,因为它可以更一般地纠正您提到的错误
devanshu_kaushik 2012年

10
我喜欢“这真的是您想要的吗?” ...在此之前,我有一条消息说:“您确定您不会忘记在某个地方注销广播接收器吗?” 真棒!向那些将所有这些小消息放入帮助我们的人表示敬意。
Nerdy Bunz

1
我遇到了这个问题。当我将targetSdkVersion更新为28时。–
illusionJJ

Answers:


574

要么

  • 通过适配器中的构造函数缓存Context对象,或者
  • 从您的角度来看。

或者作为最后的手段,

  • 添加-FLAG_ACTIVITY_NEW_TASK标志到您的意图:

_

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

编辑-我会避免设置标志,因为它会干扰事件和历史记录堆栈的正常流程。


6
我无法控制系统创建的Intent(因此也不能控制标志)的TextView 的autoLink功能呢?
Alex Semeniuk

75
我得到这个异常,当我在做这样的事情context.startActivity(intent);我只是改变context来自ApplicationContextActivity类型。这解决了问题。
苏菲安

@AlexSemeniuk是否找到解决方案?

@AlexSemeniuk-只要您将活动作为上下文传递给适配器,autoLink就会起作用
Georges

我通过构造函数传递了Context对象,但是它不起作用。但是FLAG_ACTIVITY_NEW_TASK非常适合我,谢谢。
希伦

100

您可以使用addFlags代替setFlags

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

根据文档,它可以:

向意图添加其他标志(或使用现有标志值)。


编辑

请注意,如果您使用的标志会更改历史记录堆栈,如Alex Volovoy的回答所述

...避免设置标志,因为它会干扰事件和历史记录堆栈的正常流程。


1
我有一个非常相似的问题。您是否在历史记录栈或上面建议的答案中遇到任何其他问题?
Einar Sundgren

1
我不确定您要查找的内容是什么,但是您可以在没有这样的历史记录的情况下开始活动:Intent intent = new Intent(Intent.ACTION_VIEW,“ http:\\ www.google.com”));意图。 addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity(intent);
Bruno Bieri 2013年

为什么不建议在这里添加addFlags?干扰事件和历史堆栈的正常流程有多重要?
杰森·克里斯

@JasonKrs,您可以使用addFlags。请注意,您可以根据添加的标志更改历史记录堆栈。在这种情况下,可以使用FLAG_ACTIVITY_NEW_TASK。有关详细信息阅读:developer.android.com/reference/android/content/...
布鲁诺BIERI


40

如果由于使用如下所示的创建选择器而出现错误:

Intent sharingIntent = new Intent(Intent.ACTION_VIEW);
sharingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sharingIntent.setData(Uri.parse("http://google.com"));
startActivity(Intent.createChooser(sharingIntent, "Open With"));

设置标志以创建选择器,如下所示:

Intent sharingIntent = new Intent(Intent.ACTION_VIEW);
sharingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sharingIntent.setData(Uri.parse("http://google.com"));

Intent chooserIntent = Intent.createChooser(sharingIntent, "Open With");
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(chooserIntent);

4
这非常有用。确切的选择器意图应该具有此标志!
Mahdi

2
这是正确的解决方案,确切地说是必须做的,intent.chooser中的new_task
拉斐尔·吉马良斯

15

另外:如果您在片段视图的列表视图中显示链接,请不要这样创建链接

adapter = new ListAdapter(getActivity().getApplicationContext(),mStrings);

代替

adapter = new ListAdapter(getActivity(),mStrings);

适配器在两种情况下均能正常工作,但链接仅在最后一种情况下有效。


@ user2676468:这为我解决了自动链接问题。
极客头球2014年

这应该是一个可以接受的答案,而不是使用标志,这样更好!
加斯顿Saillén

@GastónSaillén,我不使用getApplicationContext()(应用程序初始化除外),但是捕获了此异常。因此,情况可能有所不同。
CoolMind

这是我的问题,我使用getApplicationContext()作为上下文。设置this为上下文与当前活动相关。
布里亚

14

我认为也许您在错误的地方实现了OnClickListener-通常您肯定应该在Activity中实现一个OnItemClickListener并将其设置在ListView上,否则您的事件会遇到问题...


2
您带领我找到解决方案。我需要使用分配给ListView的OnItemClickListener。以下是其他任何人的链接:developer.android.com/reference/android/widget / ... androidpeople.com / ... 感谢您的帮助。
Sako73

请提供一般性答案。以下是Alex Volovoy的答案,以一般方式解决了该问题。
devanshu_kaushik 2012年

为了后代:如果直接在需要Context的组件上将其定义为setListener(new Listener),则会为整个活动创建一个隐式引用,这将导致您不相信的泄漏内存。可以通过创建静态内部类侦听器或将侦听器移至单独的类(如果它需要能够处理来自多个来源的输入)来避免这种情况。
G_V 2015年

9
CustomAdapter mAdapter = new CustomAdapter( getApplicationContext(), yourlist);

要么

Context mContext = getAppliactionContext();
CustomAdapter mAdapter = new CustomAdapter( mContext, yourlist);

转到下面

CustomAdapter mAdapter = new CustomAdapter( this, yourlist);

8

Android 28(Android P)startActivity

if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
        && (targetSdkVersion < Build.VERSION_CODES.N
                || targetSdkVersion >= Build.VERSION_CODES.P)
        && (options == null
                || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
    throw new AndroidRuntimeException(
            "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
}

所以最好的方法是添加 FLAG_ACTIVITY_NEW_TASK

Intent intent = new Intent(context, XXXActivity.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);

28个及以上设备需要此功能。
莫辛

7

看看,如果您正在某种方法中在listiner中创建意图

override onClick (View v).

然后也通过此视图调用上下文:

v.getContext ()

甚至不需要SetFlags ...


那是什么错呢?v.getApplicationContext()?
CoolMind


3

详细阐述Alex Volovoy的答案-

如果您遇到碎片问题,getActivity()可以很好地获取上下文

在其他情况下:

如果您不想使用-

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//not recommend

然后在OutsideClass中创建如下函数:

public void gettingContext(Context context){
    real_context = context;//where real_context is a global variable of type Context
}

现在,在您的主要活动中,无论何时创建新的OutsideClass,在定义将活动上下文作为参数的OutsideClass之后,立即调用上述方法。同样在您的主要活动中,请执行以下功能:

public void startNewActivity(final String activity_to_start) {
    if(activity_to_start.equals("ACTIVITY_KEY"));
    //ACTIVITY_KEY-is a custom key,just to
    //differentiate different activities
    Intent i = new Intent(MainActivity.this, ActivityToStartName.class);
    activity_context.startActivity(i);      
}//you can make a if-else ladder or use switch-case

现在回到您的OutsideClass,并开始新的活动,例如

@Override
public void onClick(View v) {
........
case R.id.any_button:

            MainActivity mainAct = (MainActivity) real_context;             
            mainAct.startNewActivity("ACTIVITY_KEY");                   

        break;
    }
........
}

这样,您将能够启动从不同的OutsideClass调用的不同活动,而不会弄乱标志。

注意-尝试不要通过片段的构造函数缓存上下文对象(使用适配器,它很好)。片段应该有一个空的构造函数,否则在某些情况下应用程序会崩溃。

记得打电话

OutsideClass.gettingContext(Context context);

在onResume()函数中。


3

当startactivity不知道他的活动是什么时,就会发生此错误。因此,您必须在startActivity()之前添加活动

你必须设置

context.startActivity(yourIntent);

如果startActivity从呼叫Fragment,呼叫者通常可以是片段,而不是活动。
CoolMind

2

我认为,最好startActivity()在您的代码中使用的方法Activity.class。如果在Adapter或其他类中使用它,则会导致该情况。


2

我也有同样的问题。检查您通过的所有上下文。对于“ 链接 ”,它需要活动上下文而不是应用程序上下文

这是您应该检查的地方:

1.)如果您使用了LayoutInflater,请检查您传递的上下文。

2.)如果您使用任何适配器,请检查已传递的上下文。


2

我有同样的问题。问题在于上下文。如果要打开任何链接(例如,通过选择器共享任何链接),则传递活动上下文,而不是应用程序上下文。

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)如果您不在活动中,请不要忘记添加。


2

在您的Adapter_Activity中使用此代码,并使用context.startActivity(intent_Object)intent_Object.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

像这样:

Intent n_act = new Intent(context, N_Activity.class);
n_act.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(n_act);

有用....


1
Intent viewIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);    
viewIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    
startActivity(viewIntent);   

我希望这会工作。



1

使用此代码。对我来说很好。在活动之外分享一些东西:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");

// Append Text
String Text = "Your Text Here"

intent.putExtra(Intent.EXTRA_TEXT, Text);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Intent shareIntent = Intent.createChooser(intent,"Share . . . ");
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
G.context.getApplicationContext().startActivity(shareIntent);

设置标志会破坏堆栈跟踪历史记录
-Ezio

1

由于添加标志会影响event_flowstack_history因此最好通过以下方式从需要调用活动类的位置将“应用程序上下文”传递给非活动:

“ ActivityClassName.this”(当您以这种方式传递上下文时,它将包含从非活动场景调用活动所需的所有详细信息)

因此,无需设置或添加标志,这在每种情况下都可以正常工作。


0
Intent i= new Intent(context, NextActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);

0

如果您在Cordova插件中调用共享意图,则设置标志将无济于事。而是使用这个-

cordova.getActivity().startActivity(Intent.createChooser(shareIntent, "title"));

0

我的情况略有不同,我正在使用测试我的应用程序,Espresso并且不得不ActivityTestRule从工具启动我的Activity Context(不是来自的工具Activity)。

fun intent(context: Context) = 
    Intent(context, HomeActivity::class.java)
        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

我不得不更改标志并在其中添加or按位(|在Java中)Intent.FLAG_ACTIVITY_NEW_TASK

因此它导致:

fun intent(context: Context) = 
    Intent(context, HomeActivity::class.java)
        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)

0

Kotlin版本

val intent = Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
this.startActivity(intent)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.