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

时间:2010-10-12 20:00:23

标签: android android-activity android-context

我在Android应用程序中实现了ListView。我使用ListView类的自定义子类绑定到此ArrayAdapter。在重写的ArrayAdapter.getView(...)方法中,我指定了OnClickListener。在onClick的{​​{1}}方法中,我想发布一项新活动。我得到了例外:

OnClickListener

如何获得Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? (当前Context)正在使用的ListView

25 个答案:

答案 0 :(得分:511)

要么

  • 通过适配器中的构造函数缓存Context对象,或
  • 从你的观点中得到它。

或作为最后的手段,

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

_

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

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

答案 1 :(得分:89)

您可以使用 addFlags 而非setFlags来实现

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

根据它所做的documentation

  

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


修改

请注意,如果您使用的是您更改历史记录堆栈的标记,则Alex Volovoy's answer会说:

  

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

答案 2 :(得分:54)

而不是使用(getApplicationContext)使用YourActivity.this

答案 3 :(得分:29)

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

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 :(得分:13)

我想也许你正在错误的地方实现OnClickListener - 通常你应该在你的Activity中实现一个OnItemClickListener并将其设置在ListView上,否则你的事件就会出现问题...

答案 5 :(得分:11)

此外:如果您在片段中的listview中显示链接,请不要像这样创建

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

而是打电话

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

适配器在两种情况下都能正常工作,但链接仅适用于最后一种。

答案 6 :(得分:7)

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

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

更改为

CustomAdapter mAdapter = new CustomAdapter( this, yourlist);

答案 7 :(得分:6)

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

答案 8 :(得分:5)

请参阅,如果您在某个方法中使用列表器创建意图

override onClick (View v).

然后通过这个视图调用上下文:

v.getContext ()

甚至不需要SetFlags ...

答案 9 :(得分:3)

当startactivity不知道哪个是他的活动时,会出现此错误。因此,您必须在startActivity()

之前添加活动

你必须设置

activity.startActivity(yourIntent);

答案 10 :(得分:3)

对于任何人在 Xamarin.Android(MonoDroid)上获取此功能,即使从活动中调用StartActivity - 这实际上是新的ART运行时的Xamarin错误,请参阅https://bugzilla.xamarin.com/show_bug.cgi?id=17630

答案 11 :(得分:2)

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

这是您应该检查的地方:

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

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

答案 12 :(得分:2)

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

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

答案 13 :(得分:2)

详细阐述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
}

现在,在你的主活动中,当你定义外部类,并将活动的上下文作为参数时,你立即调用上面的方法。 同样在你的主要活动中创建一个函数 -

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()函数中使用

答案 14 :(得分:2)

在我看来,最好在startActivity()的代码中使用Activity.class的方法。如果您在Adapter或其他类中使用它,则会产生该结果。

答案 15 :(得分:1)

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

我希望这会奏效。

答案 16 :(得分:1)

面对同样的问题然后实施

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

并解决了这个问题。

可能还有另一个与列表视图适配器相关的原因 你可以看到This blog,描述得非常好。

答案 17 :(得分: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);

答案 18 :(得分:1)

在您的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);

有效。...

答案 19 :(得分:0)

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

答案 20 :(得分:0)

如果您在Cordova插件中调用共享Intent,设置Flag将无济于事。而是使用它 -

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

答案 21 :(得分:0)

我的情况略有不同,我正在使用Espresso测试我的应用,我必须使用ActivityTestRule(不是一个来自Context)。

Activity

我必须更改标记,并在fun intent(context: Context) = Intent(context, HomeActivity::class.java) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

中按位or在Java中添加|

因此导致:

Intent.FLAG_ACTIVITY_NEW_TASK

答案 22 :(得分:0)

由于添加标记会影响event_flowstack_history,因此最好传递应用程序上下文&#39;通过以下方式调用活动类的非活动:

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

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

答案 23 :(得分:0)

科特林版本

val intent = Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
this.startActivity(intent)

答案 24 :(得分:0)

在“活动”(您在其中调用适配器的地方)中,只需将getActivityContext()更改为YourActivity.this。 这是一个例子:

yourAdapter = new YourAdapter(yourList, YourActivity.this); // Here YourActivity.this is the Context instead of getActivityContext()
recyclerView.setAdapter(yourAdapter);