com.vidinoti.pixlive.PixLive.java Source code

Java tutorial

Introduction

Here is the source code for com.vidinoti.pixlive.PixLive.java

Source

package com.vidinoti.pixlive;

import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.media.RingtoneManager;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.vidinoti.android.vdarsdk.DeviceCameraImageSender;
import com.vidinoti.android.vdarsdk.NotificationCompat;
import com.vidinoti.android.vdarsdk.NotificationFactory;
import com.vidinoti.android.vdarsdk.VDARAnnotationView;
import com.vidinoti.android.vdarsdk.VDARCode;
import com.vidinoti.android.vdarsdk.VDARCodeType;
import com.vidinoti.android.vdarsdk.VDARPrior;
import com.vidinoti.android.vdarsdk.VDARRemoteController;
import com.vidinoti.android.vdarsdk.VDARSDKController;
import com.vidinoti.android.vdarsdk.VDARSDKControllerEventReceiver;
import com.vidinoti.android.vdarsdk.VDARTagPrior;

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

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.net.URL;
import java.net.MalformedURLException;

/**
 * This class echoes a string called from JavaScript.
 */
public class PixLive extends CordovaPlugin implements VDARSDKControllerEventReceiver {

    private static final String TAG = "PixLiveCordova";

    class TouchInterceptorView extends FrameLayout {
        public boolean touchEnabled = true;

        private View.OnTouchListener privateListener = null;

        public TouchInterceptorView(android.content.Context context) {
            super(context);
        }

        public void setTouchEnabled(boolean val) {
            touchEnabled = val;
        }

        private int getRelativeLeft(View myView) {
            if (myView.getParent() == myView.getRootView())
                return myView.getLeft();
            else
                return myView.getLeft() + getRelativeLeft((View) myView.getParent());
        }

        private int getRelativeTop(View myView) {
            if (myView.getParent() == myView.getRootView())
                return myView.getTop();
            else
                return myView.getTop() + getRelativeTop((View) myView.getParent());
        }

        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            //Log.v(TAG,"touch: action:" + ev.getAction() + " touchEnabled: " + touchEnabled +" intercepting " + intercepting);

            if ((!touchEnabled || arViews.size() == 0)) {
                return super.onInterceptTouchEvent(ev);
            }

            int thisViewLeft = getRelativeLeft(this);
            int thisViewTop = getRelativeTop(this);

            //Check if we fall into one AR view

            for (Map.Entry<Integer, VDARAnnotationView> s : arViews.entrySet()) {
                VDARAnnotationView view = s.getValue();

                if (view.getVisibility() != View.VISIBLE || view.getParent() == null) {
                    continue;
                }

                //WARNING: We assume here that the AR view share the same parent as this view.

                float arViewX = view.getLeft();
                float arViewY = view.getTop();

                for (int i = 0; i < ev.getPointerCount(); i++) {

                    float xPos = ev.getX(i) - thisViewLeft;
                    float yPos = ev.getY(i) - thisViewTop;

                    if (xPos >= arViewX && xPos < arViewX + view.getWidth() && yPos >= arViewY
                            && yPos < arViewY + view.getHeight()) {
                        return true;
                    }
                }
            }

            return super.onInterceptTouchEvent(ev);
        }

