com.samsung.spen.SpenPlugin.java Source code

Java tutorial

Introduction

Here is the source code for com.samsung.spen.SpenPlugin.java

Source

/*
 * Copyright (c) 2015 Samsung Electronics, Co. Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.samsung.spen;

import java.io.File;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;

import com.samsung.android.sdk.SsdkUnsupportedException;
import com.samsung.android.sdk.pen.Spen;
import com.samsung.spen.SpenException.SpenExceptionType;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * This class is responsible for launching both popup and Inline surface.
 */
public class SpenPlugin extends CordovaPlugin {
    private static final int ID = 0;
    private static final int SPEN_FLAGS = 1;
    private static final int RETURN_TYPE = 2;
    private static final int BACKGROUND_COLOR = 3;
    private static final int BACKGROUND_IMAGE_SCALE_TYPE = 4;
    private static final int IMAGE_PATH = 5;
    private static final int IMAGE_URI_SCALE_TYPE = 6;
    private static final int RECTANGLE_X_VALUE = 7;
    private static final int RECTANGLE_Y_VALUE = 8;
    private static final int POPUP_WIDTH = 7;
    private static final int POPUP_HEIGHT = 8;
    private static final int WIDTH = 9;
    private static final int HEIGHT = 10;
    private static final int BODY_RECTANGLE_X_VALUE = 11;
    private static final int BODY_RECTANGLE_Y_VALUE = 12;
    private static final int SPEN_AND_HAND_SUPPORTED = 100;
    private static final int ONLY_HAND_SUPPORTED = 101;
    private static final int SPEN_INITILIZATION_ERROR = 102;
    private static final int MAX_ID_LENGTH = 100;
    private static final String META_DATA = "com.samsung.cordova.spen";
    private static final String TAG = "SpenPlugin";
    private Boolean pluginMetadata = null;
    private Boolean isStatic = null;
    private Activity mActivity;
    private SpenContextParams mContextParams;
    private String mCurrentWorkingId;
    private SpenSurfaceViews mSpenSurfaceViews = new SpenSurfaceViews();
    private SpenSurfaceViews mSpenSurfaceViewsPopup = new SpenSurfaceViews();
    private int mCurrentSurfaceType;
    private int surfaceCount = 0;
    private int mSpenState;

