org.kaaproject.kaa.examples.robotrun.android.RobotRunFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.kaaproject.kaa.examples.robotrun.android.RobotRunFragment.java

Source

/*
 * Copyright 2014 CyberVision, Inc.
 *
 * 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.kaaproject.kaa.examples.robotrun.android;

import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;

import org.kaaproject.kaa.examples.robotrun.controller.Launcher;
import org.kaaproject.kaa.examples.robotrun.controller.Launcher.LauncherCallback;
import org.kaaproject.kaa.examples.robotrun.emulator.RobotEmulator;
import org.kaaproject.kaa.examples.robotrun.labyrinth.Cell;
import org.kaaproject.kaa.examples.robotrun.labyrinth.Direction;
import org.kaaproject.kaa.examples.robotrun.labyrinth.Labyrinth;
import org.kaaproject.kaa.examples.robotrun.labyrinth.impl.BasicLabyrinth;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;

public class RobotRunFragment extends Fragment implements TextWatcher, LauncherCallback {

    private static final Logger LOG = LoggerFactory.getLogger(RobotRunFragment.class);

    private RobotRunActivity mActivity;

    private EditText xInput;
    private EditText yInput;
    private Spinner directionInput;
    private Button startButton;
    private Button startEmulatorButton;
    private Button stopButton;

    private View statusView;
    private TextView statusText;
    private TextView connectedToText;

    private Launcher launcher;

    private RobotType robotType = null;

    private String connectedEntityName;

    public static RobotRunFragment newInstance() {
        RobotRunFragment fragment = new RobotRunFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity = (RobotRunActivity) this.getActivity();
    }

    @Override
    public void onDestroy() {
        mActivity = null;
        super.onDestroy();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.robotrun_fragment, container, false);
        xInput = (EditText) view.findViewById(R.id.x_input);
        xInput.setFilters(new InputFilterMinMax[] { new InputFilterMinMax(0, 12) });
        yInput = (EditText) view.findViewById(R.id.y_input);
        yInput.setFilters(new InputFilterMinMax[] { new InputFilterMinMax(0, 12) });
        directionInput = (Spinner) view.findViewById(R.id.direction_input);

        CharSequence[] directionEntries = new CharSequence[Direction.values().length];
        for (int i = 0; i < Direction.values().length; i++) {
            directionEntries[i] = Direction.values()[i].name();
        }
        ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getActivity(),
                android.R.layout.simple_spinner_item, directionEntries);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        directionInput.setAdapter(adapter);

        startButton = (Button) view.findViewById(R.id.start_button);
        startEmulatorButton = (Button) view.findViewById(R.id.start_emulator_button);
        stopButton = (Button) view.findViewById(R.id.stop_button);

        statusView = (View) view.findViewById(R.id.status);
        statusText = (TextView) view.findViewById(R.id.status_text);
        connectedToText = (TextView) view.findViewById(R.id.connected_to_text);

        startButton.setEnabled(false);
        startEmulatorButton.setEnabled(false);
        stopButton.setEnabled(false);

        xInput.addTextChangedListener(this);
        yInput.addTextChangedListener(this);

        xInput.setText("0");
        yInput.setText("0");

        startButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                start();
            }
        });

        startEmulatorButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                startEmulator();
            }
        });

        stopButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                stop();
            }
        });

        return view;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        checkValues();
    }

    @Override
    public void afterTextChanged(Editable s) {
    }

    private void checkValues() {
        CharSequence xText = xInput.getText();
        CharSequence yText = yInput.getText();
        if (!isEmpty(xText) && !isEmpty(yText)) {
            startButton.setEnabled(true);
            startEmulatorButton.setEnabled(true);
        } else {
            startButton.setEnabled(false);
            startEmulatorButton.setEnabled(false);
        }
    }

    private static boolean isEmpty(CharSequence chs) {
        return chs == null || chs.length() == 0;
    }

    private int getStartX() {
        CharSequence xText = xInput.getText();
        return Integer.valueOf(xText.toString());
    }

    private int getStartY() {
        CharSequence yText = yInput.getText();
        return Integer.valueOf(yText.toString());
    }

    private Direction getStartDirection() {
        CharSequence dirString = (CharSequence) directionInput.getSelectedItem();
        return Direction.valueOf(dirString.toString());
    }

    private void disableInput() {
        xInput.setEnabled(false);
        yInput.setEnabled(false);
        directionInput.setEnabled(false);
        startButton.setEnabled(false);
        startEmulatorButton.setEnabled(false);
        stopButton.setEnabled(true);
    }

    private void enableInput() {
        xInput.setEnabled(true);
        yInput.setEnabled(true);
        directionInput.setEnabled(true);
        startButton.setEnabled(true);
        startEmulatorButton.setEnabled(true);
        stopButton.setEnabled(false);
    }

    private void start() {
        updateStatus(RobotRunStatus.SETTING_UP);
        int startX = getStartX();
        int startY = getStartY();
        Direction startDirection = getStartDirection();
        try {
            launcher = new AndroidBtLauncher(this, getActivity(), startX, startY, startDirection, "Unknown bot");
        } catch (Exception e) {
            LOG.error("Failed to create android bt launcher!", e);
            showError("Failed to create android bt launcher!\n" + e.getMessage());
            stop();
        }
        if (launcher != null) {
            robotType = RobotType.BOT;
            startLauncher();
        }
    }

    private void startEmulator() {
        updateStatus(RobotRunStatus.SETTING_UP);
        File labyrinthFile = new File(Environment.getExternalStorageDirectory(), "labyrinth.data");
        Labyrinth labyrinth = tryReadEmulatorLabyrinth(labyrinthFile);
        if (labyrinth == null) {
            showError("Unable to load labyrinth from file:\n" + labyrinthFile.getAbsolutePath());
            stop();
        } else {
            int startX = getStartX();
            int startY = getStartY();
            Direction startDirection = getStartDirection();
            Cell startCell = labyrinth.getCell(startX, startY);
            Properties robotProperties = new Properties();
            robotProperties.put(RobotEmulator.PROPERTY_NAME_COMMAND_TIMEOUT,
                    "" + RobotEmulator.DEFAULT_COMMAND_TIMEOUT / 5);
            robotProperties.put(RobotEmulator.PROPERTY_NAME_COMMAND_TIMEOUT_DEVIATION,
                    "" + RobotEmulator.DEFAULT_COMMAND_TIMEOUT_DEVIATION / 5);
            robotProperties.put(RobotEmulator.PROPERTY_NAME_PING_TIMEOUT,
                    "" + RobotEmulator.DEFAULT_PING_TIMEOUT / 5);
            try {
                launcher = new AndroidEmulatorLauncher(this, getActivity(), labyrinth, startCell, startDirection,
                        "android emulated bot", robotProperties);
            } catch (Exception e) {
                LOG.error("Failed to create emulator launcher!", e);
                showError("Failed to create emulator launcher!\n" + e.getMessage());
                stop();
            }
            if (launcher != null) {
                robotType = RobotType.EMULATOR;
                startLauncher();
            }
        }
    }

    private void startLauncher() {
        try {
            launcher.start();
        } catch (RuntimeException e) {
            LOG.error("Failed to start launcher!", e);
            showError("Failed to start launcher!\n" + e.getMessage());
            stop();
        }
    }

    private void stop() {
        if (launcher != null) {
            launcher.stop();
            launcher = null;
        } else {
            updateStatus(RobotRunStatus.SETUP);
        }
    }

    @Override
    public void onLauncherStarted(String entityName) {
        connectedEntityName = entityName;
        updateStatus(RobotRunStatus.READY);
    }

    @Override
    public void onLauncherStartRun() {
        updateStatus(RobotRunStatus.STARTED);
    }

    @Override
    public void onLauncherStopped() {
        updateStatus(RobotRunStatus.SETUP);
    }

    @Override
    public void onLauncherError(final Exception e) {
        if (launcher != null) {
            LOG.error("Launcher error!", e);
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    showError("Launcher error!\n" + e.getMessage());
                    stop();
                }
            });
        }
    }

    private void updateStatus(final RobotRunStatus status) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                statusView.setBackgroundResource(status.backgroundResId);
                statusText.setText(getResources().getText(status.textResId));
                Animation fadeAnimation;
                switch (status) {
                case SETUP:
                    enableInput();
                    connectedToText.setVisibility(View.GONE);
                    statusView.clearAnimation();
                    break;
                case SETTING_UP:
                    disableInput();
                    fadeAnimation = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_infinite);
                    statusView.startAnimation(fadeAnimation);
                    break;
                case READY:
                    statusView.clearAnimation();
                    connectedToText.setVisibility(View.VISIBLE);
                    connectedToText.setText(String.format(getResources().getString(R.string.connected_to_message),
                            getResources().getString(robotType.textResId), connectedEntityName));
                    break;
                case STARTED:
                    fadeAnimation = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_infinite);
                    statusView.startAnimation(fadeAnimation);
                    break;
                default:
                    break;
                }
            }

        });
    }

    private Labyrinth tryReadEmulatorLabyrinth(File labyrinthFile) {
        Labyrinth labyrinth = null;
        if (labyrinthFile.exists()) {
            try {
                FileInputStream fis = new FileInputStream(labyrinthFile);
                labyrinth = BasicLabyrinth.load(fis);
            } catch (Exception e) {
                LOG.error("Unable to load labyrinth from file [{}]!", labyrinthFile);
            }
        }
        return labyrinth;
    }

    private void showError(String message) {
        AlertDialog dialog = new AlertDialog.Builder(getActivity()).setMessage(message).setTitle("Error")
                .setNeutralButton("Close", new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int which) {
                        dialog.dismiss();
                    }
                }).create();
        dialog.show();
    }

}