Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I catch a static java.lang.UnsatisfiedLinkError from Android and show the user a better error message?

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?

like image 524
ashleysmithgpu Avatar asked Aug 18 '14 10:08

ashleysmithgpu


People also ask

What is UnsatisfiedLinkError in Java?

Class UnsatisfiedLinkErrorThrown if the Java Virtual Machine cannot find an appropriate native-language definition of a method declared native .


1 Answers

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);
like image 50
ashleysmithgpu Avatar answered Nov 14 '22 22:11

ashleysmithgpu