How can I synthesise a Task Stack using Intents with appropriated data? - android

Lets say I have 3 Activities defined as follows:
ACTIVITY PARENT
ClassActivity -
StudentActivity ClassActivity
StudentExamActivity StudentActivity
In the application's normal workflow, the user should be able to select a student in ClassActivity. This will start StudentActivity passing the student's content uri, represented here as <STUDENT_ID_URI> (to be handled by a ContentResolver), in the intent to specify what should be displayed. Similarly, an exam can be selected in StudentActivity by starting StudentExamActivity and passing its uri, represented as <EXAM_ID_URI>.
The question is: what if I need to start StudentExamActivity directly (e.g. from a notification or an external application)? How can I assure that when StudentExamActivity is started with the <EXAM_ID_URI> data, its parent (StudentActivity) will be started with <STUDENT_ID_URI> when the user navigates back to it?

You can use the TaskStackBuilder and use it something like this
TaskStackBuilder stack = TaskStackBuilder.create(context);
Intent classAct = new Intent(context, ClassActivity.class);
// This will clear any opened activities. Use if necessary
classAct.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Intent studentAct = new Intent(context, StudentActivity.class);
studentAct.putExtra("exam_id", 123);
stack.addNextIntent(home);
stack.addNextIntent(studentAct);
stack.addNextIntent(new Intent(context, StudentExamActivity.class));
stack.startActivities();

Related

Build a PendingIntent with a back stack

