I am developing an app with capturing the image as one of the feature. In my home screen i have two spinner. After selecting spinner values user can go capturing the picture by clicking take picture button. Up to this working fine. But the problem resides in Camera App Orientation.
Take Picture button launches the camera.When image get captured it saved(absolutely fine) and came back to the parent activity. But the problems is it refreshes the activity. while coming back i can see following wired things
1.)Some times it shows landscape screen(1second) and back to portait which refreshes the activity and results in resetting the Spinner values.
2.) Some times it just resets the Spinner values.
It's really annoying. I haven't got any clue to get rid this problem. I hope some of you guys will solve this.
Much Appreciated.
It's good to be prepared for anything when you're launching an activity in another app (Camera). The activity could return bad data, the screen orientation could be changed, or it could be a very long time before the user returns to your app. From your description, it sounds as though the orientation is changing every time the Camera app is launched.
Android has built-in state management methods to handle this type of scenario. You can override the onSaveInstanceState() method to store your activity's state (e.g., spinner values), and then restore that state in onCreate(). (Example here.) This will handle the case in which you're launching the Camera app, or your user presses the Home button and then returns to the app, etc.
EDIT:
onRestoreInstanceState() is only called if your activity is killed due to memory pressure and then recreated later. It's much more reliable to use the Bundle passed to onCreate() (which is called again after device rotation) instead. That Bundle will contain everything that was stored in onSaveInstanceState().
If you need to postpone your work until onResume(), you'll want to use onCreate() to populate some member variables in your Activity class, and then make use of those variables in onResume().
Related
I am maintaining a simple Android kotlin app that only has one MainActivity.
The app has a lot of images. We want to reload the data and images when user navigate away and then return to our app, this works so far:
override fun onResume() {
super.onResume()
tryToLoadDataAgainAndReloadAlotOfImageViews()
}
However this produces one unpleasant side effect, for example:
User launch the app
onResume fired, we load data and refresh all images (corrrect)
App shows permission dialog to grant GPS locations
User click accept
permission dialog dismisses
onResume fired again, all data reloaded and images reloaded again.
This will looks like a glitch as all images are reloaded twice in a short period of time.
I understand that I may set booleans here and there before showing permission dialogs to resolve this, but it feels like a hack and possibly buggy code.
Is there any elegant way to resolve this? For example, detecting onResume is coming from another app, or coming from internal permissions dialogs?
We want to reload the data and images when user navigate away and then return to our app
What do you mean by this exactly? Are you talking about the app disappearing from the screen? (e.g. the user switches to another app, or hits the home button, or turns off the screen.) If so, do your refreshing in onStart instead of onResume, then it'll only fire when the app becomes visible again.
But if you want to handle things like multi-window mode, where your app is visible but might not have focus, then you'll need to look into detecting that when your app hits onPause, and maybe storing a flag onResume can check.
Basically Android's Activity and Fragment lifecycles have a couple of paired callbacks, onPause/onResume and onStop/onStart.
When your app is no longer in the foreground, but still visible, it moves to the PAUSED state. If it remains visible, but then moves to the foreground, it moves from PAUSED to RESUMED by calling onResume. This is what's happening with your dialog - because it's displayed over your Activity, the Activity is paused until the dialog is dismissed, at which point it calls onResume. So what's happening is by design!
But if your app is becoming invisible (i.e. it's not on the screen anymore) then it first moves to the PAUSED state (if it's not already), and then it moves to STOPPED and you get the onStop callback. When it returns to the foreground, onStart will be called, followed by onResume. (This is also what happens when the Activity/Fragment is (re)created of course!)
So you need to handle things in the appropriate lifecycle callback. It sounds like your needs are better met by having this stuff handled in onStart, since that only gets called when the Activity/Fragment appears. onResume can be called more often, since it's possible for the component to enter the PAUSED state (onResume is called when it's "unpaused") without moving to the STOPPED state - like with dialogs.
Like I said, if you want to handle multi-window mode that's more complicated, and the lifecycle behaviour depends on API level, so you'll have to look into that!
You can use the isFinishing method to check if the activity is in the process of finishing before calling tryToLoadDataAgainAndReloadAlotOfImageViews() in onResume()
try using Glide.
dependencies :
//Glide
implementation("com.github.bumptech.glide:glide:4.12.0")
kapt("com.github.bumptech.glide:compiler:4.12.0")
As per the official documentation
Glide is a fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.
I'm writing an application implementing a bar code scanner.
Several values are gathered and displayed in the same Activity. Everytime the user wants to get a new value, he calls an Intent on a another application in the device which handles the bar code scanning part, and returns a String containing the actual value held by the bar code.
In the end, mutliple values from multiple scans are meant to be displayed in the same Activity.
It works perfectly on two different devices (Nexus 7 on Android 4.4.2, Vuzix M100 on Android 4.0.4).
On those two, it goes well and on second intent return, my previous values are still stored in the Activity.
But on the Alcatel One Touch Mini s 2 (Android 4.3), everytime I come back to the first activity, it goes through the onCreate method of the relevant Activity and erases the previous scan values stored in global Activity variables.
I have searched over the web but I couldn't manage to find any clue.Why does only one phone out of three erases the Activity for every intent created, and how can I prevent it?
It doesn't seem to be a hardware ressource problem (as said in the doc, Paused intents can be destroyed to free memory) because the problematic device is almost the most powerful.
You need to be prepared for cases when your activity gets destroyed, and later recreated. For this Android calls onSaveInstanceState() where you can store the information that you need in the Bundle provided. Then when the activity is recreated, onCreate() will be called with this Bundle passed as a parameter, so you can read your data from it. You can read more about this here => Saving Activity State
"everytime I come back to the first activity, it goes through the onCreate method of the relevant Activity and erases the previous scan values stored in global Activity variables" --> could you store them in a shared preference that you read each time in onCreate?
I have an app in which I programmatically create an EditText view. I assign an ID to that view using setId()
myEditText.setId(100);
so that Android automatically saves that object's state when pausing/stopping the app (as I was advised to do here). It works in these cases:
(1) When I leave the app using the "Home" button: if I then come back to the app, the object's state (displayed text) is restored, as expected.
(2) On a screen orientation change (which involves Android automatically destroying the activity and restoring it through a Bundle). The object state is also kept.
However, it doesn't work in this case:
(3) When I leave the app using the "Back" button: if I then come back to the app, the EditText object is empty.
Any explanation as to why this happens? Does Android really distinguish between leaving the app with "Home" and with "Back"? According to the documentation, the object's state should be automatically preserved, through a Bundle, even when the activity is destroyed. And that clearly happens in case (2). But not in case (3)!
If this is normal behaviour, how could I have the app's state automatically saved and restored when the user presses "Back"? I know I could use the SharedPreferences for that, but I'd rather have Android do that automatically, just as it does in cases (1) and (2).
This happens at least in Android 4.0 and 4.2 (I haven't tested others).
You really should study activity life cycles as there are many many ways to solve the problem. Since your activity is typically pulled off of the stack and destroyed when you navigate back one quick but not necessarily the best way is to make sure your activity flagged as singleTop or singleInstance in the manifest that way it is not pulled off of the stack and recreated when you navigate back and forth. You could also use the singleton Application class. Or pass the text back and forth as params. Or use a database. Or use MVC or some other programming paradigm that will allow your views to be destroyed and recreated with out the data populating them going with it. Lots of "or's". Study activity life cycles and then look at how you have your application architecture setup already and choose the method that will work best for you.
http://developer.android.com/training/basics/activity-lifecycle/index.html
http://developer.android.com/guide/components/tasks-and-back-stack.html
I think I found the explanation. I only needed to read the doc more carefully (thanks to #lentz for one of the links); see here and here:
When your activity is destroyed because the user presses Back or the activity finishes itself, the system's concept of that Activity instance is gone forever because the behavior indicates the activity is no longer needed.
If the user presses the Back button, the current activity is popped from the stack and destroyed. The previous activity in the stack is resumed. When an activity is destroyed, the system does not retain the activity's state.
The above explains behaviour (3) in my question.
However, if the system destroys the activity due to system constraints (rather than normal app behavior), then although the actual Activity instance is gone, the system remembers that it existed such that if the user navigates back to it, the system creates a new instance of the activity using a set of saved data that describes the state of the activity when it was destroyed. The saved data that the system uses to restore the previous state is called the "instance state" and is a collection of key-value pairs stored in a Bundle object.
The above probably explains behaviour (1) and (2).
What I don't see is why the user pressing Back should be interpreted as "the activity is no longer needed" ("its state needs not be preserved"). But that's a different matter.
I have a MainActivity and a second Activity which has an EditText. I want that the content of EditText always gets saved. However I don't want a EditTextChangedListener which writes a file after 1 char has changed.
What is a good solution? I thought about onPause or onBackPressed.
What about the home button? I think the app remains open, so is there any need to save? And what about other interrupts like phone calls? Does onPause catch all that?
Thank you.
Yes onPause gets called whenever your app gets interrupted or goes to background check Activity life cycle
A good solution is to include such logic in the onPause() method. It will always be called in all situations. This is what the developer documentation says:
you should use the onPause() method to write any persistent data (such as user edits) to storage.
One thing you should keep in mind is that this method may be called more frequently than desired, for example, when your screen light goes off (some ppl have 15sec screen light timeouts). So, you should not put in too many expensive operations inside there.
As for pressing of home button, it is recommended that you save the data (at onPause()). The reason is that your activity is in the background but it may get destroyed. The system may destroy the activity if it needs to reclaim the memory. (For example you start too any other apps afterwards and put them all in the background) From the documentation:
Stopped: The activity is completely obscured by another activity (the
activity is now in the "background"). A stopped activity is also still
alive (the Activity object is retained in memory, it maintains all
state and member information, but is not attached to the window
manager). However, it is no longer visible to the user and it can be
killed by the system when memory is needed elsewhere.
No. The correct answer here is to listen for the "return" key event. That signifies that the user has completed input to the field, and trigger the save of the field contents to the file. It's useful in many other circumstances too.
See this answer: Android Use Done button on Keyboard to click button
Peter.
Whenever the Android device locks and I unlock it, the image that was displayed in the ImageView disappears. What do I need to do to redisplay it or prevent this from happening.
More:
I have a view that displays video, images or text depending on the context and three subclasses that extend the parent view. On creation, I replace the display view with the View object returned from createMediaPreview(), which each subclass implements.
Thanks in advance
You'll probably want to call createMediaPreview() again in the onResume() method:
http://developer.android.com/reference/android/app/Activity.html#onResume()
As roundhill mentioned, you need to setup your image in onResume(). OnCreate() only gets called when the Activity is first instantiated. When the phone goes to sleep, the Activity remains in memory, in sleep mode. When you unlock the phone, Android OS will bring it back to the foreground (it doesn't call onCreate() since it already finds this activity in memory, it already exists). Check the Activity's lifecycle here