Issue
I am using a very unstable library on Android that crashes sporadically. I start it using the startActivity() in my code.
The unstable part of the code is doing a lot of video processing and uploading the result to a server. I do not really mind if the activity crashes, but I need to signal the server that it did.
The crash comes from a memory leak (no time to solve it yet). Is there a way I can catch the error a display a more friendly/funny message instead?
try {
context.startActivity(intent);
} catch (ApplicationCrashedException e) {
server.notifyServerOfCrash();
toast("I really disliked your face...");
}
Edit: Here is the Error:
java.lang.OutOfMemoryError
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at java.nio.MemoryBlock.allocate(MemoryBlock.java:125)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:72)
at io.cine.android.streaming.FFmpegMuxer.writeSampleData(FFmpegMuxer.java:151)
at io.cine.android.streaming.AndroidEncoder.drainEncoder(AndroidEncoder.java:128)
at io.cine.android.streaming.TextureMovieEncoder.handleFrameAvailable(TextureMovieEncoder.java:264)
at io.cine.android.streaming.TextureMovieEncoder$EncoderHandler.handleMessage(TextureMovieEncoder.java:409)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at io.cine.android.streaming.TextureMovieEncoder.run(TextureMovieEncoder.java:219)
at java.lang.Thread.run(Thread.java:841)
For some reason once the BroadcastActivity runs out of memory, the Activity gets killed and comes back to the previous one. It then displays the 'app' has stopped working Dialog. If I press OK, it kills the entire application and comes back to the home screen.
Ideally I would just have it come back to the previous activity notifying the server silently. (Not killing the application)
Solution
Is there a way I can catch the error a display a more friendly/funny message instead?
If the app is leaking so much memory that it crashes, you cannot easily catch this.
Why you can't always catch this
When you start running out of memory, exceptions are thrown from any part of your app's code that tries to allocate more memory than is available. So it isn't just your library that will throw the exceptions.
How you could detect this
Catch the OutOfMemoryError and make an effort to tell user/server
Your results will vary, but you could wrap the Thread's run() method with a try catch pair and try to catch the out of memory error. You will still be out of memory and any thing you do in the catch code might fail because of it. Still it might work if the process frequently allocates large chunks of memory which would mean there is still a little bit left.
Example:
public void run() {
try {
//video process code
} catch (OutOfMemoryError error) {
//we are still out of memory so these operations might fail
tellServerWeFailed();
triggeruserDialog();
}
}
onTrimMemory() override
You could also try stopping your video tasks when onTrimMemory() is called. Your mileage may vary, I've never been able to get it to work consistently across different Android devices.
Error Reporting Framework
One solution that is pretty involved is to use a third party error reporting framework as they will often let you show your user custom crash messages.
Check out http://www.acra.ch/ and specifically the documentation on User Messages
Started Service
I do not really mind if the activity crashes, but I need to signal the server that it did.
Great! What you might try is to use a started service that android automatically relaunches after the crash. The details on how to tell your server are up to you. You might find that you will need to save some token or other information so that you can tell your server which session has ended so you might, for example, always keep that information saved in Preference entry and read it out after the crash.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(LOG_TAG, "Received start id " + startId + ": " + intent);
if (intent == null) {
Log.w(LOG_TAG, "Service was stopped and automatically restarted by the system. ");
//Tell your server about the crash.
stopSelf();
}
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
See http://developer.android.com/reference/android/app/Service.html#ServiceLifecycle
More about running out of memory on Android
To maintain a functional multi-tasking environment, Android sets a hard limit on the heap size for each app. The exact heap size limit varies between devices based on how much RAM the device has available overall. If your app has reached the heap capacity and tries to allocate more memory, it will receive an OutOfMemoryError.
In some cases, you might want to query the system to determine exactly how much heap space you have available on the current device—for example, to determine how much data is safe to keep in a cache. You can query the system for this figure by calling getMemoryClass(). This returns an integer indicating the number of megabytes available for your app's heap. This is discussed further below, under Check how much memory you should use. (source)
Some key points:
- Your entire app shares the system-assigned memory heap.
- Once you've leaked memory, it is gone until the application is restarted.
- You won't be able to segregate memory leaked in one activity by leaving that activity.
Answered By - Jon
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.