I have three activities (Home, Search, Destination), with which I could describe my UX flow. Home activity is my launcher activity, then its the search activity, which is happening to be the parent of Destination activity. So basically what I am trying to achieve is to have a notification, which starts the Destination activity and then when i press the back button I am supposed to go back to the Search activity and then to the Home, but the problem is that once I hit the back button from the Destination activity, the whole stack goes to the background...
In my manifest file, I`ve defined a parent activity for each of the child activities, like it is described here https://developer.android.com/training/notify-user/navigation
This is how my code looks like, when building the pending intent:
// Create an explicit content Intent that starts the main Activity.
Intent notificationIntent = new Intent(this, DestinationActivity.class);
notificationIntent.putExtra("test", destination);
//Intent testIntent = new Intent(this, SearchActivity.class);
notificationIntent.putExtra(DestinationAdapter.DESTINATION, destination);
// notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Construct a task stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Push the content Intent onto the stack.
//stackBuilder.addNextIntentWithParentStack(testIntent);
stackBuilder.addNextIntentWithParentStack(notificationIntent);
// Get a PendingIntent containing the entire back stack.
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
Could you please help me a bit? Am I doing something wrong?
your code should work, as described here:
https://developer.android.com/training/notify-user/navigation#java
make sure you define parent activity in manifest where relevant:
<activity
android:name=".DetailActivity"
android:parentActivityName=".MainActivity"

Resume activity from a android tv recommendation

I have some troubles with the management of recommendations (notifications) on an Android TV with the Leanback Launcher.
I use the google sample here to implement my own : https://github.com/googlesamples/androidtv-Leanback
Expected result :
I'm on my activity "MainActivity" (with a webview)
I press HOME, so I'm on the Leanback launcher with recommendation include mines.
I press on one of them
Resume activity "MainActivity" without recreate it with a new Intent with a new extra.
Actually, The resume of the activity without reload the activity works fine, below the creation of the PendingIntent :
private PendingIntent buildPendingIntent(Parcelable media, int id) {
Intent detailsIntent = new Intent(this, MainActivity.class);
detailsIntent.putExtra("media", media);
detailsIntent.putExtra("id", id);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(detailsIntent);
return stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
}
Current result :
I'm on my activity "MainActivity" (with a webview)
I press HOME, so I'm on the Leanback launcher with recommendation include mines.
I press on one of them
My activity receive "onNewIntent" event by in the extrat intent values I have always the same media.
This solution doesn't work, because Google said in a comment of the sample code :
// Ensure a unique PendingIntents, otherwise all recommendations end up with the same
// PendingIntent
detailsIntent.setAction(movie.getId());
So to differentiate all recommandations, I have to set Action with an ID, else, it will be always the last pendingintent sent to my activity. It's my current behavior, I receive in "onNewIntent" always the same "media" and "id" in the intent (the last one), whatever on which recommendation I click, I always get the same Intent.
But if I set the action with an "id", the activity "MainActivity" is recreated, so the resume failed, and the context of my webview is cleared my webview is reloaded :( but I get the good intent with the good media in the extra intent values.
Have you a solution to help me to have the behavior I want ?
To simplify my question, how can I resume my Activity B from a recommendation with the good pendingintent without reload my activity ?
Thank you in advance for your help.
I found a solution. I don't think it's the good one but it works for my case.
PendingIntent pIntent = PendingIntent.getActivity(this, id, detailsIntent, PendingIntent.FLAG_UPDATE_CURRENT);
return pIntent;
So, If I set the "resquetCode" with the id, so Android think it's a different Activity and resume it without recreate a new one.

Android: Can I create an activity conditionally?

For eg: I am using one Activity for Different UI pages with different he. So I want to check if an activity with a particular parameter in the intent exists. If it does just bring it to the top or else create another instance of an activity.
I have tried adding the flag FLAG_ACTIVITY_CLEAR_TOP to the intent but that does not solve my purpose.Here is some code: I want to create an activity only if there is a new title.
Intent intent = new Intent(activity, MyActivity.class);
intent.putExtra(DISPLAY_NAME, title);
activity.startActivity(intent);

How open same activity with different extras from widget

I have working with widgets which helpfull the user to show important data and open the application from widget.
My widget has 3 buttons and i need to open the app when user click on the different buttons.
i need to open same activity but with different data based on which button user clicked. I have passing different extra with intent
for example
Ist button i set user name as "Ranjith"
and for 2nd button i set user name as "Thomas"
and for 3rd button "Rixon"
But when the activity open it always shows Rixon the third one.
logIntent= new Intent(context, MainActivity.class);
earnIntent=new Intent(context, MainActivity.class);
connectIntent=new Intent(context, MainActivity.class);
logIntent.putExtra("user_name", "Ranjith");
connectIntent.putExtra("user_name", "Thomas");
earnIntent.putExtra("user_name", "Rixon");
}
remoteViews.setOnClickPendingIntent(R.id.bottom_of_widget_log,createPendingIntent(context, 0, logIntent));
remoteViews.setOnClickPendingIntent(R.id.bottom_of_widget_earn, createPendingIntent(context, 1, earnIntent));
remoteViews.setOnClickPendingIntent(R.id.bottom_of_widget_connect, createPendingIntent(context, 2, connectIntent));
AppWidgetManager manager = AppWidgetManager.getInstance(context) ;
manager .updateAppWidget(thisWidget, remoteViews);
You have to check the android:launchMode option in your Manifest,concerning the Activity.
As said in the Documentation,
An activity with the "standard" or "singleTop" launch mode can be instantiated multiple times[....]
In contrast, "singleTask" and "singleInstance" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such task.

Start Activity and Bring it to Front

I have a service that once it completes a task it launches an intent to start an activity from my application. Like this:
Intent i = new Intent(MyService.this, MyActivityToBringToFront.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
//i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
This service can be running even after my application has been closed. When this is the case and my application is closed I need it to bring the activity to the front of whatever the user is currently doing. So if the user is in a different app I need my activity to pop up in front. Is this possible. None of the flags had any effect. Basically I need it to be like the system phone application. When you get a phone call it always brings the phone to the front. How can I do this? Thanks!
First of all you need to keep context in memory to make intent's.
Secondary you need a mechanism that can re-obtaining your context every 24 hours because usually context stay alive in 24 hours.
After.
Launching Activity from service :
Intent dialogIntent = new Intent(getBaseContext(), myActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);
source : https://stackoverflow.com/a/3607934/2956344
To push activity on top add
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Intent i = new Intent();
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setAction("android.intent.action.VIEW");
i.setComponent(ComponentName.unflattenFromString("com.example.package/com.example.package.activityName"));
startActivity(i);
Intent i = new Intent(MyService.this, MyActivityToBringToFront.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity( i);
And API reference is
If set, and the activity being launched is already running in the
current task, then instead of launching a new instance of that
activity, all of the other activities on top of it will be closed and
this Intent will be delivered to the (now on top) old activity as a
new Intent.
For example, consider a task consisting of the activities: A, B, C, D.
If D calls startActivity() with an Intent that resolves to the
component of activity B, then C and D will be finished and B receive
the given Intent, resulting in the stack now being: A, B.
The currently running instance of activity B in the above example will
either receive the new intent you are starting here in its
onNewIntent() method, or be itself finished and restarted with the new
intent. If it has declared its launch mode to be "multiple" (the
default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same
intent, then it will be finished and re-created; for all other launch
modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be
delivered to the current instance's onNewIntent().
This launch mode can also be used to good effect in conjunction with
FLAG_ACTIVITY_NEW_TASK: if used to start the root activity of a task,
it will bring any currently running instance of that task to the
foreground, and then clear it to its root state. This is especially
useful, for example, when launching an activity from the notification
manager.
launching an activity from a service isn't always a good idea. You may want to use notification for that. If the user clicks on the notification, thats the time you show the Activity.

Categories

Resources