In the starting activity of my app I show a dialog to user and ask if he wants to see some contents in my website or not.
If he clicks No, the dialog disappears and I call continueActivity() to do some process and go from current activity to MainActivity.
If he click yes, I want to open the webpage in the external browser and again I call continueActivity() to do some process and go from current activity to MainActivity.
The problem is in positive state. This is my code in positive state:
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.aaa.ir"));
startActivity(browserIntent);
continueActivity();
Because of calling continueActivity(), the external browser can't open and if I don't call continueActivity(), the URL opens in the external browser and the app sticks in the current activity.
So how could I open the URL and at the same time, continue the process and go to other activities.
I usually use
startActivityForResult(browserIntent, BROWSER_REQUEST);
and override onActivityResult(int reqCode, int resultStat, Intent intent)
if(reqCode == BROWSER_REQUEST) {
continueActivity();
}
Once you call startActivity, your current Activity will follow through the exit of the Activity lifecycle. This is unavoidable.
If you have processing you want to continue in the meantime, you should consider a Service. If you want the App to return to its current state, you need to store relevant data and load your Activity to its previous state (or next intended state).
in both ways ContinueActivity is opening. i don't know you architecture. You could just add to intent some extra like
intent.putBoolean("openExternalLink", dialogResultHere);
Then in continueActivity you will got this intent like
getIntent().getBoolean("openExternalLink")
also dont forget to delete this option, otherwise you will open browser each time after Activity recreation (screen rotation, minimize, etc.)
getIntent().removeBoolean("openExternalLink");
P.S. signatures of methods could be littlebit different, but general idea is here
Related
I have a problem regarding Android task and intent management.
Scenario
User gets a push with a deep-link into the app.
We show a notification putting the URI into the Intent Data.
User clicks the notification and is taken into the app and redirected to some Feature1Activity described by the deep-link.
User looks around, and backs out of the app.
Later, user opens the app from history (long-press home or multitasking button).
Now the same intent that were used from the notification (with the deep-link in the Intent Data) is used to start the app.
Hence, user is taken into the Feature1Activity again.
Problem:
Starting the app from history (long-press home or multitasking button) does not reset the Task (which it does when launching from app icon).
I understand that starting an app from history is not supposed to reset the task since it is intended to be used as "get-right-back-where-you-were". However, in my case this is an issue since the launch of the app from a notification is a one time thing.
Anyone else encountered this problem? Anyone know any solution?
More in-depth
The intent inside the PendingIntent is built like this:
Intent intent = new Intent (Intent.ActionView);
intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags (Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
intent.setData (Uri.Parse (DEEP_LINK_URL));
I found out about the FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET just this day and really thought that it would git rid of my problem but it made no difference.
There are three activities of interest:
SplashActivity (main launcher & listener of the deep-linking schema -- this activity just redirects either to login or OverviewActivity)
OverviewActivity (authorized user's main activity)
Feature1Activity (any feature that the deep-link is pointing to)
What happens when the user clicks the notification is that the SplashActivity acts as a listener for the schema and converts the deep-link url to two intents to start up OverviewActivity and Feature1Activity using Activity.startActivities (Intent[]).
When I look at the intent from the notification inside SplashActivity it always contain the deep-link in the Data.
One work around
There is a work around, setting some booleanExtra field to the notification intent (for instance "ignoreWhenLaunchedFromHistory" = true) and then check in SplashActivity before redirecting
boolean fromHistory = (getIntent().getFlags() & FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY;
if (fromHistory && getIntent().getBooleanExtra ("ignoreWhenLaunchedFromHistory", false))
// Don't follow deep-link even if it exists
else
// Follow deep-link
Except that it hackish and ugly, can you see any problems with this work around?
EDIT: The work around only works when I am responsible for sending the Intent with the deep-link. Since no external source can know about the "ignoreWhenLaunchedFromHistory" extra.
From what I get, maybe using android:excludeFromRecents="true"on your manifest (as a property for the Activity declaration) might ameliorate the issue?
I have searched a lot on this.
But, I have my code working to open my app using a custom intent URL. This URL is usually delivered via email.
When I click on the link, it opens my app fine and everything seems to be working; however, it opens in the context of the email application.
For example, if I click on the link from Gmail, when I open multitasking, I have to click on Gmail to return back to the app that just opened.
I would think it should open my app and I can continue using Gmail while my other app is running.
Any thoughts on this?
Make your URL look like this:
intent:#Intent;launchFlags=0x10000000;component=com.mycompany.myapp/com.mycompany.myapp.MyActivity;end
This URL contains the launchFlag for Intent.FLAG_ACTIVIY_NEW_TASK, so this will launch your app in a separate task (outside of the email client or browser or whatever).
EDIT: Add additional details based on OP's comment
You say that you are using a URL like this: http://com.my.app/5058749
In that case you must have used an Intent filter to get Android to open your app by specifying an <intent-filter> on a certain <activity> in your manifest. There are several things you can do to deal with the problem of the launched Activity ending up in the same task as the Activity that launched it:
1) If the Activity is always intended to be the root (starting, first) Activity of a task, you can put the following code in onCreate() after the call to super.onCreate():
if (!isTaskRoot()) {
// Activity was launched into another task. Restart it in its own task
Intent intent = new Intent(this, this.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
return;
}
2) You can set the launch mode of this Activity to singleTask in the manifest by adding
android:launchMode="singleTask"
to the <activity> definition. This will cause the Activity to be launched in its own task but this launch mode has other consequences that are more subtle and so you need to be careful about using it. In general I don't like to suggest this because it tends to create more problems than it solves.
3) You can determine if your app was launched from the browser or email client by examining the Intent used to start it in onCreate() (The Intent will have the data set to the URL when launched via the browser or email client). You can then decide if you want to restart it in its own task by using the code I've supplied in option 1 above.
Add Intent.FLAG_ACTIVITY_NEW_TASK and Intent.FLAG_ACTIVITY_CLEAR_TOP flags(intent.SetFlags() to your intent. Your actitivty will be opened in a new task and this activity will be the root of your new stack.
This is the default behavior with android, but to override it, you need to pass
Intent.FLAG_ACTIVITY_NEW_TASK
Intent.FLAG_ACTIVITY_CLEAR_TOP
with your intent.
I am little confused about getting data from intent of an activity, here is what I am trying to do.
I am opening my first activity
I press home button and my activity(application) goes in background
I go to download folder and select one doc file it gives me Open with feature with my application in list.
I select my application.
Now instead of getting resume it calls create method of activity(I think its ok because second instance of my app(activity is created))
Here I try to get data from intent using intent = activity.getIntent();
But I dont get anything(getting null expecting path of this doc)
If I first open my app with Open with feature(No background activity right now) I get file path successfully but when I pres home button and my app goes background again and if I press my app from application list again intent has same data(expecting null in this case.)
What I am trying to achieve:-
I am simply trying that if user is coming from application list intent data should be null and if he is coming from Open with function then he intent data should be path of file.
One more thing I am trying this behaviour in Appcelerator Titanium but as this is native behaviour(handling life cycle of activity and I can do this in titanium) but having no luck.
Thanks.
I some what manage this by giving my activity as 'singleInstance' in manfiest file. So now I can be sure that at a time same instance is running.
Now for handling intent data I am registering onNewInstance method. By using this intent data is get affected everytime when I comes from background or when when I select any file to open with my application.
Thanks.
I am implementing oauth login in Android, and I'm stuck on one point. I am required to redirect to the native browser to initiate the login (rather than use an embedded WebView of my own), but that is causing issues with the back stack. My goal is simple: return to my activity after the redirect with no trace of the native browser in the back stack. Here is the closest I've come so far:
To initiate the login from my activity I use:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
context.startActivity(intent);
I have a separate activity to receive the return redirect and handle the rest of the login process. I don't really care whether it's a separate activity or not, it is just my current solution. In its manifest I set android:noHistory="true". Once it finishes the login process, I attempt to return to the first activity using code like this:
Intent intent = new Intent(context, OrigActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
However, this ends up creating a second copy of the original activity, and when I press back it returns me to the first copy. In other words, it does not seem to respect FLAG_ACTIVITY_CLEAR_TOP. Did I miss something simple to make it work, despite all my searching? Or is there some other way I should go about all of this?
Edit: It turns out the problem stems from the fact that the browser is launched in a separate task. From some Android documentation:
... if your application issues an intent to open the Android Browser, its activity is not placed in the same task as your application. Instead, either a new task starts for the Browser or, if the Browser already has a task running in the background, that task is brought forward to handle the new intent.
If I set my original activity's launch mode to singleTask it properly brings it to the foreground instead of creating a new copy, but a new problem occurs. The browser is now in the back stack behind all of my activities, so now it seems FLAG_ACTIVITY_NO_HISTORY is not being respected. I'm not sure if that brings me any closer to a proper solution ...
Edit 2: Correction: if the browser was not running before I launched it, everything works perfectly. However, if it WAS already running FLAG_ACTIVITY_NO_HISTORY seems to have no effect on it.
What you're seeing makes sense because calling the browser with the FLAG_ACTIVITY_NO_HISTORY wouldn't remove back stack from PRIOR to the start of your application.
I'm working on an app that launches the browser activity to perform a Twitter OAuth authorization. This process uses a callback url which will re-launch the activity that started the browser activity in the first place.
My problem is that the browser pages remain in the history stack and when the user then clicks back from the preferences activity that launched the browser in the first place, they don't go back to the app's main activity, but instead are brought back to the browser. I've tried adding flags to the launching intent to prevent history and reset on clear, but it doesn't seem to work when running on my phone, only on the emulators.
Here is the code I'm using to launch the browser activity:
Intent webIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl));
webIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
webIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
webIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
ctx.startActivity(webIntent);
Anyone have any idea what might be wrong?
Set the activity flag to Intent.FLAG_ACTIVITY_CLEAR_TOP after starting it. This way, the task will be deleted form the app stack so your main activity remains the top one on every new launch:
ctx.startActivity(webIntent);
browserIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
call
finish();
after
ctx.startActivity(webIntent);
Hi i have the same problem at the moment. I think the solution is to start the activity you want to return to with a special flag:
Intent intent = new Intent(this, acticityToReturnTo.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
The problem is that is does not work (on 1.6 at least).. But maybe someone finds a solution for this. I think FLAG_ACTIVITY_CLEAR_TOP is exactly what we.
I found that Intent.FLAG_ACTIVITY_NO_HISTORY works only if the browser was not running before. If I restart Android and run my app which call browser everything work well. But when I start browser before my app, browser will stay in history.
Here is related question also, but with no really working solution
How can I do that in Android. Activity -> WebBrowser -> Acrivity, but Press Back not see the WebBrowser