        @Override
        public boolean onTouchEvent(MotionEvent ev) {

            //Forward it to ar views
            for (Map.Entry<Integer, VDARAnnotationView> s : arViews.entrySet()) {
                VDARAnnotationView view = s.getValue();

                float arViewX = view.getLeft();
                float arViewY = view.getTop();

                ev.offsetLocation(-arViewX, -arViewY);

                if (view.dispatchTouchEvent(ev)) {
                    return true;
                }

                ev.offsetLocation(arViewX, arViewY);
            }
            return false;
        }

    }

    private HashMap<Integer, VDARAnnotationView> arViews = new HashMap<Integer, VDARAnnotationView>();

    private DeviceCameraImageSender imageSender = null;

    private TouchInterceptorView touchView = null;

    private CallbackContext eventHandler = null;

    protected void pluginInitialize() {

        startSDK(cordova.getActivity());

        VDARSDKController.getInstance().setEnableCodesRecognition(true);

        VDARSDKController.getInstance().setActivity(cordova.getActivity());
        VDARSDKController.getInstance().registerEventReceiver(this);

        VDARSDKController.getInstance().addNewAfterLoadingTask(new Runnable() {
            @Override
            public void run() {

                Intent intent = cordova.getActivity().getIntent();

                if (intent != null && intent.getExtras() != null && intent.getExtras().getString("nid") != null) {

                    VDARSDKController.getInstance().processNotification(intent.getExtras().getString("nid"),
                            intent.getExtras().getBoolean("remote"));
                }
            }
        });

        cordova.getActivity().runOnUiThread(new Runnable() {
            public void run() {
                if (touchView == null) {
                    View v = webView.getView();

                    FrameLayout parent = ((FrameLayout) v.getParent());
                    parent.removeView(v);

                    touchView = new TouchInterceptorView(cordova.getActivity());

                    touchView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.MATCH_PARENT));

                    cordova.getActivity().setContentView(touchView);

                    touchView.addView(v);

                    v.setBackgroundColor(Color.TRANSPARENT);
                }
            }
        });
    }

    static void startSDK(final Context c) {

        if (VDARSDKController.getInstance() != null) {
            return;
        }

        String storage = c.getApplicationContext().getFilesDir().getAbsolutePath() + "/pixliveSDK";

        String licenseKey = null;

        try {
            ApplicationInfo ai = c.getPackageManager().getApplicationInfo(c.getPackageName(),
                    PackageManager.GET_META_DATA);
            Bundle bundle = ai.metaData;
            licenseKey = bundle.getString("com.vidinoti.pixlive.LicenseKey");
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Unable to start PixLive SDK without valid storage and license key.");
            return;
        } catch (NullPointerException e) {
            Log.e(TAG, "Unable to start PixLive SDK without valid storage and license key.");
            return;
        }

        if (storage == null || licenseKey == null) {
            Log.e(TAG, "Unable to start PixLive SDK without valid storage and license key.");
            return;
        }

        VDARSDKController.startSDK(c, storage, licenseKey);

        /* Comment out to disable QR code detection */
        VDARSDKController.getInstance().setEnableCodesRecognition(true);

        VDARSDKController.getInstance().setNotificationFactory(new NotificationFactory() {

            @Override
            public Notification createNotification(String title, String message, String notificationID) {

                Intent appIntent = c.getPackageManager().getLaunchIntentForPackage(c.getPackageName());

                appIntent.putExtra("nid", notificationID);
                appIntent.putExtra("remote", false);

                PendingIntent contentIntent = PendingIntent.getActivity(c, 0, appIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);

                ApplicationInfo ai = c.getApplicationInfo();

                NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(c)
                        .setSmallIcon(ai.icon != 0 ? ai.icon : android.R.drawable.star_big_off)
                        .setContentTitle(title).setContentText(message).setContentIntent(contentIntent)
                        .setAutoCancel(true).setVibrate(new long[] { 100, 200, 200, 400 })
                        .setLights(Color.BLUE, 500, 1500);

                mBuilder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));

                return mBuilder.getNotification();
            }
        });
    }

    public void onReset() {

        cordova.getActivity().runOnUiThread(new Runnable() {
            public void run() {
                for (VDARAnnotationView view : arViews.values()) {
                    view.onPause();

                    if (view.getParent() != null) {
                        touchView.removeView(view);
                    }
                }
                arViews.clear();
            }
        });
    }

    @Override
    public void onNewIntent(Intent intent) {
        if (intent != null && intent.getExtras() != null && intent.getExtras().getString("nid") != null
                && VDARSDKController.getInstance() != null) {

            VDARSDKController.getInstance().processNotification(intent.getExtras().getString("nid"),
                    intent.getExtras().getBoolean("remote"));
        }
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (action.equals("createARView") && args.length() >= 5) {
            int x = args.getInt(0);
            int y = args.getInt(1);
            int width = args.getInt(2);
            int height = args.getInt(3);
            int ctrlID = args.getInt(4);
            this.createARView(x, y, width, height, ctrlID, args.length() >= 6 ? args.getBoolean(5) : true,
                    callbackContext);
            return true;
        } else if (action.equals("beforeLeave") && args.length() >= 1) {
            int ctrlID = args.getInt(0);
            this.beforeLeave(ctrlID, callbackContext);
            return true;
        } else if (action.equals("afterLeave") && args.length() >= 1) {
            int ctrlID = args.getInt(0);
            this.afterLeave(ctrlID, callbackContext);
            return true;
        } else if (action.equals("beforeEnter") && args.length() >= 1) {
            int ctrlID = args.getInt(0);
            this.beforeEnter(ctrlID, callbackContext);
            return true;
        } else if (action.equals("afterEnter") && args.length() >= 1) {
            int ctrlID = args.getInt(0);
            this.afterEnter(ctrlID, callbackContext);
            return true;
        } else if (action.equals("destroy") && args.length() >= 1) {
            int ctrlID = args.getInt(0);
            this.destroy(ctrlID, callbackContext);
            return true;
        } else if (action.equals("resize") && args.length() >= 5) {
            int x = args.getInt(1);
            int y = args.getInt(2);
            int width = args.getInt(3);
            int height = args.getInt(4);
            int ctrlID = args.getInt(0);
            this.resize(x, y, width, height, ctrlID, callbackContext);
            return true;
        } else if (action.equals("synchronize")) {
            ArrayList<String> list = new ArrayList<String>();

            if (args.length() > 0) {
                JSONArray a = args.getJSONArray(0);
                for (int i = 0; i < a.length(); i++) {
                    list.add(a.getString(i));
                }
            }

            this.synchronize(list, callbackContext);
            return true;
        } else if (action.equals("enableTouch")) {
            this.enableTouch();
            return true;
        } else if (action.equals("disableTouch")) {
            this.disableTouch();
            return true;
        } else if (action.equals("setNotificationsSupport") && args.length() >= 1) {
            this.setNotificationsSupport(args.getString(0));
            return true;
        } else if (action.equals("installEventHandler")) {
            this.installEventHandler(callbackContext);
            return true;
        } else if (action.equals("presentNotificationsList")) {
            this.presentNotificationsList(callbackContext);
            return true;
        } else if (action.equals("openURLInInternalBrowser") && args.length() >= 1) {
            this.openURLInInternalBrowser(args.getString(0), callbackContext);
            return true;
        }
        return false;
    }

    private void installEventHandler(CallbackContext callback) {
        this.eventHandler = callback;
    }

    private void setNotificationsSupport(String googleProjectKey) {
        VDARSDKController.getInstance().setNotificationsSupport(googleProjectKey != null, googleProjectKey);
    }

    private void enableTouch() {
        if (touchView != null) {
            touchView.setTouchEnabled(true);
        }
    }

    private void disableTouch() {
        if (touchView != null) {
            touchView.setTouchEnabled(false);
        }
    }

    private boolean isWebViewDestroyed() {

        if (webView == null) {
            return true;
        }

        final String url = webView.getUrl();
        if (url == null || url.equals("about:blank")) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Called when the system is about to start resuming a previous activity.
     *
     * @param multitasking      Flag indicating if multitasking is turned on for app
     */
    public void onPause(boolean multitasking) {
        for (Map.Entry<Integer, VDARAnnotationView> s : arViews.entrySet()) {
            VDARAnnotationView view = s.getValue();

            if (view.getParent() != null && view.getVisibility() == View.VISIBLE) {
                view.onPause();
            }
        }

        VDARSDKController.getInstance().getLocalizationManager().stopLocalization();
    }

    public void onDestroy() {
        for (Map.Entry<Integer, VDARAnnotationView> s : arViews.entrySet()) {
            VDARAnnotationView view = s.getValue();

            touchView.removeView(view);
        }

        arViews.clear();

        this.eventHandler = null;
    }

    /**
     * Called when the activity will start interacting with the user.
     *
     * @param multitasking      Flag indicating if multitasking is turned on for app
     */
    public void onResume(boolean multitasking) {
        for (Map.Entry<Integer, VDARAnnotationView> s : arViews.entrySet()) {
            VDARAnnotationView view = s.getValue();

            if (view.getParent() != null && view.getVisibility() == View.VISIBLE) {
                view.onResume();
            }
        }

        VDARSDKController.getInstance().getLocalizationManager().startLocalization();
    }

    private void presentNotificationsList(final CallbackContext callbackContext) {

        if (0 == VDARSDKController.getInstance().getPendingNotifications().size()) {
            callbackContext.error("empty");
        } else {
            callbackContext.success();
            VDARSDKController.getInstance().presentNotificationsList();
        }
    }

    private void openURLInInternalBrowser(String url, final CallbackContext callbackContext) {
        try {
            URL urlObj = new URL(url);

            VDARSDKController.getInstance().openURLInInternalBrowser(urlObj);
        } catch (MalformedURLException e) {

        }
    }

    private void synchronize(ArrayList<String> tags, final CallbackContext callbackContext) {
        final ArrayList<VDARPrior> priors = new ArrayList<VDARPrior>();

        for (String s : tags) {
            priors.add(new VDARTagPrior(s));
        }

        VDARSDKController.getInstance().addNewAfterLoadingTask(new Runnable() {
            @Override
            public void run() {
                VDARRemoteController.getInstance().syncRemoteContextsAsynchronouslyWithPriors(priors,
                        new Observer() {
                            @Override
                            public void update(Observable observable, Object data) {
                                VDARRemoteController.ObserverUpdateInfo info = (VDARRemoteController.ObserverUpdateInfo) data;

                                if (info.isCompleted()) {
                                    if (info.getError() == null) {
                                        JSONArray ctx = new JSONArray(info.getFetchedContexts());
                                        if (!isWebViewDestroyed()) {
                                            callbackContext.success(ctx);
                                        }
                                    } else {
                                        if (!isWebViewDestroyed()) {
                                            callbackContext.error(info.getError());
                                        }
                                    }
                                }
                            }
                        });
            }
        });
    }

    private void beforeLeave(final int ctrlID, CallbackContext callbackContext) {
        cordova.getActivity().runOnUiThread(new Runnable() {
            public void run() {
                VDARAnnotationView view = arViews.get(ctrlID);

                if (view != null) {
                    view.onPause();
                    view.setVisibility(View.GONE);
                }
            }
        });
    }

    private void afterLeave(final int ctrlID, CallbackContext callbackContext) {

    }

    private void beforeEnter(final int ctrlID, CallbackContext callbackContext) {
        cordova.getActivity().runOnUiThread(new Runnable() {
            public void run() {
                VDARAnnotationView view = arViews.get(ctrlID);

                if (view != null) {

                    view.onResume();

                    view.setVisibility(View.VISIBLE);
                }
            }
        });
    }

    private void afterEnter(final int ctrlID, CallbackContext callbackContext) {

    }

    private void resize(final int x, final int y, final int width, final int height, final int ctrlID,
            CallbackContext callbackContext) {
        cordova.getActivity().runOnUiThread(new Runnable() {
            public void run() {
                VDARAnnotationView annotationView = arViews.get(ctrlID);

                if (annotationView != null) {
                    DisplayMetrics displaymetrics = new DisplayMetrics();

                    cordova.getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);

                    annotationView.setVisibility(View.VISIBLE);
                    FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) annotationView.getLayoutParams();
                    params.leftMargin = (int) Math.round(x * displaymetrics.scaledDensity);
                    params.topMargin = (int) Math.round(y * displaymetrics.scaledDensity);
                    params.width = (int) Math.round(width * displaymetrics.scaledDensity);
                    params.height = (int) Math.round(height * displaymetrics.scaledDensity);

                    annotationView.setLayoutParams(params);

                    annotationView.requestLayout();
                }
            }
        });

    }

    private void destroy(final int ctrlID, CallbackContext callbackContext) {
        cordova.getActivity().runOnUiThread(new Runnable() {
            public void run() {
                VDARAnnotationView view = arViews.get(ctrlID);
                if (view != null) {

                    view.onPause();

                    if (view.getParent() != null) {
                        touchView.removeView(view);
                    }

                    arViews.remove(ctrlID);
                }
            }
        });
    }

    private void createARView(final int x, final int y, final int width, final int height, final int ctrlID,
            final boolean insertBelow, final CallbackContext callbackContext) {
        cordova.getActivity().runOnUiThread(new Runnable() {
            public void run() {

                if (imageSender == null) {
                    try {
                        imageSender = new DeviceCameraImageSender();
                    } catch (IOException e) {
                        VDARSDKController.log(Log.ERROR, TAG, Log.getStackTraceString(e));
                    }

                    VDARSDKController.getInstance().setImageSender(imageSender);
                }

                VDARAnnotationView annotationView = new VDARAnnotationView(cordova.getActivity());

                DisplayMetrics displaymetrics = new DisplayMetrics();

                cordova.getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);

                annotationView.setVisibility(View.VISIBLE);

                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
                        (int) Math.round(width * displaymetrics.scaledDensity),
                        (int) Math.round(height * displaymetrics.scaledDensity));
                params.leftMargin = (int) Math.round(x * displaymetrics.scaledDensity);
                params.topMargin = (int) Math.round(y * displaymetrics.scaledDensity);

                annotationView.setLayoutParams(params);

                touchView.addView(annotationView, 0);

                arViews.put(ctrlID, annotationView);

                VDARSDKController.getInstance().setActivity(cordova.getActivity());

                annotationView.onResume();

            }
        });
    }

    private String getCodeTypeAsString(VDARCodeType c) {
        switch (c) {
        default:
        case VDAR_CODE_TYPE_NONE:
            return "none";
        case VDAR_CODE_TYPE_EAN2:
            return "ean2";
        case VDAR_CODE_TYPE_EAN5:
            return "ean5";
        case VDAR_CODE_TYPE_EAN8:
            return "ean8";
        case VDAR_CODE_TYPE_UPCE:
            return "upce";
        case VDAR_CODE_TYPE_ISBN10:
            return "isbn10";
        case VDAR_CODE_TYPE_UPCA:
            return "upca";
        case VDAR_CODE_TYPE_EAN13:
            return "ean13";
        case VDAR_CODE_TYPE_ISBN13:
            return "isbn13";
        case VDAR_CODE_TYPE_COMPOSITE:
            return "composite";
        case VDAR_CODE_TYPE_I25:
            return "i25";
        case VDAR_CODE_TYPE_CODE39:
            return "code39";
        case VDAR_CODE_TYPE_QRCODE:
            return "qrcode";
        }
    }

    public void onCodesRecognized(java.util.ArrayList<com.vidinoti.android.vdarsdk.VDARCode> arrayList) {
        if (this.eventHandler != null) {
            for (VDARCode code : arrayList) {
                if (!code.isSpecialCode()) {
                    JSONObject o = new JSONObject();

                    try {
                        o.put("type", "codeRecognize");
                        o.put("codeType", getCodeTypeAsString(code.getCodeType()));
                        o.put("code", code.getCodeData());
                    } catch (JSONException e) {

                    }

                    PluginResult p = new PluginResult(PluginResult.Status.OK, o);
                    p.setKeepCallback(true);
                    this.eventHandler.sendPluginResult(p);
                }
            }
        }
    }

    public void onFatalError(java.lang.String s) {

    }

    public void onPresentAnnotations() {
        if (this.eventHandler != null) {
            JSONObject o = new JSONObject();

            try {
                o.put("type", "presentAnnotations");
            } catch (JSONException e) {

            }

            PluginResult p = new PluginResult(PluginResult.Status.OK, o);
            p.setKeepCallback(true);
            this.eventHandler.sendPluginResult(p);
        }
    }

    public void onAnnotationsHidden() {
        if (this.eventHandler != null) {
            JSONObject o = new JSONObject();

            try {
                o.put("type", "hideAnnotations");
            } catch (JSONException e) {

            }

            PluginResult p = new PluginResult(PluginResult.Status.OK, o);
            p.setKeepCallback(true);
            this.eventHandler.sendPluginResult(p);
        }
    }

    public void onTrackingStarted(int w, int h) {

    }

    public void onEnterContext(com.vidinoti.android.vdarsdk.VDARContext vdarContext) {
        if (this.eventHandler != null) {
            JSONObject o = new JSONObject();

            try {
                o.put("type", "enterContext");
                o.put("context", vdarContext.getRemoteID());
            } catch (JSONException e) {

            }

            PluginResult p = new PluginResult(PluginResult.Status.OK, o);
            p.setKeepCallback(true);
            this.eventHandler.sendPluginResult(p);
        }
    }

    public void onExitContext(com.vidinoti.android.vdarsdk.VDARContext vdarContext) {
        if (this.eventHandler != null) {
            JSONObject o = new JSONObject();

            try {
                o.put("type", "exitContext");
                o.put("context", vdarContext.getRemoteID());
            } catch (JSONException e) {

            }

            PluginResult p = new PluginResult(PluginResult.Status.OK, o);
            p.setKeepCallback(true);
            this.eventHandler.sendPluginResult(p);
        }
    }

    public void onRequireSynchronization(ArrayList<com.vidinoti.android.vdarsdk.VDARPrior> priors) {
        if (this.eventHandler != null) {
            JSONObject o = new JSONObject();

            try {
                JSONArray arr = new JSONArray();

                for (VDARPrior p : priors) {
                    if (p instanceof VDARTagPrior) {
                        arr.put(((VDARTagPrior) p).getTag());
                    }
                }

                o.put("type", "requireSync");
                o.put("tags", arr);
            } catch (JSONException e) {

            }

            PluginResult p = new PluginResult(PluginResult.Status.OK, o);
            p.setKeepCallback(true);
            this.eventHandler.sendPluginResult(p);
        }
    }
}