org.smartrobot.android.web.RobotWebView.java Source code

Java tutorial

Introduction

Here is the source code for org.smartrobot.android.web.RobotWebView.java

Source

/*
 * Copyright (C) 2011 SmartRobot.ORG
 *
 * 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 org.smartrobot.android.web;

import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONArray;
import org.roboid.robot.Robot;
import org.smartrobot.android.AbstractRobot;
import org.smartrobot.android.SmartRobot;
import org.smartrobot.android.action.AbstractAction;
import org.smartrobot.android.action.Action;
import org.smartrobot.android.clip.ClipPlayer;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.webkit.WebView;
import android.webkit.WebViewClient;

/**
 * <p>           .
 * <p>    {@link #onActivated()}    {@link #onDeactivated()}       .
 * </p>
 * @author akaii@kw.ac.kr (Kwang-Hyun Park)
 * <p>
 * @see org.smartrobot.android.SmartRobot SmartRobot
 * @see org.smartrobot.android.SmartRobot.Callback SmartRobot.Callback
 */
public class RobotWebView extends WebView implements SmartRobot.Callback {
    final SmartRobotHandler mSmartRobotHandler = new SmartRobotHandler();
    final HashMap<String, Action> mActions = new HashMap<String, Action>();
    final ArrayList<String> mMessages = new ArrayList<String>();
    private WebThread mWebThread;
    private final Object mLock = new Object();
    Robot mRobot;
    boolean mInitialized;
    boolean mActivated;
    boolean mPageLoaded;

    public RobotWebView(Context context) {
        super(context);
        init();
    }

