458

I have implemented a ListView in my Android application. I bind to this ListView using a custom subclass of the ArrayAdapter class. Inside the overridden ArrayAdapter.getView(...) method, I assign an OnClickListener. In the onClick method of the OnClickListener, I want to launch a new activity. I get the exception:

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

How can I get the Context that the ListView(the current Activity) is working under?

user
  • 86,916
  • 18
  • 197
  • 190
Sako73
  • 9,957
  • 13
  • 57
  • 75
  • 1
    I think Alex's answer should be the 'accepted' solution to your problem, since it rectifies the error you mentioned in a more generic manner – devanshu_kaushik Oct 15 '12 at 07:10
  • 15
    I love that "Is this really what you want?" ... I've had a message before that said "Are you sure you didn't forget to unregister a broadcast receiver somewhere?" AWESOME! Hats off to whoever put all these little messages in to help us squabs. – Nerdy Bunz May 25 '16 at 11:23
  • 1
    I met this issue. when I updated targetSdkVersion to 28. – illusionJJ Apr 13 '19 at 11:50

28 Answers28

687

Either

  • cache the Context object via constructor in your adapter, or
  • get it from your view.

Or as a last resort,

  • add - FLAG_ACTIVITY_NEW_TASK flag to your intent:

_

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

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

LarsH
  • 27,481
  • 8
  • 94
  • 152
Alex Volovoy
  • 67,778
  • 13
  • 73
  • 54
  • 6
    What about the _autoLink_ feature of the TextView where I can not control Intent (and thus flags) created by the system? – Alex Semeniuk Apr 30 '13 at 07:10
  • 101
    I was getting this exception when I was doing something like this `context.startActivity(intent);` I just changed `context`from `ApplicationContext` to `Activity` type. This fixed the problem. – Sufian Nov 16 '13 at 17:08
  • @AlexSemeniuk ever find a solution? –  Mar 13 '14 at 16:28
  • 1
    @AlexSemeniuk - autoLink will work as long as you pass the activity as context to the adapter – Georges Dec 02 '15 at 05:40
  • I passed Context object via constructor but its not work. but FLAG_ACTIVITY_NEW_TASK is works very well for me thanks. – Hiren Nov 16 '16 at 11:27
  • getting context from view like `view.getContext()` worked for me! – Meet Vora Jul 13 '17 at 08:05
  • `getApplicationContext()` did not work for me but using `this` did. – Kaspis245 Aug 27 '18 at 13:39
123

You can achieve it with addFlags instead of setFlags

myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

According to the documentation it does:

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


EDIT

Be careful when you are using flags that you may change the history stack as Alex Volovoy's answer says:

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

Bruno Bieri
  • 9,724
  • 11
  • 63
  • 92
  • 1
    I have a very similar problem. Have you experienced any problems with the history stack or anything else as the answers above sugggest? – Einar Sundgren Jun 20 '13 at 09:12
  • 1
    I'm not exactly sure what you're looking for but you can start an activity without a history like that: Intent intent = new Intent(Intent.ACTION_VIEW, "http:\\www.google.com"));intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity(intent); – Bruno Bieri Jun 20 '13 at 18:47
  • Why is it that not recommended to addFlags here ? How critical is it to interfere with normal flow of event and history stack ? – Jason Krs Mar 04 '18 at 00:18
  • @JasonKrs you can use addFlags. Just be aware that you could change the history stack depending on the flag you add. The FLAG_ACTIVITY_NEW_TASK can be used in this situation. For more details read: https://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_NEW_TASK – Bruno Bieri Mar 04 '18 at 07:17
77

Instead of using (getApplicationContext) use YourActivity.this

Jeffrey Nyauke
  • 1,846
  • 14
  • 12
66

If you got error because of using create chooser like below:

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

Set the flag to create chooser like this :

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);
sanath_p
  • 2,198
  • 2
  • 26
  • 22
15

In addition: if you show links in listview in fragment, do not create it like this

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

instead call

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

