Android - Close App On Interruption

We want our app to close on interruptions, such as sleep, or voice-calls. Unfortunately the application does not close successfully on a voice call interrupt. When returning to the application after a voice call, the user is presented with a blank black screen and is unable to resume application use. The user found that the only way to exit this state was to activate the device lock screen using the power button. After unlocking the device, the user was returned to the device home screen.

Device: Samsung T959V (Vibrant Plus) B T959VUVJLB Installed Devices: Samsung P1010 (Galaxy Tab) A 2.2.1

[code]
local function onSuspend( event )

if( ‘applicationSuspend’ == event.type ) then
if( ‘simulator’ ~= system.getInfo( ‘environment’ )) then
os.exit()
end
end
end

Runtime:addEventListener( ‘system’, onSuspend )
[/code] [import]uid: 4596 topic_id: 19088 reply_id: 319088[/import]

The “black screen” issue that happened on app resume was fixed in the new release version. Please test it out for yourself to verify that it is fixed. This will make the exit on suspend unnecessary.

Also, I highly recommend that you do not call “os.exit()” ever. This is the equivalent of a “Force Quit” on OS X or Ctrl+Alt+Del “End Process” on Windows. It kills the application in a not so nice way and if an app reviewer happens to notice this in “adb logcat”, then may consider this a crash and reject your app.

Instead, I recommend that you use the new “native.requestExit()” function. This will close the app the correct way on Android via the Activity.finish() method. This function is currently only supported on Android devices. It will do nothing on iOS and within the simulator. [import]uid: 32256 topic_id: 19088 reply_id: 73818[/import]

Hi Josh,
the black screen issue is present also in the 377 built.
I use the 377 to make app back compatible with arm6

It’s possible to adopt some code (to be used in the 377) to prevent “black screen” and other instability after screen lock/unlock?
bye,
Felix [import]uid: 108637 topic_id: 19088 reply_id: 74642[/import]

Felix,

We are not able to provide support for builds that outdated. Users are free to use them but are warned we cannot assist with issues like this.

Apologies,
Peach [import]uid: 52491 topic_id: 19088 reply_id: 74661[/import]

Hi,

I don’t want to start another thread, however:

I’m using the latest Corona-SDK build and hit the same issue:
When I suspend my game and enter a different app and want to return to my game I will get a black screen for quite some time before my game resumes. I’m using Galaxy S2 and it takes around 5-10 seconds to resume. My testers using slower devices report this takes considerably longer.
I don’t see this on iOS.

Any tips? [import]uid: 109453 topic_id: 19088 reply_id: 113145[/import]

Krystian,

I’ve never heard of an issue like this. You are going to have to isolate it more. Have a look at the Android log via “adb logcat” or DDMS and check for any error or warnings that popup when you resume your app.

Also, is your app listening for system events such as suspend, resume, exit, etc.? If so, try putting a print() function at the top and bottom of that function and see how long it takes for your app to resume. The print() functions will print to the Android log, which you can via “adb logcat”. [import]uid: 32256 topic_id: 19088 reply_id: 113240[/import]

Joshua:

I’ve tried running logcat, however I cannot get any logs from my app.
At the beginning of main I’ve got:

io.output():setvbuf('no')  

set and it works fine on iOS, not on Android.

Any tips?
Oh and just to make sure: I do have logs, I can see logs from my other [not corona-sdk] apps.
EDIT:
although I can’t get my prints to show up, I can see what Dalvikvm is doing. It seems like when I come back from suspension it’s loading all of the textures back into memory and it takes a while.
I came to that conclusion by comparing time it takes to load the textures on my “loading screen” with the time it takes to come back from resume [it’s either black screen or some gray-ish screen with darker gray-ish rectangles in places where my pause menu buttons should be].
Also, the logs of dalvikvm seems to be the same - it’s trying to free up some space:

06-27 09:11:35.619: INFO/dalvikvm-heap(32460): Grow heap (frag case) to 12.658MB for 2752336-byte allocation  
06-27 09:11:35.634: DEBUG/dalvikvm(32460): GC\_CONCURRENT freed \<1K, 72% free 12876K/45063K, paused 2ms+2ms  
06-27 09:11:35.704: DEBUG/dalvikvm(32460): GC\_FOR\_ALLOC freed \<1K, 72% free 12876K/45063K, paused 11ms  

this kind of logs are repeated multiple times until all the textures are loaded.

This happens only when I suspend my app, open some other app and then go back to mine. It does not happen if I only go to home screen and back to my app.
EDIT2:
My logs do not show because I’m using logging framework, which in turn uses io.stdout.write.
Even though I put io.flush() after it, it didn’t spit the lines to logcat. [import]uid: 109453 topic_id: 19088 reply_id: 113299[/import]

Normally, you do not have to call io.output() in Lua. We’ve set up Corona to automatically output print() statements to the Android system log by default. Perhaps that logging framework that you are using has changed that default, in which case you should perhaps use that for debugging instead?

Oh, and if you are seeing the heap grow in size and the garbage collector being invoked frequently, then that tells me that your app is allocating and deleting large blocks of memory frequently. That typically happens when you update onscreen text frequently such as with a FPS counter. Updating text is expensive because it involves creating a new bitmap in memory, drawing text to it, and then transferring that text bitmap to OpenGL. If you do that on every frame, then that is a major performance killer. Although some Android devices handle this better than others. For example, a Samsung Galaxy SII can handle frequent text updates quite well and you rarely hear anything from the garbage collector, but a Galaxy Nexus will collect garbage on every frame killing performance. Just an example of the random behavior difference that you can see on different Android devices. Crazy, eh? [import]uid: 32256 topic_id: 19088 reply_id: 113389[/import]

Joshua,

