I have following activities. 1) Main activity 2) Activity 1 3) Activity 2
This is the way Activities is connected together
Main Activity -> Activity 1 -> Activity 2(Create Background Async Task) So "Activity 1" is child activity and "Activity 2" is a subchild activity. And creating Background Async task from "Activity 2"
So Let's say I am currently on "Activity 2" screen and Backround Async task is running. Now after some failure event on "Background Async task", I want go back to "Main activity". What can be good way to do this?
Few way I am thinking is, 1) To restart the app completely 2) To create new Intent of Main activity from Background Async task just like we created "Activity 1 & 2".
I am not sure which one from this is good to use. Is there any other way to do it?
I am kind of newbie to android. I am currently using BroadcastReceiver(on Activity 1 & 2)to finish current activity when Background Async task broadcast failure event but sometimes it jump to "Main activity" and sometimes jump to "Activity 1". So not working as I am looking for.
Will you please suggest a good way to do this?
[Sorry, I had to ask this question once again. Because old question was deleted]
#Rohit, I tried way you suggested to finish Activity 1 before going to Activity2. That also works but It create one another problem.
After doing this, when I press back button it directly go to Main activity rather than Activity 1 since it no longer exist.
Is there any solution which can get this both thing working? I want to jump to Activity 1 when back button is pressed. And I want to jump to Main activity when Background Async task created from Activity 2 find problem.
[Edit]
Let me describe more specific case.
Main Activity list open Wifi access point based hardware.
When clicked on particular listed access point, It opens Login activity and ask for user id & password for hardware access. Login activity onCreate function also create TcpAsyncTask background task which will communicate with hardware(which has WiFi accesspoint feature) for authentication and data passing.
When user enter login detail and click on login button, It will create momentary background task LoginDeviceAsyncTask. This task will communicate to hardware via TcpAsyncTask created earlier to verify authentication. If authentication is successful, it will create Navigation activity using startActivityForResult.
In the Navigation activity, It list options for opening specific window e.g. Dashboard. History. When user select Dashboard from options, it creates Dashboard activity using startActivity. When user select History from options, it creates History activity using startActivity.
So if Dashboard activity is opened, it display some data periodically received from hardware using TcpAsyncTask(created earlier in Login activity)
Similarly if History activity is opened, it display some data periodically received from hardware using TcpAsyncTask(created earlier in Login activity)
Dashboard/History activity has options to move to History/Dashboard activity directly. For this it creates selected activity using startActivity and finish current activity.
Now my problem is,
Let's say I am in Dashboard activity and it is displaying data received from hardware using TcpAsyncTask. Now somehow TcpAsyncTask fails to communicate with hardware and at this point I want to move to Main activity directly.
In TcpAsyncTask, I don't have context of activity like Navigation/Dashboard/History which was created after TcpAsyncTask. May be I can get this context in TcpAsyncTask using some MainActivity variables which is updated as per create/finish. Am I correct?
I am current broadcasting to close from TcpAsyncTask and receiving broadcast message in Navigation/Dashboard/History activity using BroadcastReceiver and finish particular activity which received broadcast close message. But sometimes it jump to Main activity and sometimes it jump to Navigation activity when sendBroadcast from TcpAsyncTask to close.
Pass Context in your AsyncTask and through that you can kill your Activity 1 as well as Activity 2
((Activity)context).finish();
You can do this for both activities by passing context of both.
One possible solution is to start Activity 2 with startActivityForResult() then during its processing, you can call setResult() to indicate success or failure. In Activity 1, override onActivityResult() and detect the result of Activity 2. If Activity 2 indicates a failure, simply call finish() on Activity 1 to return to the main activity.
Firstly, remember that code being run in an inactive activity when it is not in the foreground cannot be relied upon. So you should not rely on background async task. Instead, use a Service which does the background processing; this is precisely what Services are meant to encompass (among other persistent processing). While it is quite a lot for a beginner to learn, it will save you a LOT of trouble long term, as its lifecycle is far easier to manage than complex webs of activities and their relationships and lifecycles.
You should read up on android "Back Stacks". If you finish an activity, the previous activity on the back stack will be displayed. These are like the history browsers maintain that determine how browser back-buttons to operate.
So what you need is the main activity spawning a new instance of the sub-activity. Then when the user navigates the back button, the previous activity in the back stack (your main activity) will be resumed. This will not need intents.
However, for an activity to be triggered by a background processing task, I strongly recommend using a Service and intents to co-ordinate it all.
Related
How can i transfer data between two activities, without actually move to that activity? The scenario is as follows:
Activity A is a splash screen. While the splash screen is showing, some data is being generated in the background of type ArrayList. After This data is loaded, i need to start Activity B (lets say a Login screen) and just before that i need to transfer the data to Activity C. I know i can use PutExtras for transferring data, but wont this run the target Activity instead only sending the data?
Thanks
The full flow of the app is as follows:
Activity A (splash screen) --> Activity B (Login screen) --> Activity D (some user interface and buttons) --> Activity C (the activity which should be able to load the data generated in the splash screen upon certain Button press).
I think You don't fully understand life cycle of Activity and application.
Rule of thumb, there is always just one activity, (it is the worst scenario when each activity has to be recreated when You go back to it) the one visible at the moment. You can't do things like start activity but don't show it yet or anything like this.
If You have expensive task to do like downloading data do it in AsyncTask
if this task has to be start and finish when You enter and leave Activity A use fragments
if it has to finish once You start whether Activity A is still existing or it was already destroyed use services
Places You can store this loaded data so it may be easily accessed later form any Activity is database with help of Loaders(loader is optional but really nice) or SharedPreferences.
If you want to pass data to an activity that is running and not start a new instance of that activity you just need to set flags on your intent. For example:
Intent i = new Intent()
i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
will not re-launch an activity if it is already running at the top of the stack. If all you want to do is get data to Activity C which is running without starting it again you could try this or one of the other flags. There's a bunch of them. Just look look through the list and see if one fits your needs.
I hope you can help me understanding the Android Lifecycle and how I can manage navigation between several kinds if activities. Suppose the following scenario:
Activity A "MainMenu" is started: User clicks on a menuentry
Activity B is started and UI is loaded with content from local database
user interacts with Activity B
user presses Backbutton and returns to Activity A
user presses again the same menuentry for returning to activity B
At the moment: The activity is loaded from scratch
Whished: The previous instance of Activity B with all its UI entries and User interactions should resume
I thought of saving all activities in a static manager. If a activity is started, the manager looks if it has already been started previously. If so, resume the previous activity else startActivity(ActivityA). Is that a good way of handling those navigations? How can I directly resume via code an instance of an activity?
Or is there another way to do this in a better way?
Thanks in advance!
greetings,
faiko
Your not going to be able to "cache" an activity once its off the stack. Activities are very quick to start, Im guessing its your database stuff that is slowing you down. That you could do something about.
In theory, if you knew the user was going to click on entries multiple times going from A -> B, you might want to just load the DB stuff into memory in Activity A, and then send it via Parcel into B. Then when you go back to A, its still in memory, and it will be to go back to B instantly.
If you are unsure of whether this is true, try debugging it and stepping through. You will see the activity is launched fairly quickly, but you need to identify which operations are lagging. From your description above it is probably your database calls, but it could be other things like network calls, or other long standing calls
The life cycle of android activities makes it not possible to start a new intent but keep the old state.
You should save the state of the activity by saving the fields and restore it to this state when needed.
You cannot resume an instance of an activity in the scenario that you have posted. Because due to the android lifecycle, when you press the back button on activity B that activity is destroyed, with all its states and information.
One option to get the information to persist is to extend the Application class and save the information into some variables inside the application class. Although alot of what you do even then can be garbage collected if the system needs the memory. I dont believe there is any good way to have that information persist through the activities even using Jameo's solution, if activity A is killed then if you return to Activity A from activity B then that activity is reloaded and the database access has to happen again.
I have the following flow in my code:
Activity1 : startActivity(Activity2) --->
Activity2: startActivity(Activity3) --->
Activity3: startService(MyService) --->
MyService: startActivity(Activity4)
Each Activity above shows a single view and represents a step in a 4-step setup. The final Activity - Activity 4 - is started after some setup work is done inside MyService, which basically tells the user,
"The service has started, you can close the application by pressing Back or Home button"
When the user presses Back or Home, I want to destroy Activities 1-4 , and only have MyService running. Also, after stopping the Application as above, when the user navigates back to the Application via the menu and starts it, I'll be checking if MyService is already running. If it is already running, I don't want to show Activities 1-3, I want to show another Control Panel View (Another Activity), which says,
"Dude, the service is already running, do you want to Stop or Restart it?"
This view will have a Stop and Restart button, to do the appropriate tasks.
My Questions:
How do I stop Activities 1-4 from inside Activity 4 when Back or Home is pressed,safely? My thought was to add a static stopActivity() method to each Activity, and calling Activity[1-3].stopActivity() from onBackPressed() or onPause() of Activity4. Then inside each stopActivity(), I'll call finish(), thus ending each Activity. But is it safe and efficient to do it this way?
The flow I have illustrated above, is it the optimal way of doing things, or is there a cleaner way? I have BroadcastReceivers registered in these Activities, so I need to perform clean exits for each Activity, without leaked receivers, or worse, crashing the App or affect the User's phone due to unclean exit strategies.
Thanks for your suggestions.
You don't need to stop activities, Android will do it for you. Start your activities using intents with the flag FLAG_ACTIVITY_NO_HISTORY so they won't appear when the user presses back. Those activities will be stopped as soon as the user leaves them.
In the onStop method of each of your activities, write any code you want to deallocate memory if there is something you want to deallocate manually, although that wouldn't be necessary because Android will deallocate it for yourself when the device is short on memory. In those onStop methods unregister any BroadcastReceiverpreviously registered.
Let's assume I have 2 activities: Activity 1, Activity 2. I am starting Activity 2 from Activity 1. Activity 2 - is activity with image and progress bar to display the progress of executing some background task in it which is started in service.
When I try to press hardware Back button from Activity 2 it brings me back to Activity 1, so I can start Activity 2 again even if there is service still running.
So the question is such: How can I prevent such behaviour. I need to start Activity 2 only 1 time and not exit from it while the work is not finished?? And another case is that I can stop my application from Task manager, but service will be working and after that I can run application again - with new service, while old will be still running? What mechanisms are there to prevent such behaviour? Thanks.
You can bind to a local service from your Activity class when it is starting up. Once bound, your Activity can call any public methods declared by that service. This would allow your Activity to bind to the service, then check to see if the service is currently doing any work. You might make a method like isRunning() or similar. If the service is not currently doing any work, you might want to start a new job. If it is already executing some task, you could then display the current progress of that task.
You should read the Local Service Sample article on the Android developer site to get an idea how to do this.
I want to start two activities A and B. I want A to be in the foreground and I want B to be in the background.
At some point, I want to switch the order of the two Activities: A is moved to the background and B is moved to the foreground.
But here there are three different activities comes live, Acitivity A will start actvity B in bacground and activity C in foreground
You can use below link to start one of your activity in background
Sending Activity to background without finishing
Other activity which you want to start in foreground can be started normally.
You don't really want to do this. Activities in Android are meant to be shown to a user and be interacted with. If you launch more than one Activity, there is no guarantee that your other Activity will even be around when you need to display it.
Perhaps it would help to know more about what you are trying to accomplish.
If you want to have code running in the background, you should consider writing a Service or an AsyncTask.
Service: http://developer.android.com/guide/topics/fundamentals/services.html
AsyncTask: http://developer.android.com/reference/android/os/AsyncTask.html
Your question is not clear, if you are asking whether or not you can start two activities at the same time? The answer is no, Android's mechanism is such that an activity can start another activity and so forth.
Read this for more reference on how you can start and use activities.
http://developer.android.com/guide/topics/fundamentals/activities.html
Moreover read this to understand how you can switch between your activities to get the desired result http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html
There are 2 ways to do what you want:
The first way is to launch one of the activities (the one you want "in the background") and have that Activity launch the other one (the one you want "in the foreground") immediately (in onCreate(). When the top Activity is finished, the other one (the "background" Activity) will be shown.
The second way to do this is to simply launch the Activity that you want to be in the "foreground". In this Activity you can override onBackPressed() to launch the other ("background") Activity. In this way, the user experience is as you desire, but you don't need to launch the "background" Activity until it needs to be shown to the user. Depending on your requirements, you can also switch back and forth between these 2 activities, by simply calling startActivity() with an Intent where you have set Intent.FLAG_ACTIVITY_REORDER_TO_FRONT when you want to move from one Activity to another. In this case, Android will bring an existing instance of the target Activity to the front of the task (if it exists) or will launch a new instance of the target Activity (if one does not already exist).
However, none of your terminology is correct and that causes problems when communicating with other developers. An Activity isn't in the "foreground" or the "background". These terms are used when talking about tasks. A task is in the "foreground" when the user is interacting with it and it is shown on screen. Other tasks are in the "background". A task is made up of one (or more) activities, and they are stacked in such a way that the top-most Activity is the one that the user is interacting with. The other activities in the task are not "in the background", they are just paused.