Black Screen Bug.
I've thrown together an .ANE plugin to deal with the black screen issue on AIR when switching back from various processes and plugins.
----Symptoms:
User opens admob advert, web address, google market page (via http:// or internal market:// URL), or Google Play In App Purchase/Billing plugin. Upon returning to the game, the screen is blank, though everything's working fine in the background - including dislplaylist element placement and touch event handlers.
Repeating the action, such as clicking the button you used to open the market (in the dark), then cancelling will fix this and restore your display.
Other variations include when the app has been minimised or when the user has locked the app and returned, and the issue is especially prevailent on Samsung devices it seems.
Generally, things like Admob adverts will be visible on top if they're called again after return. (As they're likely to vanish as you open an external link).
There are threads discussing the issue here:
http://forum.starling-framework.org/topic/starling-turns-into-black-screen
http://forum.starling-framework.org/topic/maybe-context-loss
http://forum.starling-framework.org/topic/resuming-using-eventactivate
Unfortunately, Adobe closed the bug ticket for this a while ago.
----Steps to reproduce:
While I've not been able to replicate this at all on some devices, on Samsung devices (Tab2, Tab3, ACE, etc), hitting a button that opens a market URL for example then immediately hitting the back key can sometimes cause the screen to blank out. Returning to the market and closing again generally fixes it.
Immediately hitting the back key seems to increase your chances of encountering the bug from about 1 in 20 to about 1 in 4.
----Affected devices/SDKS:
The bug appears on and the fixes work on the following devices:
Galaxy Tab 2, Galaxy Tab 3, Xperia X10, Galaxy S, Galaxy Ace, HTC One, HTC Desire. (So Android 2.3.3 to 4.0.4)
It has been tested to work with Flex4.6 and AIR 3.7-4.0 SDKS, built against AIR 3.7, 3.8 and AIR 3.9
The plugin is built for Air 3.5 and up.
----Cause:
Possibly a display list ordering issue. Some users have reported that forcably changing the device orientation via stage.orientation fixes this, but this hasn't worked for me. Some report it might be to do with various ANE's for facebook, billing, etc.
It's important to note that this is not an issue with Starling specifically, but rather AIR itsself. If you've suffered the problem yourself, you're probably sick of people asking you to check if your app is recovering from a lost context properly, when you know it's not that, but humour me briefly and check that
Starling.context.dispose(true); works for you. Your app should recover momentarily.
If it doesn't, ensure that you've set "Starling.handleLostContext = true;" before creating your starling object and that you're not deleting the bitmapdatas you're using to create textures from. In Starling.core.Starling.as, there's a function called "onContextCreated(event:Event):void" with an "Initialize()" call near the bottom. Have that line add something to your main stage. If you can see it, it's a context bug, if not, it's the black screen bug.
But that's out of the scope of this post, so with that out of the way, let's continue.
----Putting together a fix:
So knowing that one could re-open the market and close it to fix the screen without any context fiddling, I figured it must be possible to pop open a new android activity with the right setting to programatically fix this.
In the end I settled for something like this:
public class FlickScreen extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.finish();
}
}
It pops open, changing the screen orientation and closes itsself, returning orientation. Don't get me wrong, it's a total hack, and you have to call it just after Event.ACTIVATE whether or not the screen is black ('cause you can't actually tell as far as I know). This causes a brief flicker (and sometimes a quick rotation animation), and can sometimes cause a loss of context itsself (hence making sure your context is restored properly) but it does seem to work fairly effectively.
You're literally popping open a blank window that immediately closes itsself.
----Usage:
Unless your app is set to run in the background, it will stop ticking on a minimise event. So set an int to count say 5-10 frames ideally before the minimise event, and on maximise, it'll be counting down, call the fix, and restore your screen. (possibly nuking and restoring the context in the process).
Note:
This will cause another minimise/maximise event, so be sure to handle that. Something like starting the counter before launching a URL, and having your minimse (Event.DEACTIVATE) event handler ignore the next call to it.
----Example:
private static var initialisedPlugin:Boolean = false;
openWindow("market://something?package=com.whatever.something");
public static function openWindow(url:String, window:String = "_blank"):void{
screenFixTimer = 20;
navigateToURL(new URLRequest(url), window);
}
function onFrame(e:* = null):void{
if ( screenFixTimer > -1 ) {
screenFixTimer--;
if ( screenFixTimer == -1) {
if ( !initialisedPlugin ) {
initialisedPlugin = true;
FlickbackConnect.init();
}
com.sickle.flickbackFlash.showFlickScreen();
}
}
}
(Or have your Event.ACTIVATE call the fix, etc.)
If it's something like the new Google Play in app billing plugin's overlay causing the blanking, have the flick code execute 40-50 frames after you launch a purchase request. (it'll work nicely behind the overlay).
----Application.xml Manifest Requirements. (All 3 required)
//containsVideo addition (before manifestadditions node)
//thanks to polarthene for this one.
<android>
<!-- for flickscreen -->
<containsVideo>true</containsVideo>
<manifestAdditions><![CDATA[<manifest android:installLocation="auto">
...
//activity addition:
<application>
<!-- for flickscreen -->
<activity android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:name="com.sickle.flickbackjava.FlickScreen" android:screenOrientation="portrait">
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
<intent-filter>
<action android:name="android.intent.action.VIEW" />
</intent-filter>
</activity>
</application>
//extensions addition
<extensions>
<!-- for flickscreen -->
<extensionID>com.sickle.flickbackFlash</extensionID>
</extensions>
---- Download:
Anyhoo, here's a link to anyone who wants to give it a whirl:
http://sicklebrick.com/wp-downloads/TEST_com.sickle.flickbackFlash.ane
If you use it, please let me know how you get on. It's a total hack, but it works for me, and a few others so far. Also, manymany thanks to polarthene for pointing out the containsVideo tags.
---- Other stuff.
Here's some stuff that didn't work for me, but might for you
Josh Tynjala suggested the following which seems to have worked for some:
<uses-sdk android:targetSdkVersion="11" /> <!-- was 17 -->
<uses-sdk android:minSdkVersion="11" /> <!-- was 8-->
Someone else suggested this, sorry I can't remember whom.
<activity android:launchMode="singletop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>