I am trying to make my game multitask friendly, however whenever the screen is turned off and turned back on, or the game is navigated away from and back to, I get a null pointer exception pointing to this part of the code:
GLES20.glUniformMatrix3fv(mTextureMatrixHandle, 1, false, render.mTexMatrix, 0);
I don't have anything apart from super.onResume(); and mGLSurfaceView.onResume(); for the onResume() method and the same for onPause(), except with onPause rather than onResume. Any idea how to fix this?
You must make sure that the objects are re-created when the activity is started again. Where are those variables initialized? Typical case for this kind error is when you store objects in a global variables. When the activity is created again, they are null.
So: check which of mTextureMatrixHandle, render, or render.mTexMatrix is null. Re-create it if it is null.
In general, you should not rely on any data being restored at activity creation. So don't use global variables, and rely only on data passed via the intent. If you really want to use global data, you should be aware that it may be reset, and re-create it when needed.
Related
I understand the basic Lifecycle of Activity/Fragment but sometimes, when user puts the app in background state for long time I'm not sure what's going to happen when he opens it again. Recently I've encountered a bug: User gets nullpointer exception by calling method of a view saved in class variable (textView = findViewById(...)), inside fragment's OnResume method. The variable is set in OnViewCreated(). Is that possible that over long period of time fragment might lose it's fields due to lack of memory? When onResume() will be called and when onCreate()?
If the app is in background for a long time its process will be killed by OS, or if the device is running low memory. To test how your app works under these conditions use flag "Do not keep activities" in Developer options on your device. In the described case onCreate will be called when Activity will come to the foreground.
If the process is not yet killed then onResume will be triggered. Normal variables persist, but the problem is that you can never be sure when you're calling onResume and when you're calling onCreate (since you have no control over when Android just goes and tosses stuff on the stack out the window... anything not currently being used is eligible for destruction).
So my solution is to add a null check with if condition: if the variable is null then initialize and perform actions, if not then just preform actions.
I have an Activity, where I initialize a class member variable in onCreate(). In some case, I need to startActivity() which means this Activity turn into stopped state. When I come back, I need to use the variable.
This works OK in most phones, but I also get some crash from my users because the member become null on their phones. This member just contains some String and a POJO.
Does Android clean up Activity's member variable to free up memory?
Those member variables will be cleared out if onDestroy is called, even if the activity isn't finished. You can simulate this by turning on "Don't keep activities alive" in developer settings. Once that's enabled, start your activity and then pause it (i.e. hit the home button)
To get around this, you'll need to store those member variables in onSaveInstanceState, and then restore them using the savedState bundle in onCreate
I currently have an activity's onCreate() method set to capture an intent the first thing it does. The intent will always have an extra int "ACTIONCODE" that determines what the activity should do.
Activity A might want activity Z to set up variables for the first time, so it calls startActivity(includedIntent) which has some extra int ActivityZ.SET_UP_FIRST_TIME (which is a constant in Activity Z.) Activity B might want to change the variables around a bit, so it does a startActivity(includedIntent) with the intent now including an extra int ActivityZ.CHANGE_VARIABLES as well as other data to change those variables.
Activity Z could just be a bunch of textviews that display what its variables are. Depending on what ACTIONCODE it receives from getIntent(), it will perform things just as it needs to.
I feel like I have a lot more control over the activities in my app my doing this, yet I fear as though it might be a really naive and inefficient implementation. I basically do not trust (nor fully understand) onStart(),onResume(),onPause(),and onStop(). From what I've heard, there is no guarantee that an activity will always return back to onResume(). While it was in its onPause() or onStop() state, it could have been killed or completely destroyed by the system, and thus would only return back to onCreate() again. It's the only method that I trust.
I even do all of my data saving from onCreate(). Why? I heard that if an activity is in onPause() or onStop(), it is liable to be killed, and may not even finish running through all the lines included in the overridden onPause() or onStop() method. I don't want to perform a data saving function from within a method that could abruptly stop!
Is my thinking wrong here? Are my fears irrational? If so, what should I do instead?
Here are my app screenshots by the way:
Thanks, Luksprog. After some reading, I think I can trust the activity lifecycle better now.
I will implement setting up in onCreate, loading in onResume, and saving in onPause! Hopefully that's correct.
Now all I need is some advice on the right way to set up activities and fragments. I just need some general rule of thumb for deciding when and when not to start a new activity, or if it may be better to use fragments.
So I have been looking at tutorials and messing with things for hours. I have my main activity which creates a map of object that it gets from the database. To avoid unnecessary database queries, I am trying to save that map using the onSaveInstanceState method and then restore it with the onRestoreInstanceState. I can see that it gets saved correctly using the debugger, but if I set break points in the onRestoreInstaceState method the program never breaks. Then I thought I would just do it with the onCreate() method but it's not breaking there either. The program should break in both of those places when returning from a different activity right?
Those two methods are only called if the activity is killed and restarted.
The good news is, if your activity was not killed, there's no need to restore your state. It should still be just the way it was.
If you do need to do something when switching back from another Activity, that's what onResume() is for.
See the chart for more.
My question is can i get to know when the entire application gets paused/resumed start/stop etc.
For example if i have 5 activities in my application. Whenever any activity gets paused/resumed android notify the activity by calling the onPause/onResume methods.
So there are two possible scenarios when my activity gets paused.
1. My activity-2 gets paused because my activity-3 gets invoked.
2. My activity-2 gets paused because of some outside activity like incoming call.
Here I am interested only tracking when my activity gets paused by outside activities not my own application activities.
So is there any android provided solution for this or do I have to write my customized solution.
Thanks
Dalvin
There is no solution provided by the API because it is not needed in most cases.
What you can do is to create an abstract activity and make all your activities inheriting from this abstract one.
In this abstract activity, by overriding onCreate, onResume, onPause, onDestroy, you can manage to count how many of your own activities are "alive", and then determine the state of your application.
This could work but it's not really the Android phylosophy
You can know the starting of the whole application on application.oncreate() but there is no indicator for the whole application pause. Most of the cases never needs it anyway.
So further read in the activity lifecycle and the application class.
Still you can do this option in your program by overriding the onPause in each class and save a value to the sharedPrefrences then check on this value all over the application
If I understand your question, you want your app to be able to distinguish between exiting the current activity within the context of your program or by an external event like a phone call. I have used the following method in the past to do this (although it may not be the best, it definitely works):
(1) Set up a value in SharedPreferences (the built in file for storing a program's data). Call it something like "exitStatus" which is set to 1 for an exit within the program code and 0 for an exit based on external events.
(2) Now, within each of your activities, set the value of exitStatus to 0 in onResume (which is called no matter how you enter). If your program exits due to an external event within that activity, this value will persist when the program is reloaded.
(3) At the end of your activity, at all points where you are going to transfer to another activity, first set exitStatus to 1. Then, when you arrive at the other activity, it will know that you arrived there from within your program.
(4) Thus, just to be clear, each of your activities can check exitStatus at the outset to see whether you are entering from within your program context (= 1) or after a non-local exit of some kind (= 0).
That's all there is to it. I use this method to be sure that load data for my app is present as it may be lost if a user turns off their device so that the app tries to pick up in the middle of things when they later reboot, etc.
Instead of making base activity and override onPause/onResume you can use
registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback)
where you can handle these states for application activities in one place.