android thread crashes when screen orientation changes - java

I am making an android app, which needs to download a text from a url and show it on a alertdialog.
I created a new thread. The thread reads a file on the web, a progressdialog appears before the thread starts, the thread packages the file content from the web on bundle , and passes it to a handler, the handler stops the progress, and shows the text from the bundle on a alertdialog. Well this works pretty good, but when the screen orientation changes when the progressdialog is shown and the thread is running, the app crashes. Any ideas on how to fix this thing?
Any help will be appreciated. :)

When the orientation changes, normally the OS will shut down your activity completely and restart it. That will mess up your download thread. One solution that might work is to save the Thread object as non-configuration data. You'll need to override onRetainNonConfigurationInstance() in your activity. However: do not do this if your Thread object has any references to any view- or activity-related object. That will cause a huge memory leak and will make your users very unhappy very quickly.
See the guide topic Handling Runtime Changes for details on using onRetainNonConfigurationInstance() and also an alternative approach. See the article Avoiding Memory Leaks on ... well, just that.

Add activity to menifest file as following -
<activity
android:name=".MyActivity" //Replace MyActivity with Your activity
android:configChanges="orientation|screenSize|screenLayout">
</activity>

This usually happens because your Activity actually gets destroyed and recreated on orientation changes.
Your options are:
Embrace the destruction, and use an AsyncTask instead of a Thread to fetch your data. You cancel() the task in your onDestroy() method.
Also use AsyncTask and cancel() it in your onDestroy() method. Additionally, handle configuration changes such as in the answers to this question.

KSubedi... Assumptions can be dangerous. Step by step testing to eliminate the exception may reveal that it is the running progress dialog that is causing the exception. The cure is:
protected void onPause() {
super.onPause();
//if (asynch != null) {asynch.cancel(true);}
if (progress != null){progress.cancel();}
}
JAL

Related

How is an Android Activity recreated when the screen is rotated?

I'm a newbie Android developer. I know that when the screen orientation changes, the Activity is re-created and onCreate() is called again. What I couldn't find online, however, is how exactly the original Activity is destroyed. If some code called by onCreate() is in the middle of running, does that code just stop, or does the system wait for that code to finish before rotating the screen and calling onCreate() again? Thanks.
Activity's onCreate() is called everytime when the orientation changes and you should take care of your asynchronous task because the system does not wait, but you can avoid the re-creation of Activity by adding configChanges attribute of Activity in your AndroidManifest file in the activity tag.
android:configChanges="keyboardHidden|orientation"
According to the official documentation on configuration changes, once a device rotation is detected or the activity is started for the first time, onCreate() is called; you should assume that for all intents and purposes the onCreate() method will complete its execution before another screen rotation triggers activity recreation. Any code executed in your onCreate() should be done instantaneously since it shouldn't block your UI.
When rotating a screen we call it one of the Configuration Changes, it includes situations such as screen orientation, keyboard availability, and language changes. As quoted from Android official documentation here onDestroy() will be called then onCreate().
Some device configurations can change during runtime (such as screen orientation, keyboard availability, and language). When such a change occurs, Android restarts the running Activity (onDestroy() is called, followed by onCreate()).
But if there was any code executing on the main thread will have to finish (not other threads) and Android gives you time to save the activity data which you can receive on onCreate() when the activity is restarted. It does so by calling the method by calling the method onSaveInstanceState() as explained here in the documentation.
To properly handle a restart, it is important that your activity restores its previous state through the normal Activity lifecycle, in which Android calls onSaveInstanceState() before it destroys your activity so that you can save data about the application state. You can then restore the state during onCreate() or onRestoreInstanceState().
So the whole issues of code in the activity is that it will wait for the code to finish if it were executing on the main thread and if the code taking too slow it may make configuration changes very slow as it is discouraged in the documentation to make huge tasks in the main thread (for instance http requests).
This whole answer and descriptions and quotes has been taken from Android Official Documentation Guide, you can visit it for reference and more descriptions on configuration changes.

Activity being destroyed when taking photo

When I do startActivityForResult to take a photo, the underlying Activity is destroyed. Even when I put
android:configChanges="orientation|keyboardHidden|screenSize"
in the manifest, any ideas would be extremely appreciated!
Probably your process is being terminated while your app is in the background. This is perfectly normal and will happen in many other cases, not just this one. You will need to adjust your application to deal with this situation (e.g., use the saved instance state Bundle).

Click on item leads to IllegalStateException

How can this happen? I use a RecyclerView in an fragment and the fragment itself implements my click listener...
Sometimes, clicking an item in the list results in following error:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
How can this happen? Clicks should be forwarded to their handlers synchronous and this should not happen, should it?
Some code fragment would really help. But your error already states Can not perform this action after onSaveInstanceState
This means that after the function onSaveInstanceState() has been called, you try to do something. Put that code before onSaveInstanceState() and you might have a solution.
OnSaveInstance is called when the activity is about to be destroyed.
The android gives a last attempt to save all the data in a bundle that can be retrived back when the activity is recreated onRestoreInstance.
Mostly this case occurs when the android decide to garbage collect your activity due to lack of memory.
The error state that you are doing some work on UI -fragment after the onSaveInstance has been called.
Android does not allow any work on fragments after this has been called and soon onDestroy will be called.
So kindly revisit your logic or place a isFinishing() check before doing any work.
Actually it's because you're activity is getting destroyed due to lack of memory and before it gets destroyed it saves the fragment state also, and like you mentioned it happens sometine, during this you might have clicked your own which tried calling that previous state non click on the destroyed fragment.
How can you avoid it
Use volley and Picasso. And check which part of your application is using more memory using memory monitor given in android studio.
Also if you are not able to reduce memory usage consider adding.
large heap="true"
in your manifest