adapter works fine in both cases, but links work only in last one.

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
djdance
  • 3,110
  • 27
  • 33
14

I think maybe you are implementing the OnClickListener in the wrong place - usually you should definitely implement an OnItemClickListener in your Activity and set it on the ListView instead, or you will get problems with your events...

mreichelt
  • 12,359
  • 6
  • 56
  • 70
  • 2
    You lead me to the solution. I needed to use an OnItemClickListener, assigned to the ListView. Here are some links for anyone else: http://developer.android.com/reference/android/widget/AdapterView.OnItemClickListener.html http://www.androidpeople.com/android-custom-listview-tutorial-example-part-2/ Thanks for the help. – Sako73 Oct 12 '10 at 21:02
  • Please provide generic answers. Alex Volovoy's answer below solves the problem in a generic manner. – devanshu_kaushik Oct 15 '12 at 07:08
  • For posterity: If you directly define it as setListener(new Listener) on a component requires a Context, you create an implicit reference to the entire activity which will leak memory like you wouldn't believe. This can be circumvented by either making a static inner class listener or by moving the listener to a separate class if it needs to be able to handle inputs from more than one origin. – G_V Jan 28 '15 at 08:25
12

At the 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?");
}

So the best way is add 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);
Alen Lee
  • 2,479
  • 2
  • 21
  • 30
9
CustomAdapter mAdapter = new CustomAdapter( getApplicationContext(), yourlist);

or

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

change to below

CustomAdapter mAdapter = new CustomAdapter( this, yourlist);
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Murtaza Ashraf
  • 190
  • 1
  • 5
8

See, if you are creating an intent within a listiner in some method

override onClick (View v).

then call the context through this view as well:

v.getContext ()

There will not even need SetFlags ...

slfan
  • 8,950
  • 115
  • 65
  • 78
4

For anybody getting this on Xamarin.Android (MonoDroid) even when StartActivity is called from activity - this is actually Xamarin bug with new ART runtime, see https://bugzilla.xamarin.com/show_bug.cgi?id=17630

rouen
  • 5,003
  • 2
  • 25
  • 48
  • Yeah you just have to do as what's been described above, but the wording has changed... intent.SetFlags(ActivityFlags.NewTask); – Luke Alderton Aug 08 '19 at 15:16
  • Intent intent = new Intent(); intent.AddFlags(ActivityFlags.NewTask); intent.SetData(Android.Net.Uri.Parse(baseUrl + @"name_of_apk")); Android.App.Application.Context.StartActivity(intent); – KennyAli Mar 17 '21 at 05:35
  • NO NEED TO USE SetFlags in Xamarin.Android. Use `Xamarin.Essentials.Platform.CurrentActivity.StartActivity(intent);` – Junaid Pathan May 18 '22 at 23:15
3

This error goes when startactivity doesn't know which is his activity. So you must add activity before startActivity()

you must set

context.startActivity(yourIntent);
Cabezas
  • 9,329
  • 7
  • 67
  • 69
3

Elaborating Alex Volovoy's answer a little more -

in case u are getting this problem with fragments, getActivity() works fine to get the context

In Other Cases:

If you don't want to use-

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

then make a function like this in your OutsideClass -

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

Now,in your main activity when ever you make a new OutsideClass call the above method immediately after you define the OutsideClass giving the activity's context as argument. Also in your main activity make a function-

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

now come back to your OutsideClass,and to start new activity do something like this-

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

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

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

This way you will be able to start different activities called from different OutsideClass without messing up with flags.

Note-Try not to cache context object via constructor for fragment(with adapter,its fine).A fragment should have a empty constructor otherwise application crashes in some scenarios.

remember to call

OutsideClass.gettingContext(Context context);

in the onResume() function as well.

Flying Monkey
  • 669
  • 1
  • 5
  • 13
2

In my opinion, it's better to use the method of startActivity() just in the your code of the Activity.class. If you use that in the Adapter or other class, it will result in that.

rayryeng
  • 102,964
  • 22
  • 184
  • 193
kaosmys
  • 29
  • 1
  • 1
