关于android:从Activity上下文外部调用startActivity()

Calling startActivity() from outside of an Activity context

我在我的Android应用程序中实现了一个ListView。我使用ArrayAdapter类的自定义子类绑定到这个ListView。在重写的ArrayAdapter.getView(...)方法中,我分配一个OnClickListener。在OnClickListeneronClick方法中,我想启动一个新的活动。我得到例外:

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

我怎样才能得到EDOCX1(当前的Activity)正在使用的Context


要么

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

或者作为最后的手段,

  • 将-flag_activity_new_task标志添加到您的意图中:

γ

1
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

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


你可以用addflags而不是setFlags来实现它。

1
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

根据文件,它可以:

Add additional flags to the intent (or with existing flags value).

编辑

请注意,如果您使用的标志更改了历史堆栈,正如Alex Volovoy的回答所说:

...avoid setting flags as it will interfere with normal flow of event and history stack.


不使用(getApplicationContext),使用YourActivity.this


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

1
2
3
4
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"));

设置如下创建选择器的标志:

1
2
3
4
5
6
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);


我认为您可能在错误的地方实现OnClickListener—通常您应该在活动中明确地实现OnTiceClickListener,并将其设置在ListView上,否则您的事件会出现问题…


另外:如果在片段中的ListView中显示链接,则不要这样创建链接。

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

代替呼叫

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

适配器在这两种情况下都可以正常工作,但链接只能在最后一种情况下工作。


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

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

改变到下面

1
CustomAdapter mAdapter = new CustomAdapter( this, yourlist);

看,如果您在某个方法的listiner中创建了一个意图

1
override onClick (View v).

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

1
v.getContext ()

甚至不需要设置标志…


对于任何在xamarin.android(monodroid)上获取此信息的人,即使从activity调用startactivity-这实际上是带有新艺术运行时的xamarin bug,请参见https://bugzilla.xamarin.com/show_bug.cgi?ID=17630


当StartActivity不知道哪个是他的活动时,就会出现此错误。因此,必须在StartActivity()之前添加Activity。

你必须设置

1
activity.startActivity(yourIntent);

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

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


在我看来,最好只在你的Activity.class代码中使用startActivity()的方法。如果在Adapter或其他类中使用它,将导致这种情况。


进一步阐述亚历克斯·沃洛维的回答-

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

在其他情况下:

如果你不想使用-

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

然后在你的局外人类中做一个这样的函数-

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

现在,在您的主活动中,当您创建一个新的OutsideClass时,在定义了将活动的上下文作为参数的OutsideClass之后,立即调用上面的方法。也在你的主要活动中发挥作用-

1
2
3
4
5
6
7
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

现在回到你的局外人的课堂上,开始新的活动,像这样做。-

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public void onClick(View v) {
........
case R.id.any_button:

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

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

这样,您就可以从不同的OutsideClass启动不同的活动,而不会弄乱标志。

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

记得打电话

1
OutsideClass.gettingContext(Context context);

在onresume()函数中。


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

这是您应该检查的地方:

1.)如果您使用了布局膨胀器,那么请检查您已通过的上下文。

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


在适配器活动中使用此代码,并使用context.startActivity(intent_Object)intent_Object.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

这样地:

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

它起作用了…


面临同样的问题,然后实施

1
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

解决了这个问题。

可能还有另一个与列表视图适配器相关的原因。你可以看到这个博客,描述得很好。


使用此代码。对我来说很好。从活动外部共享内容:

1
2
3
4
5
6
7
8
9
10
11
12
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);


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

我希望这能奏效。


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


如果您在cordova插件中调用share intent,那么设置该标志将没有帮助。而是用这个-

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

我的情况有点不同,我正在使用Espresso测试我的应用程序,我必须从仪器Context启动我的ActivityTestRule活动(不是来自Activity)。

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

我必须改变标志,并在EDOCX1×6中添加一个EDOCX1×4位(EDCOX1,5,爪哇)。

因此,结果是:

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

由于添加标志会影响event_flowstack_history,因此最好将"应用程序上下文"传递给非活动,从该活动中需要按以下方式调用活动类:

"activityclassname.this"(以这种方式传递上下文时,它将包含从非活动方案调用活动所需的所有详细信息和信息)

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