    public RobotWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RobotWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        getSettings().setJavaScriptEnabled(true);
        addJavascriptInterface(mSmartRobotHandler, "SmartRobotHandler");
        setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                mPageLoaded = false;
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                if (mInitialized)
                    initialize();
                if (mActivated)
                    loadUrl("javascript:onActivated()");
                mPageLoaded = true;
            }
        });
    }

    void startWebThread() {
        synchronized (mLock) {
            WebThread oldThread = mWebThread;
            mWebThread = null;
            if (oldThread != null)
                oldThread.cancel();
            WebThread newThread = new WebThread();
            newThread.start();
            mWebThread = newThread;
        }
    }

    void stopWebThread() {
        synchronized (mLock) {
            WebThread oldThread = mWebThread;
            mWebThread = null;
            if (oldThread != null)
                oldThread.cancel();
        }
    }

    void initialize() {
        Robot robot = mRobot;
        if (robot == null)
            return;
        StringBuilder sb = new StringBuilder("javascript:SmartRobot.initialized('");
        sb.append(robot.getId());
        sb.append("','");
        sb.append(robot.getName());
        sb.append("')");
        loadUrl(sb.toString());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onInitialized(Robot robot) {
        if (robot == null)
            return;
        mRobot = robot;
        if (mPageLoaded)
            initialize();
        mInitialized = true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onActivated() {
        if (mPageLoaded)
            loadUrl("javascript:onActivated()");
        startWebThread();
        mActivated = true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onDeactivated() {
        mActivated = false;
        stopWebThread();
        if (mPageLoaded)
            loadUrl("javascript:onDeactivated()");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onDisposed() {
        mInitialized = false;
        if (mPageLoaded)
            loadUrl("javascript:onDisposed()");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onExecute() {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onStateChanged(int state) {
        if (!mPageLoaded)
            return;
        StringBuilder sb = new StringBuilder("javascript:onStateChanged(");
        sb.append(state);
        sb.append(")");
        loadUrl(sb.toString());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onNameChanged(String name) {
        if (!mPageLoaded)
            return;
        StringBuilder sb = new StringBuilder("javascript:SmartRobot.nameChanged('");
        sb.append(name);
        sb.append("')");
        loadUrl(sb.toString());
    }

    class WebThread extends Thread {
        private volatile boolean mStopped = false;

        @Override
        public void run() {
            long time = System.currentTimeMillis();
            long currentTime;
            while (!mStopped && !isInterrupted()) {
                currentTime = System.currentTimeMillis();
                if (currentTime > time) {
                    loadUrl("javascript:SmartRobot.encode()");
                    if (mStopped)
                        break;

                    if (mRobot != null) {
                        StringBuilder sb = new StringBuilder("javascript:SmartRobot.decode(");
                        sb.append("{ \"simulacrum\" : [");
                        long timestamp = System.nanoTime();
                        ((AbstractRobot) mRobot).encodeJson(sb, timestamp);
                        synchronized (mActions) {
                            for (Action action : mActions.values())
                                ((AbstractAction) action).encodeJson(sb, timestamp);
                        }
                        synchronized (mMessages) {
                            for (String msg : mMessages)
                                sb.append(msg);
                            mMessages.clear();
                        }
                        sb.append("]})");
                        if (mStopped)
                            break;

                        loadUrl(sb.toString());
                    }
                    time += 20;
                }

                if (mStopped)
                    break;
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    break;
                }
            }
            mSmartRobotHandler.clear();
        }

        void cancel() {
            mStopped = true;
            interrupt();
        }
    }

    class SmartRobotHandler implements Action.OnStateChangedListener, Action.OnCompletedListener,
            Action.OnErrorListener, ClipPlayer.OnCompletedListener, ClipPlayer.OnErrorListener {
        private final SparseArray<ClipPlayer> mClipPlayers = new SparseArray<ClipPlayer>();

        public void decode(String json) {
            try {
                JSONArray jsonArray = new JSONArray(json);

                JSONArray ja;
                int type, command;
                String actionId = null;
                int clipPlayerId = 0;
                int sz = jsonArray.length();
                for (int i = 0; i < sz; ++i) {
                    try {
                        ja = jsonArray.getJSONArray(i);
                        type = ja.getInt(0);
                        switch (type) {
                        case 0: {
                            ((AbstractRobot) mRobot).decodeJson(ja);
                        }
                            break;
                        case 2: {
                            Action action = null;
                            synchronized (mActions) {
                                action = mActions.get(ja.getString(1));
                            }
                            if (action != null)
                                ((AbstractAction) action).decodeJson(ja);
                        }
                            break;
                        case 4: {
                            command = ja.getInt(1);
                            if (command != 4)
                                actionId = ja.getString(2);
                            switch (command) {
                            case 0:
                                obtainAction(actionId);
                                break;
                            case 1:
                                disposeAction(actionId);
                                break;
                            case 2:
                                activateAction(actionId);
                                break;
                            case 3:
                                deactivateAction(actionId);
                                break;
                            case 4:
                                disposeAllActions();
                                break;
                            }
                        }
                            break;
                        case 5: {
                            command = ja.getInt(1);
                            if (command != 6)
                                clipPlayerId = ja.getInt(2);
                            switch (command) {
                            case 0:
                                obtainClipPlayer(clipPlayerId);
                                break;
                            case 1:
                                openUrl(clipPlayerId, ja.getString(3));
                                break;
                            case 2:
                                openResource(clipPlayerId, ja.getString(3), ja.getString(4));
                                break;
                            case 3:
                                closeClipPlayer(clipPlayerId);
                                break;
                            case 4:
                                playClipPlayer(clipPlayerId);
                                break;
                            case 5:
                                stopClipPlayer(clipPlayerId);
                                break;
                            case 6:
                                closeAllClipPlayers();
                                break;
                            }
                        }
                            break;
                        }
                    } catch (Exception e) {
                    }
                }
            } catch (Exception e) {
            }
        }

        boolean obtainAction(String actionId) {
            if (actionId == null)
                return false;
            Action action = null;
            synchronized (mActions) {
                action = mActions.get(actionId);
                if (action != null)
                    return true;

                action = Action.obtain(getContext(), actionId);
                if (action == null)
                    return false;
                mActions.put(actionId, action);
            }
            action.setOnStateChangedListener(this);
            action.setOnCompletedListener(this);
            action.setOnErrorListener(this);
            return true;
        }

        void disposeAllActions() {
            synchronized (mActions) {
                for (Action action : mActions.values()) {
                    action.clearDeviceDataChangedListener();
                }
                mActions.clear();
            }
            Action.disposeAll();
        }

        void disposeAction(String actionId) {
            if (actionId == null)
                return;
            Action action = null;
            synchronized (mActions) {
                action = mActions.get(actionId);
                if (action == null)
                    return;
                mActions.remove(actionId);
            }
            action.clearDeviceDataChangedListener();
            action.dispose();
        }

        boolean activateAction(String actionId) {
            if (actionId == null)
                return false;
            Action action = null;
            synchronized (mActions) {
                action = mActions.get(actionId);
            }
            if (action == null)
                return false;
            return action.activate();
        }

        boolean deactivateAction(String actionId) {
            if (actionId == null)
                return false;
            Action action = null;
            synchronized (mActions) {
                action = mActions.get(actionId);
            }
            if (action == null)
                return false;
            return action.deactivate();
        }

        boolean obtainClipPlayer(int clipPlayerId) {
            ClipPlayer clipPlayer = mClipPlayers.get(clipPlayerId);
            if (clipPlayer != null)
                return true;

            clipPlayer = ClipPlayer.obtain(getContext(), clipPlayerId);
            if (clipPlayer == null)
                return false;
            mClipPlayers.put(clipPlayerId, clipPlayer);
            clipPlayer.setOnCompletedListener(this);
            clipPlayer.setOnErrorListener(this);
            return true;
        }

        boolean openUrl(int clipPlayerId, String url) {
            ClipPlayer clipPlayer = mClipPlayers.get(clipPlayerId);
            if (clipPlayer == null)
                return false;
            return clipPlayer.open(url);
        }

        boolean openResource(int clipPlayerId, String packageName, String resName) {
            ClipPlayer clipPlayer = mClipPlayers.get(clipPlayerId);
            if (clipPlayer == null)
                return false;
            return clipPlayer.open(packageName, resName);
        }

        void closeAllClipPlayers() {
            ClipPlayer.closeAll();
        }

        void closeClipPlayer(int clipPlayerId) {
            ClipPlayer clipPlayer = mClipPlayers.get(clipPlayerId);
            if (clipPlayer == null)
                return;
            clipPlayer.close();
        }

        boolean playClipPlayer(int clipPlayerId) {
            ClipPlayer clipPlayer = mClipPlayers.get(clipPlayerId);
            if (clipPlayer == null)
                return false;
            return clipPlayer.play();
        }

        boolean stopClipPlayer(int clipPlayerId) {
            ClipPlayer clipPlayer = mClipPlayers.get(clipPlayerId);
            if (clipPlayer == null)
                return false;
            return clipPlayer.stop();
        }

        void clear() {
            disposeAllActions();
            closeAllClipPlayers();
            mClipPlayers.clear();
        }

        @Override
        public void onStateChanged(Action action, int state) {
            StringBuilder sb = new StringBuilder(",[4,1,'");
            sb.append(action.getId());
            sb.append("',");
            sb.append(state);
            sb.append("]");
            synchronized (mMessages) {
                mMessages.add(sb.toString());
            }
        }

        @Override
        public void onCompleted(Action action) {
            StringBuilder sb = new StringBuilder(",[4,2,'");
            sb.append(action.getId());
            sb.append("']");
            synchronized (mMessages) {
                mMessages.add(sb.toString());
            }
        }

        @Override
        public void onError(Action action, int errorCode) {
            StringBuilder sb = new StringBuilder(",[4,3,'");
            sb.append(action.getId());
            sb.append("',");
            sb.append(errorCode);
            sb.append("]");
            synchronized (mMessages) {
                mMessages.add(sb.toString());
            }
        }

        @Override
        public void onCompleted(ClipPlayer clipPlayer) {
            StringBuilder sb = new StringBuilder(",[5,1,");
            sb.append(clipPlayer.getId());
            sb.append("]");
            synchronized (mMessages) {
                mMessages.add(sb.toString());
            }
        }

        @Override
        public void onError(ClipPlayer clipPlayer, int errorCode) {
            StringBuilder sb = new StringBuilder(",[5,2,");
            sb.append(clipPlayer.getId());
            sb.append(",");
            sb.append(errorCode);
            sb.append("]");
            synchronized (mMessages) {
                mMessages.add(sb.toString());
            }
        }
    }
}