7

My application loads various shared objects when created. I would like to catch errors thrown because of the shared objects not being present on the device and show a better error message to the user. How do I achieve this?

I can catch the java.lang.UnsatisfiedLinkError like so

static
{
    try
    {
        System.loadLibrary("MyApplication");
    }
    catch(java.lang.UnsatisfiedLinkError e)
    {
        if(e.getMessage().contains("libSharedObject"))
        {
            Log.e( TAG, "This device does not support ..." );
        }
        else
        {
            throw e;
        }
    }
}

But Toast.makeText(...).show() and other application message boxes won't work because the application will die in onCreate() because of the previous error.

Is there a way of changing the systems default error message of "Unfortunately there was an error.."? Or a way of displaying an error message with another process or the Android OS?

ashleysmithgpu
  • 1,867
  • 20
  • 39

2 Answers2

11

I found an answer using this answer. I catch the exception in the static {} block, set a member variable that there was an error and a message, then I create a new thread which displays the error using Toast and use Looper to call the message loop in that thread. I need to sleep the main thread for a while though before I let the application crash.

static boolean mWasError = false;
static String mErrorMessage = "";

static
{
    try
    {
        System.loadLibrary("MyApplication");
    }
    catch(java.lang.UnsatisfiedLinkError e)
    {
        if(e.getMessage().contains("libOpenCL"))
        {
            Log.e( TAG, "This device does not support OpenCL" );
            mWasError = true;
            mErrorMessage = "This device does not support OpenCL";
        }
        else
        {
            throw e;
        }
    }
}


@Override
protected void onCreate( Bundle savedInstanceState )
{
    if(mWasError)
    {
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(getApplicationContext(), mErrorMessage, Toast.LENGTH_SHORT).show();
                Looper.loop();

            }
        }.start();

        try
        {
            Thread.sleep(10000);
        }
        catch(InterruptedException e)
        {
        }
    }

    // Will crash here if there was an error
    super.onCreate(savedInstanceState);
Community
  • 1
  • 1
ashleysmithgpu
  • 1,867
  • 20
  • 39
1

You could start load libraries later when you have your main Activity is displaying. If an exception gets thrown you will be able to show a Toast or an AlertDialog then.

Although this all is strange. Aren't the *.so a part of the apk, you seem to know which of them you have in your apk.

Alexander Kulyakhtin
  • 47,782
  • 38
  • 107
  • 158
  • The shared objects are stored on the device. However they are sometimes not present. Maybe I could package the shared objects with the application, but then I don't know how I would catch the various errors that would create when the device does not support the .so. I was hoping there would be an async way of creating a notification or error message from the os. I suppose I could also delay load the symbols, however that would require quite a few changes to the application. – ashleysmithgpu Aug 18 '14 at 10:16