What I pasted happens only during my loading screen in which I load all of the image sheets I use in game [apart from all the sheets there are only few large files [backgrounds etc.] which are not loaded there.

I’ve modified my logging framework to work with print and I can see, that onSystemEvent listener is called after the black screen. It seems I can do nothing about it from my end :frowning:

If I could at least have a loading background instead of this black screen - this would help a lot. [import]uid: 109453 topic_id: 19088 reply_id: 113433[/import]

What I think is happening is that you have a lot of images onscreen and they are all being re-loaded from file when your app is being resumed, back from the suspended state. This is a difference in behavior between Android on iOS. You see, Android forces apps to destroy their OpenGL view and dump all of the loaded images/textures from memory when leaving the app/activity. So, when your app resumes, Corona is forced to re-load all image files again in order to re-display them onscreen as it was displayed before. iOS doesn’t do this and maintains all images in memory, but Android does and we have no choice in the matter.

This means that you’ll need to optimize your image handling. The best way to do this is to use our sprite API and pack as many sprites/images into a single image file as possible. This way Corona only has to load 1 image file in order to display several different image objects. Does that make sense? There are 3rd party texture packer software that can do this for you such as Spriteloq and TexturePacker.

Another optimization that you can make is making sure that your image file widths and height (in pixels) are a power of 2, such as 64x64, 128x128, etc. They don’t have to be square, so 64x128 is legal. This power of 2 thing is an OpenGL limitation. If your image is not a power of 2, then Corona will automatically increase the width/height of your image in memory to a power of 2, which is another performance hit. Especially if your image is just above one of those power of 2 thresholds such 1025… which would have to be increased to 2048… and that’s a hug hit in performance and memory.

Anyways, I hope the above is helpful.
You may want to set up a test project and try measuring the performance difference for yourself between using individual image files and full spritesheet image files. [import]uid: 32256 topic_id: 19088 reply_id: 113665[/import]

Hi Joshua,

I’m already using image sheets. Graphics are quite optimized now. I won’t be able to do much on this front, however, there is something you can do.
Allow me to specify an image file, which will be shown during this load. This way users at least will know what’s going on.
The only other way I see (which definitely is something I don’t want to do)is to dispose all of the image sheets on suspend. But this just seems stupid:/

Krystian [import]uid: 109453 topic_id: 19088 reply_id: 113680[/import]

You can already do this now, but what you would have to do is delete all of your display objects during the suspend event and then display your own splash screen with progress bar upon resume while you re-load your app. I’ve seen other games on Android do it this way. Including games not made with Corona. I think this is the best way to handle it for apps that use a lot of resources. The progress bar is particularly important. [import]uid: 32256 topic_id: 19088 reply_id: 113685[/import]

Huh…

This seems almost impossible, and will mean a complete rewrite of a lot of code!
The moment I’ve got over 100 display objects on screen, each of them doing something, with it’s own state [I decorate display objects], functions etc. etc. Handling removal of all of them and then recreation when the only thing needed is to display an image while game is loading assets back :confused:

There’s got to be another way to handle it :confused:

EDIT:

I was surprised by the loading time during resume, I’ve tested our game on Android multiple times, having phone calls in the middle and never seeing such thing. I’ve checked out our branch which is pre-imagesheet, to test it using old sprite sheets and without using imagesheet to load static images [every image in separate file]. It takes about 3 seconds to show up the game [using the 704 build], where on the same device, using latest daily build it takes around 30 seconds to load version with imagesheets.
Currently, during the game, there are only ~10 small display objects, which are loaded from an imagesheet, and previously they were loaded from separate files. The rest [animations] were sprite sheets and now they are image sheets. This leads me to a conclusion, that there’s something wrong with image sheets. What do you think?

EDIT 2:
I’ve tried using openPopUp() function from director class to display a loading image during applicationSuspended event, hoping that it will show up when game is resuming. It sometimes does, but only when Android won’t free to much of the memory [i.e. when you wait until screen is off and you unlock your phone] :frowning: Damn [import]uid: 109453 topic_id: 19088 reply_id: 113867[/import]

The 3 to 30 second difference is definitely something to be concerned about. However, our tests have shown that loading a single image sheet file is considerably faster than loading several image files. If loading an image sheet was that bad, then we would have heard about this a while ago from other customers.

Are you sure that you are not loading any other assets/resources between those 2 app versions of yours? There’s got to be some other differences. Just needs to be isolated. [import]uid: 32256 topic_id: 19088 reply_id: 113933[/import]

Well I gave up isolating differences. I’m releasing part of my imagesheets [the larger ones] during suspension and I’m loading them on resume.
This gives me around 3-4 seconds of black screen during resume and then my loading screen appears for the rest of the time.
It’s far from perfect, but much better than it was before.
If only I knew about that during design stage :confused: [import]uid: 109453 topic_id: 19088 reply_id: 114418[/import]

Perhaps the issue is that your image sheets are too big? As in they exceed the max OpenGL texture size for the device? When this happens, Corona is forced to scale down the image to something that OpenGL (ie: the GPU) will accept, which of course takes more CPU time. If this happens, then Corona will log it to the Android system log.

The really old low-end Android devices have a max texture size of 1024x1024 pixels. But most Android devices I’ve tested with have a max texture size of 2048x2048 pixels. If you are going beyond that, then that might be the problem. [import]uid: 32256 topic_id: 19088 reply_id: 114503[/import]

Nope, all of the textures are below 2048x2048. Texture packer takes care of this.
I’m testing on Galaxy S2. Not the newest, but still high end.
I have to admit, I would never hit that issue on my own. I was of course suspending my app and resuming it, but it was never from another app, which was memory hungry. It was a great shock to see what I saw. [import]uid: 109453 topic_id: 19088 reply_id: 114711[/import]