I have a recurring task. I schedule it in the standard way (Timer is the libgdx one: com.badlogic.gdx.utils.Timer):
Timer.schedule(myTask, 2, 2);
When the user wants to pause the game, I call:
Timer.instance().stop();
to pause the execution of the task. When the user resumes the game I call:
Timer.instance().start();
This works well, but if the user:
Pauses the game
Makes the game to loose focus (e.g, by focusing on a different window)
Resumes the game
the task is never fired again. Any ideas how this can be solved?
Update
I've opened this issue as a possible bug in libgdx: https://github.com/libgdx/libgdx/issues/3181
Turns out this was indeed a bug in libgdx. It was fixed and now this issue is gone (I'm using libgdx 1.6.2-SNAPSHOT version).
Thanks go to the great team of libgdx!
Related
I have a Canvas object in my app and I want to update it each 20 ms. I tried Java's TimerTask, but it makes my app crash after few updates. Here's update code;
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
invalidate(); // canvas's update
}
}, 20, 20);
What shall I do?
Edit: Error log:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
In this case, run() is called on a background thread, and invalidate() is called on that background thread. This will lead to the exception you have in your question, as those sorts of updates can only be done on the main application thread.
Since calling invalidate() 50 times/second is unlikely to be the right solution for whatever problem you are trying to solve, you may wish to ask a separate Stack Overflow question where you explain what sorts of changes you are trying to make to your UI every 20ms, to see what the recommended approach is. Or, pick up a book on Android game development — while you may not be building a game, game developers drawing to a Canvas also have these sorts of concerns, so the techniques that they use might be relevant to you as well.
If you really want to do this, just change invalidate to postInvalidate.
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();
}
In my LibGDX game for android, if the user backs out of the game (either by pressing the home button or switching to another application) LibGDX's built in pause() method is supposed to run. Now, this is fine, and it works fine as well. My problem is that if I back out of the game to do whatever, and then rejoin the game, it has restarted the app completely (kind of like if every time you exited and rejoined in the middle of a game of Pacman your score would be zero and all the dots would be back). For my screen switching, it is necessary that the game NOT restart every time the user exits, but simply enter the corresponding state to actually simulate the 'paused' game. How do I stop LibGDX/Android from killing the game altogether upon user exit, but simply pausing it?
The libGDX application lifecycle matches the lifecycle of the Android Activity as documented in the ApplicationListener interface so you should expect the same behavior. When you press the home button while in a libGDX game then the pause method will be called, which is the same as onPause in Android. The game will go to the background but will stay in memory. However this is not guaranteed and the OS might release the games memory for other applications, there really is no way to get around this. In the case when the game comes back to the foreground and the game restarts you'll need to load the games state from when it was paused.
I've written my own article on how to save and load the game state using Json in libGDX, maybe that will be useful to you.
You should use Asset Manager to prevent it, here a good tutorial :
http://code.google.com/p/libgdx/wiki/AssetManager
the official doc :
http://code.google.com/p/libgdx/wiki/AssetManager
Load all of your textures with assets manager
I have the same problem, but I found the solution by:
Disable option in Developer options called
- Don't keep activities (Destroy every activity as soon as the user leaves it)
I have a question regarding the pausing/freezing a game while a window/pausemenu will appear at center of the screen. I've already created a pausescreen class which will be called each time the back key is being pressed.
My problem is that I don't know how to freeze or put the game to pause, this becomes a problem because whenever i tried to click on the outsides of the pause window the player could move around.
superjumper code
follow this link . You will find a gameScreen , there they have specified game state which is responsible for pausing and resuming the game. Read it and your problem will be solved.
All you need is to check current game state in render() function. Here is sample solution: libgdx game how to display pause screen when user click on pause icon
In my app I use a camera, and I want to take a pictures. In my app is button (Photo). If I press it one times - all work perfect, but if I press button many times until camera take picture, my app hangs. How can I fix it?
In your onClickListener call Button.setEnabled() and set it to false.
Then set it to true when you've finished taking the photo.
Use a listener that disables the button on press (setEnalbed(false)), than start a countdown thread that re-enables it after some time, 200ms maybe, or whatever fits the best.
After second thoughts this might not be a really good idea.
There is a chance that the thread will not be scheduled to run, so if you exactly know the point when you can re-enable the button in your code, don't use threads.