Reputation: 10147
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?
Upvotes: 471
Views: 364328
Reputation: 574
If you encounter this issue, while using Kotlin Multiplatform (KMP), and you have Intent.FLAG_ACTIVITY_NEW_TASK
set, make sure you pass the Activity context, not the applicationContext
. The flag is not needed anymore if you pass the activity context. I implemented it as follows:
commonMain:
@Composable
expect fun getLocalContext(): Any?
view(getLocalContext(), ...)
androidMain:
@Composable
actual fun getLocalContext(): Any? {
return LocalContext.current
}
actual fun view(localContext: Any?, ...) {
localContext as Activity
val intent = Intent(Intent.ACTION_VIEW)
val mBundle = Bundle()
startActivity(localContext, Intent.createChooser(intent, "Open with"), mBundle)
}
iosMain:
@Composable
actual fun getLocalContext(): Any? = null
actual fun view(localContext: Any?, ...) {
// Ignore localContext here
}
Upvotes: 1
Reputation: 701
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))
}
}
Upvotes: 1
Reputation: 4336
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.
Upvotes: -1
Reputation: 701
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.
Upvotes: -2
Reputation: 10256
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.
Upvotes: 130
Reputation: 7524
If you use databinding, just get your context with
binding.root.context
This solved my problem.
Upvotes: 1
Reputation: 1487
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);
Upvotes: 2
Reputation: 2218
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);
Upvotes: 67
Reputation: 2509
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);
Upvotes: 12
Reputation: 10767
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);
Upvotes: 3
Reputation: 40255
val intent = Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
this.startActivity(intent)
Upvotes: 0
Reputation: 3219
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.
Upvotes: 16
Reputation: 308
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);
Upvotes: 10
Reputation: 261
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.
Upvotes: 1
Reputation: 313
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....
Upvotes: 2
Reputation: 5472
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)
Upvotes: 0
Reputation: 89
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);
Upvotes: 1
Reputation: 779
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.
Upvotes: 1
Reputation: 1293
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"));
Upvotes: 0
Reputation: 17
Intent i= new Intent(context, NextActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Upvotes: 0
Reputation: 2395
Instead of using (getApplicationContext)
use YourActivity.this
Upvotes: 81
Reputation: 1204
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 ...
Upvotes: 8
Reputation: 68474
Either
Or as a last resort,
_
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.
Upvotes: 709
Reputation: 31
Intent viewIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
viewIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(viewIntent);
i hope this will work.
Upvotes: 1
Reputation: 260
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.
Upvotes: 2
Reputation: 669
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.
Upvotes: 3
Reputation: 29
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.
Upvotes: 2
Reputation: 5134
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
Upvotes: 4
Reputation: 12455
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...
Upvotes: 14