Houcine
Houcine

Reputation: 24181

ExceptionInInitializerError when instanciating AsyncTask inside Plugin.execute()

im developping an app and inside it i'm using cordova Api to communicate between Sencha code and *Android native Code*.

inside my plugin's execute method , i'm launching an AsyncTask( for device registration) , but i got ExceptionInInitializerError in line 36 ( instanciation of TaskDeviceRegistration).

RegistrationDevicePlugin :

public class DeviceRegistrationPlugin extends Plugin {

    public static final String TAG = "DeviceRegistrationPlugin";
    public static final String ACTION_REGISTER_DEVICE = "registerDeviceAction";

    protected String callBackMethod;

    @Override
    public PluginResult execute(String action, JSONArray args, String callBackId) {

        String token;
        if(action.equals(ACTION_REGISTER_DEVICE)) {
            try {
                token = args.getString(0);
                if(token != null) {
                    // launch the task to register device
                    SharedPreferences prefs = cordova.getActivity().getSharedPreferences(WebServiceRequest.PREFS_IDENTIFICATION, Context.MODE_PRIVATE);
                    prefs.edit().putString(WebServiceRequest.PREF_TOKEN_PARAM, token).commit();
                    TaskRegisterDevice task = new TaskRegisterDevice(cordova.getActivity());// this is the line 36
                    task.execute();

                    // tell the plugin that the callBack will be executed after the task
                    // has finished his work.
                    this.callBackMethod = callBackId;
                    PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
                    pluginResult.setKeepCallback(true);
                    return pluginResult;
                }
                else {
                    return new PluginResult(Status.ERROR, "token required");
                }

            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
            }
        }
        else {
            // invalid action sended to the plugin
            return new PluginResult(PluginResult.Status.INVALID_ACTION);
        }
    }


    /**
     * asynctask to register the device
     * @author houcine
     * 
     */
    class TaskRegisterDevice extends AsyncTask<Void, Void, Boolean> {

        protected Context context;

        public TaskRegisterDevice(Context context) {
            this.context = context;
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                return WebServiceRequest.RegisterDevice(context);
            } catch (JSONException e) {
                e.printStackTrace();
                return true;
            } catch (IOException e) {
                e.printStackTrace();
                return true;
            }
        }

        @Override
        protected void onPostExecute(Boolean result) {
            // return new plugin result when synchronization done
            Log.d(TAG, "resultat DeviceRegistration : "+result + " , \ncallBackMethod : "+callBackMethod);
            PluginResult pluginResult = new PluginResult(
                    PluginResult.Status.OK, result);
            pluginResult.setKeepCallback(false);
            success(pluginResult, callBackMethod);
        }

    }

}

ManifestFile :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.myapp.activity"
    android:versionCode="1"
    android:versionName="1.0.2" >

     <supports-screens
     android:largeScreens="true"
     android:normalScreens="true"
     android:smallScreens="true"
     android:resizeable="true"
     android:anyDensity="true"
     />

     <uses-sdk android:minSdkVersion="5" android:targetSdkVersion="16"/>
     //other stuff : declaration of <application> tag , activities , services...etc
>

and logCat :

01-01 06:54:26.251: E/AndroidRuntime(6189): FATAL EXCEPTION: Thread-31
01-01 06:54:26.251: E/AndroidRuntime(6189): java.lang.ExceptionInInitializerError
01-01 06:54:26.251: E/AndroidRuntime(6189):     at com.myapp.plugins.DeviceRegistrationPlugin.execute(DeviceRegistrationPlugin.java:36)
01-01 06:54:26.251: E/AndroidRuntime(6189):     at org.apache.cordova.api.PluginManager$1.run(PluginManager.java:192)
01-01 06:54:26.251: E/AndroidRuntime(6189):     at java.lang.Thread.run(Thread.java:1096)
01-01 06:54:26.251: E/AndroidRuntime(6189): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
01-01 06:54:26.251: E/AndroidRuntime(6189):     at android.os.Handler.<init>(Handler.java:121)
01-01 06:54:26.251: E/AndroidRuntime(6189):     at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
01-01 06:54:26.251: E/AndroidRuntime(6189):     at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
01-01 06:54:26.251: E/AndroidRuntime(6189):     at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
01-01 06:54:26.251: E/AndroidRuntime(6189):     ... 3 more

NOTE : the app is working just fine on HTC ONE S , HTC ONE X , SAMSUNG GALAXY S II , SAMSUNG GALAXY SIII with android sdk version : 4.0 or higher , but it doesn't work for devices with android version like : 2.2.2 , 2.3.5 , 2.3.3

Upvotes: 2

Views: 2446

Answers (1)

Vladimir Mironov
Vladimir Mironov

Reputation: 30864

AsyncTask should be created and executed on the UI thread. It looks like DeviceRegistrationPlugin.execute() method is invoked outside the main thread that's why you are getting the error.

You can try to fix it this way:

cordova.getActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
        TaskRegisterDevice task = new TaskRegisterDevice(cordova.getActivity());
        task.execute();
    }
});

Upvotes: 6

Related Questions