Jelly Bean and timers/Activities

In Jelly Bean (Android 4.1), creating a Runnable in an Activity and then exiting the Activity will allow the Runnable thread to continue to live (it seems like!).

If your Runnable is being used as a game timer, you now have it running in the background.

I had to to explicitly kill all callbacks and timers in my onDestroy(). I probably should have been doing this anyway, but it did not cause any problems in older versions (including ICS 4.0.3).

Also new: JB will start up and then destroy your Activities MULTIPLE TIMES !!

Symptoms:

  • JB starts the Activity twice, then kills one
  • Runnable used as timer and started in both Activities
  • When my game timer expires, it kills current Activity and launches new Activity (Results)
  • Since you had two Runnable timers… you now have TWO copies of your second Activity running !

Sounds very strange. I know with older Android versions, onCreate() could be called multiple times for a single activity instance. Haven’t heard of anything like this happening though.

Is there anything in the changelog which could help understand the new behaviour?

Thanks for the info. In one of my games it might be a problem because I use runnable as a timer, I will have to check if I destroy it properly.

Hi all, long time reader, first time poster.

I’ve come across this issue with the game prototype I’m currently working on with Jelly Bean and this is the only place so far that I’ve seen someone else mention it. It’s my first android game (actually make that app!) and so it’s a bit of a learning curve! On an older device with 2.1 there is no issue.

At the moment I’ve got the prototype down to just running the game for 60 seconds and then stopping the thread. When it does this and the thread stops, pressing the home or back button is all fine. I use a thread.join around a catch block in my onDestroy and Log Cat is showing as expected. However if I exit before the 60 seconds are up it just looks like it’s not stopped and it’s trying to carry on and then falls over like the original post.

It also seems to be intermittent. Sometimes it works, sometimes not.

I’ve looked into ‘killing’ the callbacks with removeCallback(blah) just before I try and stop the thread, but it doesn’t seem to work and I’m not entirely sure I am doing it right.

I googled for quite a while, but I can’t seem to find anything definitive. There were some things about if you’ve implemented the Runnable interface, but I’m extending the Thread class. If anyone knows if this has been documented somewhere that I could read up on I would be eternally grateful.

Not sure if this is only limited to jelly bean, but I’ve had it happen on my nexus 7 that has jelly bean, not any other devices I’ve tested with.

What happens is when using a framelayout and a view for your game layer and another view for an ad. I’m hiding the ad during gameplay calling gameView.bringToFront. When I try to show the ad on level recap screen, mAd.bringToFront, the game layer turns all black for a few seconds. Sometimes it last for only a few seconds sometime the screen is black untill I call bringToFront on the gameView again. Anyone else seen this before?

Try slapping in an invalidate() for the game layer and hope that fixes the problem ? :slight_smile:

I’m not sure if this is in fact the same problem as the original post now, but I’ve finally found a solution to the problem in my previous post. I’m doing pretty much exactly what the poster is doing here:

For whatever reason the thread.join does not seem to be behaving as I would expect, but putting a canvas null check in the thread loop seems to have done the trick and has done away with the crash message when exiting.

Hopefully posting this here will prevent others from headbutting the table in frustration for a few hours like I did! :smiley:

Nope… that is a different problem. I figured out why I did not have this problem on my beta app that I am working on… It seems that since I have been running ICS since it came out, I already ran the debugger through that problem and put a null check in there :slight_smile:

Thanks for the suggestion, but invalidate() didn’t work, I also try .requestLayout on my layout. Now it’s doing it on my apps that show the ads full time, when the ads update the view behind them goes completely black. But, I’ve finally found a fix. Seems it has something to do with hardware acceleration. Adding this line when creating the adView fixed the problem, it turns off hardware acceleration for the adView:

sdkVersion = Integer.parseInt(Build.VERSION.SDK);
if (sdkVersion >= Build.VERSION_CODES.HONEYCOMB) mAd.setLayerType (android.view.View.LAYER_TYPE_SOFTWARE,null);

Note I had to check for SDK version because setLayerType is not in the previous api’s. You could also set it from xml with:

android:layerType=“software”

Also note I had tried taking out hardware acceleration for the whole application by removing this line from my manifest: android:hardwareAccelerated=“true”
That didn’t work though, only turning off hardware accerleration for the AdView it’self actually work on my Nexus Tablet.

I was doing the reflection all wrong in my above statement. You need to hide the higher api class calls behind another class not an if statement. Also if your checking for Build.VERSION_CODES.HONEYCOMB on a pre-honeycomb device hows it going to now what code honeycomb is? So this is the new (correct) way I’m doing it:

I have a class called ReflectClass in which I will call the setLayerType method (the honeycomb and higher class):


package xdebugx.wordSearch;

import com.google.ads.*;
public class ReflectClass {

public static void setLayerType (AdView mAd) {

mAd.setLayerType (android.view.View.LAYER_TYPE_SOFTWARE,null);

}

}


Then in my activities code I call it like this:


sdkVersion = Integer.parseInt(Build.VERSION.SDK);
if (sdkVersion >= 11) ReflectClass.setLayerType (mAd);

Note I hard coded the honeycomb sdk version (11), because how would a pre-honeycomb sdk know what version code honeycomb is.