My simple structure:
List.java (Activity A)
New.java (Activity B)
Steps:
Start A and use startActivityForResult() to turn to B by a button.
Then in B, use Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); and startActivityForResult() to take a photo by call up camera.
After that, onActivityResult() in B is called. Then I click a button to set a resultcode and close B.
However, B is closed, but onActivityResult() in A is never called.
If I skip the step to take a photo, click a button to set a resultcode and close B. onActivityResult() in A will be successfully called.
I'm just confused about these two situations. Please anyone tell me why the first situation happens?
Thank you very much.
its happened when your first Activity would be destroy..
I tried to replicate what you are describing but with no luck:
http://androidgecko.com/project.zip
Have a look and tell me if I missed something.
Know that when another application is going to the front (camera in this case) android might kill previous processes to free memory (not even activities as google docs describe, but whole PID) which might cause your problems.
I have seen this behaviour especially on older phones when you launch Gallery or Camera applications from your application.
This is one of the reasons why Applications like Facebook have their own implementation of Gallery/Camera (so that PID is not killed because its the front one).
However.. even if PID is killed what you should see is Activity recreation, meaning its onCreate with savedInstanceState not being null should fire.. and then onActivityResult..
check out my example and let me know how I could reproduce your issue.
Related
My application is launched using a tag, and based on the information contained in tag, it further proceeds. Now my app can also be started by using touching icon, and later it asks user to touch the tag. Small flow would be as below.
So MainActivity may contains tag data(if started from TagProcessorActivity), or may not contain data (if started from icon launch). Data is passed as intent extra value from TagProcessorActivity to IconLaunchActivity then to MainActivity. After main activity, app operation proceeds. When I leave the main activity, all my previous activities gets finish. I have checked onDestroy() is called for each activity. Now if I logout after MainActivity, (Logout simply a feature that closes all existing activity), and relaunch my application from recent app, my tag details still appears in MainActivity, which I dont know why.
To make is more clear my questions are:
1) Why activity which was destroyed still contains the information from previous launch.
2) I know about removeExtra() method, but is there some better options to tackle this problem.
3) and none the less, is there some thing wrong in my code or android is keeping that instance of intent extra?
PS: Not clear which piece of code to post, so if required feel free to ask for code.
Applications never exit in Android. onDestroy only destroys the activity, not any static variables left in the app. These will keep their value the next time an Activity is launched. This can be combined with some other features (like launching from the recent tasks menu causing you to launch the same intent) and this is the behavior you will get. The answer I always used was to detect this case (by checking the intent, there's a field that says if this is a restart or fresh), and ignoring the intent extras if so.
A finished task launched from Recents (as opposed to home screen launcher icon) will receive the old Intent, including its Extras, Data, etc. There is a way to know that it was launched from Recents so you can handle the Intent appropriately.
protected boolean wasLaunchedFromRecents() {
return (getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY;
}
In my humble opinion, that flag is poorly named (other flags referencing the Recents list actually use that word, e.g. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS, FLAG_ACTIVITY_RETAIN_IN_RECENTS) and the documentation was never updated to reflect the fact that many popular Android devices have a dedicated button for Recents:
This flag is not normally set by application code, but set for you by the system if this activity is being launched from history (longpress home key).
I'm making a simple e-book reader app, and an activity can be called by many cases.
I'd like to distinguish callee activity to know its origin action in case of
From my another activity: this can be easily solved by
StartActivityForResult from calling activity.
Called by back button click from other package app after share action ("whoops, I missed to click share button, and then back.").
Switched by user's multitasking choice.
Called by user click at the start screen: this might be known by MAIN entry point at the android manifest.
How to know above cases?
I have no idea why you would need to do this but...
1.From my another activity: this can be easily solved by StartActivityForResult from calling activity.
Yes, as long as the calling Activity is your own as you can't guarantee any 3rd-party code will use startActivityForResult(...). You can, however, use getCallingPackage() and getCallingActivity() in other cases.
2.Called by back button click from other package app after share action ("whoops, I missed to click share button, and then back.").
When the user presses the BACK button your Activity isn't being "called" - it's simply being resumed or re-started. The original calling app/Activity/method will still hold true - there is no way to ascertain that this has happened as the normal Activity life-cycle methods (onStart() and onResume()) are always called even when an Activity is first created.
3.Switched by user's multitasking choice.
If you mean using the "Recent" apps view, the same applies for my answer to 2. above.
4.Called by user click at the start screen: this might be known by MAIN entry point at the android manifest.
In this case onCreate() will be called although if your Activity is simply stopped for whatever reason, it may simply be restarted depending on the launch mode you use.
In short, I can't see you being able to gather much in the way of any accurate information as to how your Activity becomes active.
I am not too sure about the actual way for the above question as I am too a new guy in android.
But to the best of my knowledge... called by back button and switched by user's multitasking leads the activity to enter pause state.
So you can access it from "onPause" method in your activity.
I have an Activity that should only get created once. That is, onCreate can only be called once. If it's called again, I want the Activity to do nothing.
Is it advisable to do the following?
protected void onCreate(Bundle savedInstanceState) {
this.setTheme(android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
super.onCreate(savedInstanceState);
if(onCreateWasCalledAlreadyBoolean) {
setResult(RESULT_OK);
finish();
return;
}
//Do other stuff here
}
I assume you understand how the activity life cycle works. I mean, you are not trying to avoid something that does not apply here (thinking that onCreate may be called multiple times whenever it just onRestarts etc.).
Technically, it's perfectly fine.
However, you should be worrying more about why you need to call your activity ("A") again if it shouldn't be created at all, if that's what you're thinking.
If you've caught yourself checking if your activity A was already "called" (?), this could mean the previous activity ("B") has a mistake in the logic flow of the app, and that B instead should be checking if it must in fact start that activity A. I mean, if you need to decide if you must call an activity, check before starting it.
I don't think that's applicable if you're restarting the activity (e.g.: go Home, then navigate back), but then again you should be restarting it from where you left (B for what I can tell). You won't be navigating back to A. And you didn't give much detail, so I'd guess this is some kind of splash screen, like evilmage93 said.
If that's indeed some kind of splash screen, I would advise to show it whenever the user navigates back all the way to remove your app from the task stack (contrary to his advice). In other words, whenever the user restarts the app from its "front door".
Although that's ultimately a design decision, I prefer to see the splash screen whenever the app is being loaded ("entered") in the stack for the first time, and it should work fine if you (obviously) finish A before calling B (the splash screen is supposed to finish itself when done, even in its first run). It's a matter of consistency: the same app should behave the same way whenever the user performs the same task (start app from its "front door").
Still, I answered your question covering some general aspects because you asked in such way.
// edited:
Finally, by looking at that onCreateWasCalledAlreadyBoolean I'm afraid you may be trying to reinvent part of the activity life cycle mechanism. In this case, don't: proceed with your regular activity logic because the user expects that behavior. Generally I wouldn't advise people to break the normal loading of an activity just because it was killed and restarted by the system.
I don't see why not. Wouldn't it be simpler to not restart the activity at all though?
What are you worried about NOT being okay? Performance..Uncaught exceptions..Code clarity?
I'm trying to kill 2 activities on the onclick of a button. The current activity and the previous activity. Using their pids. I'm just able to kill one activity. Why does this happen?
public void onClick(View v) {
android.os.Process.killProcess(pidofmain);
android.os.Process.killProcess(android.os.Process.myPid());
}
If I see in my logcat, The activity with pid "pidofmain" is getting killed whereas the current activity is not getting killed.
"pidofmain" is an integer i received from the previous activity using an intent.
Leave process killing to the OS. This is bad for any kind of program in a timesharing OS. If you want to conserve memory or something like that, let the OS handle it.
Also you can't really know if the process was correctly killed because well, if it is you wouldn't know, and if it doesn't you were not supposed to do it.
What do you want to do this for?
A much better way to do this is to call finish() for the current activity. You can also signal the previous activity to finish if it calls the current activity using startActivityForResult(Intent). The current activity would call setResult(int) before calling finish() to send a return code back to the previous activity. The previous activity can test the return code in onActivityResult(int, int, Intent) and also call finish() based on the result code.
Killing processes should be left to the OS. Once the activities finish, the will kill it off if it needs the resources. Otherwise it can let it around, which might help speed up a relaunch of your app if the user wants to run it again.
This isn't a definitive answer, but more like some thoughts that I have but it's too late for my to fire up Eclipse and prototype them. If it doesn't help you let me know and I'll try to look into it deeper tomorrow night.
A few thoughts (I hope they help):
1) Android apps really are single-threaded, and your main activity controls all the dispatch events (including events to what I assume to be a second thread that you created). If you kill the main activity, I'm pretty sure that your application would terminate execution immediately following your first call to android.os.Process.killProcess(pidofmain), and you'd never make it to your second call because you would have killed your entire application. Again, this is assuming by the variable name pidofmain that you are killing the main UI thread and not just an activity called main.
2) I'm a little curious also about where you got pidofmain? It sounds like you have three activities total, and in the first activity you get it's process id and send it to the second activity in an intent bundle, which also gets passed along to a third activity (which is the place where you're trying to kill this whole thing)? If that is the case, and you're trying to kill the currently running activity, the table in the documentation here leads me to believe that you can't just kill an activity that's in the resumed state using the same method. Official Android Docs for Activity You might want to try calling the finish() method for your currently running activity.
What exactly do you see in logcat? And what happens in the UI? Does the visible activity continue to run, but the other activity has been removed from the backstack?
Newbie question... So I have two activities, Cherry and Apple, and each one has a button on it to go to the other one. So back and forth.
In class "Cherry" I say this:
intent = new Intent(Cherry.this, Apple.class)
startActivity(intent);
Meaning that it should go to the Apple. There's similar code in the Apple activity.
What I think I am seeing is, is that each time when I startActivity Apple for example, it's starting a new instance of it instead of just reactivating Apple. I've scoured the doc and can't find the flag or other call that would do what I want.
Any tips would be appreciated!
-- Pito
What about FLAG_ACTIVITY_REORDER_TO_FRONT?
FLAG_ACTIVITY_CLEAR_TOP is also quite useful, finishing activities on the back stack until the target activity is reached.
To be clear, your activity may be restarted even if using the flags above. This would happen if your activity were destroyed in an attempt to free memory. In other words, you still need to make sure your activity can handle being restarted, taking the proper precautions in onPause and onSaveInstanceState.
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT will bring the launched activity back to front if it's already running as given here. You will have to handle the back button yourself so as not to finish the current activity.