    /** 
     * 
     * Set Id and Syrface Type
     * 
     * @params Id 
     *           String
     * @params surfaceType
     *           int
     * 
     */
    void setIdAndSurfaceType(String id, int surfaceType) {
        mCurrentWorkingId = id;
        mCurrentSurfaceType = surfaceType;
    }

    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
        init();
    }

    private void init() {
        if (isStatic == null || pluginMetadata == null) {
            mActivity = cordova.getActivity();
            String mPackageName = mActivity.getPackageName();
            PackageManager pm = mActivity.getPackageManager();
            try {
                ApplicationInfo ai = pm.getApplicationInfo(mPackageName, PackageManager.GET_META_DATA);
                if (ai.metaData != null) {
                    pluginMetadata = ai.metaData.getBoolean(META_DATA);
                } else {
                    pluginMetadata = false;
                }
            } catch (NameNotFoundException e) {
                pluginMetadata = false;
            }

            isStatic = false;
            int resId = mActivity.getResources().getIdentifier("spen_static", "bool", mActivity.getPackageName());
            try {
                if (resId != 0) {
                    isStatic = mActivity.getResources().getBoolean(resId);
                }
            } catch (Resources.NotFoundException re) {
                isStatic = false;
            }
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "Static is " + isStatic);
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.cordova.CordovaPlugin#onActivityResult(int, int,
     * android.content.Intent)
     */
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "Inside onActivityResult");
            Log.d(TAG, "Intent: " + intent + ", requestCode: " + requestCode);
        }
        if (requestCode == Utils.REQUEST_CODE_SELECT_IMAGE_BACKGROUND) {
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "on background image selected");
            }
            if (mCurrentSurfaceType == Utils.SURFACE_INLINE) {
                mSpenSurfaceViews.getSurfaceView(mCurrentWorkingId).setasBgImage(intent);
            } else {
                Message msgObj = setBgHandler.obtainMessage();
                Bundle b = new Bundle();
                b.putParcelable("intent", intent);
                msgObj.setData(b);
                setBgHandler.sendMessage(msgObj);
            }
        } else {
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "request code is not matching");
            }
        }
    }

    private Handler setBgHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "inside setBgHandler");
            }
            Intent intent = (Intent) msg.getData().getParcelable("intent");
            mSpenSurfaceViewsPopup.getSurfaceView(mCurrentWorkingId).setasBgImage(intent);
        }
    };

    private void initContextDetails(CallbackContext callbackContext) {
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "Inside initContextDetails");
        }
        if (mActivity == null) {
            mActivity = this.cordova.getActivity();
        }
        if (mContextParams == null) {
            mContextParams = new SpenContextParams();
            mContextParams.setSpenCustomDrawPlugin(this);
        }
        mContextParams.setCallbackContext(callbackContext);
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "Inside execute");
        }

        // sometimes, init is not called from initialize
        init();
        // Do not allow apis if metadata is missing
        if (!pluginMetadata) {
            callbackContext.error("METADATA_MISSING");
            Log.e(TAG, "Metadata is missing");
            return false;
        }

        initContextDetails(callbackContext);
        final CallbackContext finalCallbackContext = callbackContext;
        mSpenState = isSpenFeatureEnabled(mActivity.getApplicationContext(), callbackContext);
        if (action.equals("isSupported")) {
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "Inside isSpenSupported");
            }
            if (mSpenState == SPEN_AND_HAND_SUPPORTED) {
                callbackContext.success(SpenExceptionType.SPEN_AND_HAND_SUPPORTED.toString());
                return true;
            } else if (mSpenState == ONLY_HAND_SUPPORTED) {
                callbackContext.success(SpenExceptionType.ONLY_HAND_SUPPORTED.toString());
                // handled this in isSpenFeatureEnabled itself as it common
                // for many cases.
            }
        } else if (action.equals("launchSurfaceInline")) {
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "creating the spen surface inline");
            }
            SpenTrayBarOptions options = createTrayBarOptions(args, Utils.SURFACE_INLINE, callbackContext);
            final SpenTrayBarOptions inlineOptions = options;
            if (inlineOptions != null && mSpenState != SPEN_INITILIZATION_ERROR) {
                mActivity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        String id = inlineOptions.getId();
                        if (mSpenSurfaceViews.getSurfaceView(id) == null) {
                            if (surfaceCount >= SpenSurfaceViews.MAX_SURFACE_COUNT) {
                                SpenException.sendPluginResult(SpenExceptionType.MAX_SURFACE_LIMIT_REACHED,
                                        finalCallbackContext);
                            } else {
                                SPenSurfaceWithTrayBar mPaintViewTrayBar = null;
                                mPaintViewTrayBar = new SPenSurfaceWithTrayBar(mContextParams, inlineOptions);
                                mSpenSurfaceViews.addSurfaceView(id, mPaintViewTrayBar);
                                surfaceCount++;
                                if (!mSpenSurfaceViews.getSurfaceView(id).createSPenSurfaceWithTrayBar()) {
                                    mSpenSurfaceViews.removeSurfaceView(id);
                                    surfaceCount--;
                                    SpenException.sendPluginResult(SpenExceptionType.FAILED_CREATE_SURFACE,
                                            finalCallbackContext);
                                } else {
                                    // finalCallbackContext.success();
                                    PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, "");
                                    pluginResult.setKeepCallback(true);
                                    finalCallbackContext.sendPluginResult(pluginResult);
                                }
                            }
                        } else {
                            SpenException.sendPluginResult(SpenExceptionType.SURFACE_ID_ALREADY_EXISTS,
                                    finalCallbackContext);
                        }
                    }
                });
            }
        } else if (action.equals("launchSurfacePopup")) {
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "creating the spen surface popup");
            }
            SpenTrayBarOptions options = createTrayBarOptions(args, Utils.SURFACE_POPUP, callbackContext);
            if (options != null && mSpenState != SPEN_INITILIZATION_ERROR) {
                String id = options.getId();
                if (mSpenSurfaceViewsPopup.getSurfaceView(id) == null) {
                    if (surfaceCount >= SpenSurfaceViews.MAX_SURFACE_COUNT) {
                        SpenException.sendPluginResult(SpenExceptionType.MAX_SURFACE_LIMIT_REACHED,
                                finalCallbackContext);
                    } else {
                        SPenSurfaceWithTrayBar mPaintViewTrayBar = null;
                        mPaintViewTrayBar = new SPenSurfaceWithTrayBar(mContextParams, options);
                        mSpenSurfaceViewsPopup.addSurfaceView(id, mPaintViewTrayBar);
                        surfaceCount++;
                        if (!mSpenSurfaceViewsPopup.getSurfaceView(id).createSPenSurfaceWithTrayBar()) {
                            mSpenSurfaceViewsPopup.removeSurfaceView(id);
                            surfaceCount--;
                            SpenException.sendPluginResult(SpenExceptionType.FAILED_CREATE_SURFACE,
                                    finalCallbackContext);
                        } else {
                            PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, "");
                            pluginResult.setKeepCallback(true);
                            finalCallbackContext.sendPluginResult(pluginResult);
                        }
                    }
                } else {
                    mSpenSurfaceViewsPopup.getSurfaceView(id).changeSPenTrayBarOptions(options, mContextParams);
                    mSpenSurfaceViewsPopup.getSurfaceView(id).openSPenSurfaceWithTrayBar();
                }
            }
        } else if (action.equals("removeSurfaceInline")) {
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "removing SpenSurface Inline");
            }

            String tempId = args.getString(ID);
            if (tempId != null) {
                tempId = tempId.trim();
                if (tempId.length() > MAX_ID_LENGTH) {
                    tempId = tempId.substring(0, MAX_ID_LENGTH);
                }
            }

            final String id = tempId;
            if (id == null || id.equals("") || id.equals("null")) {
                SpenException.sendPluginResult(SpenExceptionType.INVALID_SURFACE_ID, callbackContext);
                return false;
            }

            if (mSpenState != SPEN_INITILIZATION_ERROR) {
                mActivity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (mSpenSurfaceViews.getSurfaceView(id) != null) {
                            surfaceCount--;
                            mSpenSurfaceViews.getSurfaceView(id).removeSurface();
                            mSpenSurfaceViews.removeSurfaceView(id);
                            finalCallbackContext.success(id);
                        } else {
                            SpenException.sendPluginResult(SpenExceptionType.SURFACE_ID_NOT_EXISTS,
                                    finalCallbackContext);
                        }
                    }
                });
            }
        } else if (action.equals("removeSurfacePopup")) {
            if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                Log.d(TAG, "removing SpenSurface Popup");
            }
            String tempId = args.getString(ID);
            if (tempId != null) {
                tempId = tempId.trim();
                if (tempId.length() > MAX_ID_LENGTH) {
                    tempId = tempId.substring(0, MAX_ID_LENGTH);
                }
            }

            final String id = tempId;

            if (id == null || id.equals("") || id.equals("null")) {
                SpenException.sendPluginResult(SpenExceptionType.INVALID_SURFACE_ID, callbackContext);
                return false;
            }

            if (mSpenSurfaceViewsPopup.getSurfaceView(id) != null) {
                surfaceCount--;
                mSpenSurfaceViewsPopup.getSurfaceView(id).removeSurface();
                mSpenSurfaceViewsPopup.removeSurfaceView(id);
                finalCallbackContext.success(id);
            } else {
                SpenException.sendPluginResult(SpenExceptionType.SURFACE_ID_NOT_EXISTS, finalCallbackContext);
            }
        } else {
            callbackContext.error(SpenExceptionType.ACTION_INVALID.toString());
            return false;
        }
        return true;
    }

    /**
     * 
     * @param args
     *                 JSON array of options sent from the script.
     * @param surfaceType
     *                int
     * @param callbackContext
     *                CallbackContext
     * @return   options
     *                SpenTrayBarOptions
     * @throws JSONException
     */
    private SpenTrayBarOptions createTrayBarOptions(JSONArray args, int surfaceType,
            CallbackContext callbackContext) throws JSONException {
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "Inside createTrayBarOptions");
        }

        String tempId = args.getString(ID);
        if (tempId != null) {
            tempId = tempId.trim();
            if (tempId.length() > MAX_ID_LENGTH) {
                tempId = tempId.substring(0, MAX_ID_LENGTH);
            }
        }

        final String id = tempId;
        if (id == null || id.equals("") || id.equals("null") || !id.matches("^[ !#-)+-.0-9;=@-Z^-{}~]+$")) {
            SpenException.sendPluginResult(SpenExceptionType.INVALID_SURFACE_ID, callbackContext);
            return null;
        }

        int sPenFlags = args.optInt(SPEN_FLAGS, Integer.MIN_VALUE);
        if (sPenFlags == Integer.MIN_VALUE || sPenFlags > Utils.MAX_FLAGS_VALUE
                || sPenFlags < Utils.MIN_FLAGS_VALUE) {
            SpenException.sendPluginResult(SpenExceptionType.INVALID_FLAGS, callbackContext);
            return null;
        }

        int returnType = args.optInt(RETURN_TYPE);
        if (returnType != Utils.RETURN_TYPE_IMAGE_DATA && returnType != Utils.RETURN_TYPE_IMAGE_URI
                && returnType != Utils.RETURN_TYPE_TEXT) {

            SpenException.sendPluginResult(SpenExceptionType.INVALID_RETURN_TYPE, callbackContext);
            return null;
        }

        String backgroundColor = args.getString(BACKGROUND_COLOR);

        String imagePath = args.getString(IMAGE_PATH);
        if (imagePath.equals("") || imagePath.equals("null")) {
            imagePath = null;
        } else {
            imagePath = Uri.decode(imagePath);
            String truncatedPath = truncateQueryPart(imagePath);
            File file = new File(truncatedPath);
            if (file.exists()) {
                imagePath = truncatedPath;
            }
        }

        int bgImageScaleType = args.optInt(BACKGROUND_IMAGE_SCALE_TYPE);
        if (bgImageScaleType != Utils.BACKGROUND_IMAGE_MODE_CENTER
                && bgImageScaleType != Utils.BACKGROUND_IMAGE_MODE_FIT
                && bgImageScaleType != Utils.BACKGROUND_IMAGE_MODE_STRETCH
                && bgImageScaleType != Utils.BACKGROUND_IMAGE_MODE_TILE) {
            bgImageScaleType = Utils.BACKGROUND_IMAGE_MODE_FIT;
        }

        int imageUriScaleType = args.optInt(IMAGE_URI_SCALE_TYPE);
        if (imageUriScaleType != Utils.IMAGE_URI_MODE_CENTER && imageUriScaleType != Utils.IMAGE_URI_MODE_FIT
                && imageUriScaleType != Utils.IMAGE_URI_MODE_TILE
                && imageUriScaleType != Utils.IMAGE_URI_MODE_STRETCH) {
            imageUriScaleType = Utils.IMAGE_URI_MODE_FIT;
        }

        if (surfaceType == Utils.SURFACE_INLINE) {
            if ((sPenFlags & Utils.FLAG_ADD_PAGE) == Utils.FLAG_ADD_PAGE) {
                if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                    Log.d(TAG, "Add Page is not supported in Inline");
                }
                sPenFlags = sPenFlags & ~Utils.FLAG_ADD_PAGE;
            }
        } else if (surfaceType == Utils.SURFACE_POPUP) {

            if ((sPenFlags & Utils.FLAG_EDIT) == Utils.FLAG_EDIT) {
                if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                    Log.d(TAG, "Edit Page is not supported in Popup");
                }
                sPenFlags = sPenFlags & ~Utils.FLAG_EDIT;
            }

            if ((sPenFlags & Utils.FLAG_PEN) == Utils.FLAG_PEN) {
                if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                    Log.d(TAG, "Pen option is provided by default, is not configurable in Popup");
                }
                sPenFlags = sPenFlags & ~Utils.FLAG_PEN;

            }

            if ((sPenFlags & Utils.FLAG_ERASER) == Utils.FLAG_ERASER) {
                if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                    Log.d(TAG, "Eraser option is provided by default, is not configurable in Popup");
                }
                sPenFlags = sPenFlags & ~Utils.FLAG_ERASER;

            }

            if ((sPenFlags & Utils.FLAG_UNDO_REDO) == Utils.FLAG_UNDO_REDO) {
                if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
                    Log.d(TAG, "Undo Redo option is provided by default, is not configurable in Popup");
                }
                sPenFlags = sPenFlags & ~Utils.FLAG_UNDO_REDO;

            }
        } else {
            SpenException.sendPluginResult(SpenExceptionType.INVALID_SURFACE_TYPE, callbackContext);
            return null;
        }

        if ((sPenFlags & Utils.FLAG_TEXT_RECOGNITION) == Utils.FLAG_TEXT_RECOGNITION
                || (sPenFlags & Utils.FLAG_SHAPE_RECOGNITION) == Utils.FLAG_SHAPE_RECOGNITION) {
            sPenFlags = sPenFlags | Utils.FLAG_SELECTION;
        }

        SpenTrayBarOptions options = new SpenTrayBarOptions(sPenFlags);
        options.setId(id);
        options.setIsfeatureEnabled(mSpenState == SPEN_AND_HAND_SUPPORTED ? true : false);
        options.setColor(backgroundColor);
        options.setBgImageScaleType(bgImageScaleType);
        options.setImageUriScaleType(imageUriScaleType);
        options.setReturnType(returnType);
        options.setSurfaceType(surfaceType);
        options.setImagePath(imagePath);
        options.setDensity(mActivity.getApplicationContext().getResources().getDisplayMetrics().density);

        if (surfaceType == Utils.SURFACE_INLINE) {
            long xRect = 0, yRect = 0, width = 0, height = 0, xBodyRect = 0, yBodyRect = 0;
            if (args.isNull(RECTANGLE_X_VALUE) || args.isNull(RECTANGLE_Y_VALUE) || args.isNull(WIDTH)
                    || args.isNull(HEIGHT)) {
                SpenException.sendPluginResult(SpenExceptionType.INVALID_INLINE_CORDINATES, callbackContext);
                return null;
            } else {
                xRect = args.optLong(RECTANGLE_X_VALUE, Integer.MIN_VALUE);
                yRect = args.optLong(RECTANGLE_Y_VALUE, Integer.MIN_VALUE);
                width = args.optLong(WIDTH, Integer.MIN_VALUE);
                height = args.optLong(HEIGHT, Integer.MIN_VALUE);
                xBodyRect = args.optLong(BODY_RECTANGLE_X_VALUE, Integer.MIN_VALUE);
                yBodyRect = args.optLong(BODY_RECTANGLE_Y_VALUE, Integer.MAX_VALUE);
                if (xRect == Integer.MIN_VALUE || yRect == Integer.MIN_VALUE || width == Integer.MIN_VALUE
                        || height == Integer.MIN_VALUE || xBodyRect == Integer.MIN_VALUE
                        || yBodyRect == Integer.MIN_VALUE || xRect > (long) Integer.MAX_VALUE
                        || yRect > (long) Integer.MAX_VALUE || width > (long) Integer.MAX_VALUE
                        || height > (long) Integer.MAX_VALUE || xBodyRect > (long) Integer.MAX_VALUE
                        || yBodyRect > (long) Integer.MAX_VALUE) {
                    SpenException.sendPluginResult(SpenExceptionType.INVALID_INLINE_CORDINATES, callbackContext);
                    return null;
                }
            }
            SurfacePosition surfacePosition = new SurfacePosition(mActivity.getApplicationContext(), (int) width,
                    (int) height, (int) xRect - (int) xBodyRect, (int) yRect - (int) yBodyRect);
            if (!surfacePosition.isSurfaceValid(options, mActivity.getApplicationContext())) {
                SpenException.sendPluginResult(SpenExceptionType.INVALID_INLINE_CORDINATES, callbackContext);
                return null;
            }
            options.setSurfacePosition(surfacePosition);
        } else if (surfaceType == Utils.SURFACE_POPUP) {
            long popupWidth = 0, popupHeight = 0;
            popupWidth = args.optLong(POPUP_WIDTH, Integer.MIN_VALUE);
            popupHeight = args.optLong(POPUP_HEIGHT, Integer.MIN_VALUE);
            SurfacePosition surfacePosition = new SurfacePosition(mActivity.getApplicationContext(),
                    (int) popupWidth, (int) popupHeight);
            options.setSurfacePosition(surfacePosition);
        }
        return options;
    }

    /**
     * truncates the part query part if the image has it Ex:-
     * /sdcard/hello.png?123 returns /sdcard/hello.png
     * 
     * @param imagePath
     *                String
     * @return imagePath
     */
    private String truncateQueryPart(String imagePath) {
        int qMarkIndex = imagePath.lastIndexOf('?');
        if (qMarkIndex != -1) {
            imagePath = imagePath.substring(0, qMarkIndex);
        }
        return imagePath;
    }

    /**
     * Delete SpenSurface
     * 
     * @param id
     *           String
     */
    void deleteSpenSurface(String id) {
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "Inside deleteSpenSurface");
        }
        if (mSpenSurfaceViews.getSurfaceView(id) != null) {
            mSpenSurfaceViews.removeSurfaceView(id);
        }
    }

    /**
     * checks if the Spen feature is enabled or not. Send the result as
     * SPEN_SUPPORTED if the Spen is supported otherwise the corresponding error
     * message.
     * 
     * @param context
     *                Context
     * @param callbackContext
     *                CallbackContext
     * @return spenState
     */
    private int isSpenFeatureEnabled(Context context, CallbackContext callbackContext) {
        if (Log.isLoggable(Utils.SPEN, Log.DEBUG)) {
            Log.d(TAG, "inside isSpenFeatureEnabled");
        }
        int spenState = SPEN_INITILIZATION_ERROR;
        Spen spenPackage = new Spen();
        try {
            if (isStatic) {
                spenPackage.initialize(context, 5, Spen.SPEN_STATIC_LIB_MODE);
            } else {
                spenPackage.initialize(context);
            }
            if (spenPackage.isFeatureEnabled(Spen.DEVICE_PEN)) {
                spenState = SPEN_AND_HAND_SUPPORTED;
            } else {
                spenState = ONLY_HAND_SUPPORTED;
            }
        } catch (SsdkUnsupportedException e) {
            Log.d(TAG, "failed initializing the spen package " + e.getMessage());
            e.printStackTrace();
            // if the spen sdk version name (dynamic sdk) is lesser than
            // the jar version name (which is inlcuded in the spen plugin
            // then LIBRARY_UPDATE_IS_REQUIRED should be thrown.
            // Current, Spen SDK not handled it properly.
            SpenExceptionType errorType = null;
            boolean isExceptionTypeFound = false;
            if (spenPackage != null && !isStatic) {
                String dynamicSDKPkgName = Spen.SPEN_NATIVE_PACKAGE_NAME;
                try {
                    PackageInfo packageInfo = mActivity.getPackageManager().getPackageInfo(dynamicSDKPkgName, 0);
                    if (packageInfo != null) {
                        String dynamicSDKVersionName = packageInfo.versionName.replace(".", "");
                        String pluginJarVersionName = spenPackage.getVersionName().replace(".", "");
                        if (dynamicSDKVersionName.compareTo(pluginJarVersionName) < 0) {
                            errorType = SpenExceptionType.LIBRARY_UPDATE_IS_REQUIRED;
                            isExceptionTypeFound = true;
                        }
                    }
                } catch (NameNotFoundException e1) {
                    e1.printStackTrace();
                }
            }
            if (!isExceptionTypeFound) {
                errorType = SpenException.processUnsupportedException(e);
            }
            PluginResult pluginResult = new PluginResult(PluginResult.Status.ERROR, errorType.toString());
            pluginResult.setKeepCallback(false);
            callbackContext.sendPluginResult(pluginResult);
        }
        spenPackage = null;
        return spenState;
    }
}