How to call a method when an Android app is closed or loses focus?

Because an app I'm building will handle rather sensitive data I want to sync the SQLite db with the server every time the user logs in, and remove emty the db every time the app loses focus (because the user moves to the home screen or another app).
Seeing the Activity lifecycle, my idea was to do this by emptying the database in the onDestroy of every Activity. To test the described lifecycle I just Override all lifecycle methods (onCreate, onStart, onResume, onPause, onStop, and onDestroy), included some log messages in them, and fired up my app.
The log messages are included in my SettingsActivity. When I enter my app and move to the Settings it runs onCreate, onStart and onResume (as expected). When I then click a setting and move to the next screen it runs onPause and onStop (still as expected). To move back to the settings screen I click the back button and it runs onStart and onResume again (still as expected), when I now click the back button again to move back to the initial screen, it (to my surprise) runs onPause, onStop AND onDestroy.
So my questions;
Why does it destroy the Activity when the app is not finished?
And more importantly: how can I run my CleanUp method when the app closes or loses focus?
You can have some more information here : http://developer.android.com/training/basics/activity-lifecycle/stopping.html
Even if I think you already read it because you already study the activity lifecycle, you can see in the first figure that the onDestroy() is called after the onStop() and this call is totally managed by the system : you shouldn't expect any behavior. The system will decide itself WHEN to call this method, and sometimes, this method will never be called (see here : http://developer.android.com/reference/android/app/Activity.html). When system needs memory, your activity will pass in onStop() and nothing more.
So, to answer your second question, you shloud read the note in the documentation about the onDestroy() method :
Note: do not count on this method being called as a place for saving
data! For example, if an activity is editing data in a content
provider, those edits should be committed in either onPause() or
onSaveInstanceState(Bundle), not here. This method is usually
implemented to free resources like threads that are associated with an
activity, so that a destroyed activity does not leave such things
around while the rest of its application is still running. There are
situations where the system will simply kill the activity's hosting
process without calling this method (or any others) in it, so it
should not be used to do things that are intended to remain around
after the process goes away.
So it's pretty clear that it's a bad place to make your clean-up process. So you shloud use one of onPause() or onStop() method.
onStop() is described like this in the documentation :
Called when you are no longer visible to the user. You will next receive either onRestart(), onDestroy(), or nothing, depending on later user activity.
onPause() is described like this in the documentation :
Called as part of the activity lifecycle when an activity is going
into the background, but has not (yet) been killed.
[...]
When activity B is launched in front of activity A, this callback will be
invoked on A. B will not be created until A's onPause() returns, so be
sure to not do anything lengthy here.
[...]
In situations where the system needs more memory it may kill paused processes to reclaim resources.
We now know that onPause() is designed to allow you to save your data, and also that after onPause() was executed, the system could kill your process. So, making the clean-up in onPause() seems to be the safest place as you're pretty sure it will be called everytime.
Also, as you can read, making your clean up here can make your app slow, but anyway cleaning and recreating your database at each gain/loose of focus is a really heavy process...
To resume : make your clean up process in the onPause() method and your init process in the onResume(). Keep it mind that your application can be really slow with this kind of process.
Hope this can help you.
Destroying the Activity on back is the normal behavior. From the Android developers site
There are a few scenarios in which your activity is destroyed due to normal app behavior, such as when the user presses the Back button...
Has for detecting when the application goes to background, there is no simple method call that will let you know that. However this previous question contains some nice answers on how to do it.
You can't do this (call a function) in java part of app.
Only in the native part.
About your second question, this way you could run your CleanUp method when the app closes fully. You will need to implement your method inside a service that in this case I named "ExitService"
First create this service class:
public class ExitService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
System.out.println("onTaskRemoved called");
super.onTaskRemoved(rootIntent);
//do something you want before app closes.
ADD YOUR METHOD HERE, or CALL IT
//stop service
this.stopSelf();
}
}
Then, declare this way your service in the manifest "application" label:
<service
android:enabled="true"
android:name=".ExitService"
android:exported="false"
android:stopWithTask="false" />
Now, just start the service wherever you want to do something before your app closing.
Intent intent = new Intent(this, ExitService.class);
startService(intent);

Good practice of using android activities

I completed few android apps successfully but always I feel that I am not following the best practices of android developnment.
Few things which makes me feel developing a 100% complete android app is tough are
1. Making sure that my app is following all memory management stuffs
2.Making sure that my app is not going to crash
3.This one is always a big confusion for me-
I put all my code in oncreate() method including event listeners, phonestate listeners(If I require) etc..
What is the use of other methods like onResume(), onPause()... (I understood the concept of when they are called)
Should I stop all my event listeners in onPause() or by default android clears it?
Can I put all my event listener in onResume()?
Check dev Link
when ever over activity come in on stack again like previous it was not delete from stack then on resume is calling like if u want to see any list from any web service then after light off and again screen light is on then onresume() is call and u can call that webservices here and arrange list view with update values.
when ever your application go in pause mode then onpause() will call
you can follow above link i think your all query regards this will solve
The best reference for activity lifecycle callbacks is probably the the Android developers guide, and in particular this part:
http://developer.android.com/training/basics/activity-lifecycle/starting.html
Should I stop all my event listeners in onPause() or by default android clears it?
Either there or in onDestroy() but it depends what you're using them for; if you want the listener to listen even while that activity is paused or stopped then obv. stopping in onDestroy() is better.
Can I put all my event listener in onResume()?
It depends, onCreate() is only called once when your activity first starts up, whereas onResume() is called when your activity starts as well as every time your activity comes back from being paused or stopped. So if you stopped listening in onPause() then you probably want to start listening again in onResume(). If you stop listening in onDestroy() then you probably want to start listening in onCreate().

Categories