2

I also had the same problem. Check all the context that you have passed. For 'links' it needs Activity Context not Application context.

This are the place where you should check :

1.) If you used LayoutInflater then check what context you have passed.

2.) If you are using any Adapter check what context you have passed.

codemaniac
  • 260
  • 2
  • 14
2

Use this code in your Adapter_Activity and use context.startActivity(intent_Object) and intent_Object.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Like this:

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

It Works....

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Gaurav Lambole
  • 273
  • 3
  • 3
2

In your Activity (where you're calling the adapter) just change getActivityContext() with YourActivity.this. Here's an exemple:

yourAdapter = new YourAdapter(yourList, YourActivity.this); // Here YourActivity.this is the Context instead of getActivityContext()
recyclerView.setAdapter(yourAdapter);
Félix Maroy
  • 1,389
  • 2
  • 16
  • 21
1
Intent viewIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);    
viewIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    
startActivity(viewIntent);   

i hope this will work.

1

Faced the same issue then implemented

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

and got solved the problem.

There may be an another reason which is related to list view adapter.
You can see This blog, described it very well.

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Mayank Sharma
  • 739
  • 8
  • 13
1

Use this code. Works fine for me. Share Something from Outside of an activity:

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);
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Pooya Hayati
  • 89
  • 1
  • 3
1

Since adding flags affect event_flow and stack_history it is better to pass the 'application context' to the non-activity from where you need to call an activity class in the following way:

"ActivityClassName.this" (While you pass the context in this manner it will contain all the detail and info that you need to call an Activity from a non-activity scenario)

So there is no need to set or add flags, this will work fine in every case.

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Musthafa
  • 251
  • 5
  • 4
1

If you use databinding, just get your context with

binding.root.context

This solved my problem.

kuzdu
  • 7,124
  • 1
  • 51
  • 69
0
Intent i= new Intent(context, NextActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
IntelliJ Amiya
  • 74,896
  • 15
  • 165
  • 198
0

If you are invoking share Intent in Cordova plugin, setting the Flag will not help. Instead use this -

cordova.getActivity().startActivity(Intent.createChooser(shareIntent, "title"));
Sandeep Kumar
  • 1,193
  • 13
  • 14
0

My situation was a little different, I'm testing my app using Espresso and I had to launch my Activity with ActivityTestRule from the instrumentation Context (which is not the one coming from an Activity).

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

I had to change the flags and add an or bitwise ( | in Java) with Intent.FLAG_ACTIVITY_NEW_TASK

So it results in:

fun intent(context: Context) = 
    Intent(context, HomeActivity::class.java)
        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Rafael Ruiz Muñoz
  • 5,333
  • 6
  • 46
  • 92
0

Kotlin version

val intent = Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
this.startActivity(intent)
Community
  • 1
  • 1
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
0

Calling startActivity() from outside of an Activity context get from your view

Don't

val context = activity.applicationContext
openBrowser(context, MenuUrl.TERM_CONDITION)

Do

   1. val context = binding.root.context // If you are using view binding
   2. val context = yourView.context // If you are not use view binding
    openBrowser(context, MenuUrl.TERM_CONDITION)

Thank You.

Kumar Santanu
  • 603
  • 1
  • 7
  • 14
0

For people coming from Xamarin.Forms or Xamarin.Android, In your Xamarin.Android project, use:

Xamarin.Essentials.Platform.CurrentActivity.StartActivity(intent);

Note that this might require Xamarin.Essentials v1.5 or above

As @Alex Volovoy mentioned, setting flags should be avoided as it will interfere with normal flow of event and history stack.

Junaid Pathan
  • 3,850
  • 1
  • 25
  • 47
0

If You are Using Chrome Custom Tab Then

 if (ctx.isPackageInstalled("com.android.chrome")) {
        customBuilder.apply {
            intent.setPackage("com.android.chrome")
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) //Add This Flag
            launchUrl(ctx, Uri.parse(URL))
        }

    }
Kumar Santanu
  • 603
  • 1
  • 7
  • 14