I have this wierd situation that i can't understand.
I developed an application on android studio, on the first activity i start a second activity, on that second activity i created a SurfaceView child class that extends surfaceView and implemment Runnable and draw on the canvas inside run(), when i exit the thread i call onRestart() to start the canvas thread again.
all good so far, i open the thread, draw some images in a loop, exit the thread loop, restart.
the problem is that after 20 times of restarting, the application crash with no logical reason.
what do you think the problem can be? how to check it and fix it?
this function is the thread work inside the surfaceView child class (of the activity)
#Override
public void run() {
while (!_susspendThread) {
// draw images
}
onRestart();
}
this function is on the parent activity class
protected void onRestart() {
// make some changes, nothing critical to the question
// examp. count++;
surface_view.StartThreadWork();
}
another thing i must say although i dont belive it's related to the problem is that onCreate i read some internal files.
thanks for any help.
You have a memory leak, and this could be from many things. A good place to begin, is to use the onDestroy() methods of your Activities to cleanup any resources you have generated (like the internal files you are creating in your onCreate method).
Also, there are tons of tools for tracking memory usage, in AndroidStudio (AS) there is a "Memory" tab in the "Android" view. Also, you can run the "Monitor" tool (available from the command-line, or within AS to get ton's of details on what type of resource you are leaking.
Related
Hello our application works perfect but when our users move the app to background, after a while coming back to app its been crashing.
For example i open the app then change three pages then move the app to background. after open from background 30 minutes its crash because its try to load activity when i resumed
Another applications do this from mainactivity, for example: instagram,twitter vs vs.
another applications not to try load resume activity, they are trying to main activity
how can i start my app from mainactivity when user come back to app from background ?
well, the better way would be to identify the null objects and reassign or repopulate them in the onResume() method so that the user can actually return to what they were doing.
if you can't or it's not an option, then try this code in every activity that you do not want to return to.
override fun onTrimMemory(level: Int) {
this.finishAffinity()
}
this code closes the active activity as soon as the app goes into background so when returned, the app is forced to start from the launcher activity.
Although I am not convinced that this is the best approach. there might be something better.
Context
I'm one of the developers working on a pretty large and very complicated project. Half of the project is written with JavaScript and the other half with Java, moreover about 30% of the base product comes to us pre-compiled, so we cannot exactly look inside or debug through it.
Problem
When our application comes back to foreground the activities stack gets destroyed and only the root activity is displayed. I cannot track down why.
Things I've tried so far
Setting a breakpoint on every finish() call I could find, none of them gets called
Setting android:excludeFromRecents="false" to every activity
Removing android:launchMode="singleTop" from the AndroidManifest
I've set a breakpoint in onDestroy() method for the second activity and I can see that "isFinishing()" method is executed to "True", so I know that it is not the OS that is destroying the activity, but there is no information (as far as I can see) which would pinpoint me to which class/property/method caused the method to be called. There is nothing usefully I can see in the stack trace. There is nothing useful I can see in the logs.
I've also tried asking people around in my company, but no answer this far.
Question
Are there any strategies to find what caused a certain lifecycle method to be called?
Update 1
Thank you for the great questions and the help in the comments section. Here is the sequence diagram to explain better what is happening.
Application is launched
Activity A calls onCreate()
Activity A calls onResume()
I launch Activity B
Activity A calls onUserLeaveHint()
Activity A calls onPause()
Activity B calls onCreate()
Activity B calls onResume()
Activity A calls onStop()
I put the application into the background
Activity B calls onUserLeaveHint()
Activity B calls onStop()
I return the application to foreground
Activity B calls onDestroy()
Activity A calls onRestart()
Activity A calls onResume()
Update 2
Here are the screenshots of the memory usage
When I launch the application
When I launch Activity B
When I send the application to the background
When I return to foreground
And the solution is found!
Turns out that my root activity had the following property set:
android:clearTaskOnLaunch="true"
Here is a quote from the documentation:
android:clearTaskOnLaunch
Whether or not all activities will be
removed from the task, except for the root activity, whenever it is
re-launched from the home screen — "true" if the task is always
stripped down to its root activity, and "false" if not. The default
value is "false". This attribute is meaningful only for activities
that start a new task (the root activity); it's ignored for all other
activities in the task. When the value is "true", every time users
start the task again, they are brought to its root activity regardless
of what they were last doing in the task and regardless of whether
they used the Back or Home button to leave it. When the value is
"false", the task may be cleared of activities in some situations (see
the alwaysRetainTaskState attribute), but not always.
Suppose, for example, that someone launches activity P from the home
screen, and from there goes to activity Q. The user next presses Home,
and then returns to activity P. Normally, the user would see activity
Q, since that is what they were last doing in P's task. However, if P
set this flag to "true", all of the activities on top of it (Q in this
case) were removed when the user pressed Home and the task went to the
background. So the user sees only P when returning to the task.
If this attribute and allowTaskReparenting are both "true", any
activities that can be re-parented are moved to the task they share an
affinity with; the remaining activities are then dropped, as described
above.
And here is a great article which helped me to find it: http://developer.android.com/guide/components/tasks-and-back-stack.html
Not sure if this will work:
#Override
public void finish() {
super.finish();
Log.d("derp", "who is calling me?", new RuntimeException());
}
I am using libgdx's render() function to update scene with time delta, and then draw the scene. However, when the app goes invisible, the render() function is no longer being called, which causes the scene to stop updating, E.g., an animation will stuck at the last frame, until app goes back to foreground.
The problem is that I am building an online real-time game which cannot be 'paused' on client. When the app switches to background, the game must keep updating the scene even without drawing the scene, so that when the user switches back to the app, he can see the most up-to-date scene, instead of a pause-and-resume scene that lags back.
My question is how to achieve this in libgdx, so that the scene keeps updating even when app goes background? Does anyone experience the same problem as mine?
In a Libgdx app, the render thread is only invoked when rendering, thus only when it has the screen. For most games this is the only time the game should be doing any computations, so combining the update and render makes a lot of sense.
In Android, an app generally only gets CPU cycles assigned to it by the OS when its "foreground". To run an app in the background requires using a different platform API (See, for example, https://developer.android.com/training/best-background.html.) Simply creating additional threads will not be sufficient to keep your app running in the background (the OS may decide to terminate it completely if it wants the RAM back for something else).
Generally, users do not expect an Android application to continue running (and using battery) when not in the foreground.
Additionally, even if your app is coded to run in the background correctly, when the foreground app is using the CPU significantly, your background app may not be run.
You can hook into the suspend and resume events to pause your game and then "fast-forward" your game state as necessary. Or, do your computations in the cloud if you require that they run in real-time.
You can try to update your scene from other thread if it doesn't need GL context in it.
Or you can override onPause() method in your AndroidApplication class in Android projects, and keep using render() method for updating.
In onPause() method of AndroidApplication graphics are told to stop rendering.
Maybe you can create interface class to update your scene, without constant rendering when the app is paused, concerning the battery life.
This is the code from onPause() method.
Maybe this will lead you to correct solution.
#Override
protected void onPause () {
boolean isContinuous = graphics.isContinuousRendering();
graphics.setContinuousRendering(true);
graphics.pause();
input.onPause();
if (isFinishing()) {
graphics.clearManagedCaches();
graphics.destroy();
}
graphics.setContinuousRendering(isContinuous);
graphics.onPauseGLSurfaceView();
super.onPause();
}
So here's what happening: I'm using the runOnUiThread() method to change an Image View from another class when that class receives a message from another phone. I'm calling it by using mainclass.runOnUiThread(new Runnable...) and so on. It works the first time the application is run, but when I hit the back button to exit the application, and then launch the application again, the Image View no longer updates. The logs I took shows me that everything is fine and being run, but the Image View doesn't change. I don't get any errors and it doesn't crash when I run the application, it just doesn't update the Image View. Any idea what might be causing this?
Edit*: So this is what i'm actually using to change the imageView in a class that doesn't extend Activity
peerActivity.runOnUiThread(
new Runnable(){
#Override
public void run() {
Log.v("Thread#", "Thread is running");
Log.v("Thread#2", decodedImage.toString());
// TODO Auto-generated method stub
peerActivity.ivPhoto.setImageBitmap(decodedImage);
Log.v("Thread#3", "Past UI Change");
}
});
Where peerActivity holds the other class reference and ivPHoto is the Image View. What I think I need to do is find a way to kill that thread when the program closes (when I go into the program manager, it still has the Force Close button available). Is there any way to do this?
Edit2*: So I tried a bunch of different approaches to working on the UI Thread and they all give me the same result: The program works perfectly the first time its run but when I hit the back button and close it and the re-open it, the Image View no longer updates. If I force close the app, it works fine again until I close it and re-open it.
Try using View.post(...) instead.
I use new Handler(Looper.getMainLooper()).post(...);
You can even create this from a background thread.
It looks like your Runnable is closing over a reference to your activity. When you press back and then start your activity again, your old activity is destroyed and a new instance is created. Your background thread continues to make changes to the original activity, which no longer exists, therefore making changes to its views has no effect.
You need to either stop the updating thread when the actiivty is paused or stopped as appropriate and restart it when the activty is resumed or started (again, as appropriate) and make sure that you are always updating the activty that is actually visible.
I understand how to save an application's state by using SharedPreferences, onSavedInstanceState() & onRestoreInstanceState(), etc as outlined in a similar post ( Saving Android Activity state using Save Instance State ), but how do I save the last activity?
To be more specific, my application starts up and goes to a login screen. Once a user logs in and navigates through several activities, lets say he or she leaves the app using the home button or in some other way. Next time the user starts the app, it will go back to the login screen and do a login again. Instead, I want the app to start up and go to the last activity that was on top of the stack when the user left the app in the previous session.
How is the last activity saved so that it can be restored on app startup?
I believe Android does this automatically. We have an app that we are working on. When I click the home button and them come back to the app, it starts in the activity where I left off. We have not written any code to make this happen. It just seems to work.
My colleague has written an article on Android application state including details on getLastNonConfigurationInstance() which retrieves the instance that was last stored. Take a look here: http://www.eigo.co.uk/Managing-State-in-an-Android-Activity.aspx
Please note that the above answer is correct only on one case: If your process does not get killed by android because the resources (memory, ...) are needed for a different reason.
To get what you describe, I would write a custom parent activity and override the correct life-cycle methods to store your application state and read it and act accordingly. Then let all your activities inherit from MyActivity (instead of android.app.Activity)
public MyActivity extends android.app.Activity {
...
#Override
public onCreate(...) {
// Read the Application state,
// check if the currently launching Activity is the right one,
// if not, start the last Activity and finish the current one.
}
#Override
public onDestroy(...) {
// Store the current Activity ID in the SharedPreferences
}
...
}
Take care to call the super.onDestroy and super.onCreate methods in all your Activites (like you should do anyways).
Happy coding and have fun with Android!