com.kjsaw.alcosys.ibacapp.IBAC.java Source code

Java tutorial

Introduction

Here is the source code for com.kjsaw.alcosys.ibacapp.IBAC.java

Source

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * 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.kjsaw.alcosys.ibacapp;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.List;

import org.json.JSONException;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.ShutterCallback;
import android.hardware.Camera.Size;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.kjsaw.alcosys.ibacapp.BluetoothIBACService.MODE;
import com.kjsaw.alcosys.ibacapp.MessageUtils.ApplicationConstants;
import com.kjsaw.alcosys.ibacapp.MessageUtils.ExceptionHelper;
import com.kjsaw.alcosys.ibacapp.MessageUtils.IProcessorStateListener;
import com.kjsaw.alcosys.ibacapp.MessageUtils.MessageProcessorStates;
import com.kjsaw.alcosys.ibacapp.MessageUtils.Messages;
import com.kjsaw.alcosys.ibacapp.MessageUtils.StringHelper;
import com.kjsaw.alcosys.ibacapp.MessageUtils.SuccessRule;
import com.kjsaw.alcosys.ibacapp.MessageUtils.Actions.ShutdownAction;
import com.kjsaw.alcosys.ibacapp.exception.SmartphoneException;
import com.kjsaw.alcosys.ibacapp.model.SendResultRequest;
import com.kjsaw.alcosys.ibacapp.service.SendResultService;
import com.kjsaw.alcosys.ibacapp.service.ServiceFactory;
import com.kjsaw.alcosys.ibacapp.service.https.HttpsHmac;
import com.kjsaw.alcosys.ibacapp.ui.ContainerActivity;
import com.kjsaw.alcosys.ibacapp.utility.ActivityStackControlUtil;
import com.kjsaw.alcosys.ibacapp.utility.Logging;
import com.kjsaw.alcosys.ibacapp.utility.TimeFormatter;

/**
 * This is the main Activity that displays the current chat session.
 */
public class IBAC extends ContainerActivity implements IProcessorStateListener, Callback {

    // True if we are making changes to the phone configuration, this can call our lifetime events a bit randomly
    private boolean _isConfiguringPhone;
    private boolean _inDialog = false;

    private static final String TAG = "iBac App";

    // Message types sent from the BluetoothChatService Handler
    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_TOAST = 5;
    public static final int ADD_MESSAGE = 6;
    public static final int ADD_SUCCESS_MESSAGE = 7;
    public static final int CALIBRATING = 8;
    public static final int CALIBRATION_ABORTED = 9;
    public static final int CALIBRATION_ABORTED_NO_CONNECTION = 10;
    public static final int ADD_SENT_MESSAGE = 11;
    public static final int ADD_BOTTOM_MESSAGE = 12;
    public static final int SHUTDOWN = 13;
    public static final int MESSAGE_TAKE_PHOTO = 14;
    public static final int COMPLETE_SENT_MESSAGE = 15;
    public static final int CALIB_CHECKING = 16;

    // Key names received from the BluetoothChatService Handler
    public static final String DEVICE_NAME = "device_name";
    public static final String TOAST = "toast";

    // Intent request codes
    private static final int REQUEST_CONNECT_DEVICE = 1;
    private static final int REQUEST_ENABLE_BT = 2;
    // public static final int REQUEST_ENABLE_GPS = 3;

    // Layout Views
    private TextView _title;
    private TextView _textCountdown;
    private ListView _conversationView;
    private ListView _conversationViewBottom;

    // Name of the connected device
    private String _connectedDeviceName = null;
    // Array adapter for the conversation thread
    private ArrayAdapter<String> _conversationArrayAdapter;
    private ArrayAdapter<String> _conversationArrayAdapterBottom;
    private BluetoothAdapter _bluetoothAdapter = null;
    private BluetoothIBACService _iBACservice = null;

    private Runnable _btDiscovery;
    // private SendResultAsyncTask _sendResultAsyncTask;

    private DeviceLocation deviceLocation;

    // ------------For Protocol web------
    private String bluetoothMACAddress;
    // private String phoneNumber;
    // private float alcoResult;
    private double positionLatitude;
    private double positionLongitude;
    private float positionAccuracy;
    private Bitmap bitmapPhoto;
    // private String timestamp;

    // ------------For Camera----------
    private Handler countdownHandler = new Handler();
    private int coutdownCount = 2; // 2+1 delay = 3 seconds
    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;
    private Camera camera;
    private boolean isPreviewRunning;
    private static boolean isCameraRunOnce = false;
    private ImageView imageView;
    private int showImageTime = 10;// 10 seconds
    private long showImageStartTime;
    private long showImageEndTime;
    // -------------Dialog--------------
    // private AlertDialog dialogPhoneNumber;
    // private Button buttonPhoneNumber;
    // private EditText editTextPhoneNumber;
    // private SharedPreferences sharedPhoneNumber;

    private void setDebugLog(Message msg) {
        if (_iBACservice == null || _iBACservice._messageProcessor == null)
            return;
        StringBuilder sb = new StringBuilder();
        com.kjsaw.alcosys.ibacapp.MessageUtils.Message lastMessage = _iBACservice._messageProcessor
                .GetMessageSequence().GetLastMessage();
        if (lastMessage == null)
            sb.append("No Message from IBAC yet");
        else
            sb.append("Last received:: ").append(lastMessage.toString()).append(" ")
                    .append(lastMessage.GetDescription());
        logDebug.setText(sb.toString());
    }

    private TextView textViewAppVersion;
    /*
     * Handler responsible for messages that needs to be handled on the UI thread
     */
    private final Handler _handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

            setDebugLog(msg);
            switch (msg.what) {
            case SHUTDOWN:
                CancelAllServices();
                ActivityStackControlUtil.finishProgram(Session.isFullyExit);
                break;
            case CALIBRATION_ABORTED_NO_CONNECTION:
                _conversationArrayAdapter.clear();
                _conversationArrayAdapter.add(getResources().getString(R.string.calibration_notconnected));
                if (ApplicationConstants.DebugMode) {
                    Log.d(ApplicationConstants.ApplicationTag, "Printing: Not connected, calibration aborted.");
                }
                break;
            case CALIBRATING:
                _conversationArrayAdapter.clear();
                _conversationArrayAdapter.add("Calibrating ...");
                if (ApplicationConstants.DebugMode) {
                    Log.d(ApplicationConstants.ApplicationTag, getResources().getString(R.string.calibrating));
                }
                break;
            case CALIB_CHECKING:
                _conversationArrayAdapter.clear();
                _conversationArrayAdapter.add("Calibration Checking ...");
                if (ApplicationConstants.DebugMode) {
                    Log.d(ApplicationConstants.ApplicationTag, "Checking calibration");
                }
                break;
            case CALIBRATION_ABORTED:
                _conversationArrayAdapter.clear();
                _conversationArrayAdapter.add(getResources().getString(R.string.calibration_wrongPin));
                if (ApplicationConstants.DebugMode) {
                    Log.d(ApplicationConstants.ApplicationTag, "Wrong PIN, calibration aborted.");
                }
                break;
            case ADD_MESSAGE:
                _conversationArrayAdapterBottom.clear();
                _conversationArrayAdapter.clear();
                _conversationArrayAdapter.add((String) msg.obj);
                // Toast.makeText(IBAC.this, (String) msg.obj,
                // Toast.LENGTH_SHORT).show();
                if (ApplicationConstants.DebugMode) {
                    Log.d(ApplicationConstants.ApplicationTag, "Printing: " + (String) msg.obj);
                }
                break;
            case ADD_SUCCESS_MESSAGE:
                // Foks Comments
                // ImageView mAlcoLogo = (ImageView) findViewById(R.id.mti);
                // mAlcoLogo.setImageResource(R.drawable.alcogreenbg);
                _conversationArrayAdapter.clear();
                _conversationArrayAdapter.add((String) msg.obj);
                // Toast.makeText(IBAC.this, (String) msg.obj,
                // Toast.LENGTH_SHORT).show();
                if (ApplicationConstants.DebugMode) {
                    Log.d(ApplicationConstants.ApplicationTag, "Printing: " + (String) msg.obj);
                }
                break;
            case ADD_SENT_MESSAGE:
                _conversationArrayAdapter.clear();
                _conversationArrayAdapter.add((String) msg.obj);
                if (ApplicationConstants.DebugMode) {
                    Log.d(ApplicationConstants.ApplicationTag, "Printing: " + (String) msg.obj);
                }
                break;
            case COMPLETE_SENT_MESSAGE:
                _conversationView.setBackgroundColor(getResources().getColor(R.color.green));
                _conversationArrayAdapter.clear();
                _conversationArrayAdapter.add((String) msg.obj);
                if (ApplicationConstants.DebugMode) {
                    Log.d(ApplicationConstants.ApplicationTag, "Printing: " + (String) msg.obj);
                }
                break;
            case ADD_BOTTOM_MESSAGE:
                _conversationArrayAdapterBottom.clear();
                _conversationArrayAdapterBottom.add((String) msg.obj);
                if (ApplicationConstants.DebugMode) {
                    Log.d(ApplicationConstants.ApplicationTag, "Printing: " + (String) msg.obj);
                }
                break;
            case MESSAGE_STATE_CHANGE:
                if (ApplicationConstants.DebugMode)
                    Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                switch (msg.arg1) {
                case BluetoothIBACService.STATE_CONNECTED:
                    _conversationArrayAdapterBottom.clear();
                    _title.setText(
                            getResources().getString(R.string.title_connected_to) + " " + _connectedDeviceName);
                    // mConversationArrayAdapter.clear();
                    break;
                case BluetoothIBACService.STATE_CONNECTING:
                    _conversationArrayAdapterBottom.clear();
                    _conversationArrayAdapter.clear();
                    _conversationArrayAdapterBottom.add(getResources().getString(R.string.message_connecting));
                    _title.setText(R.string.title_connecting);
                    break;
                case BluetoothIBACService.STATE_LISTEN:
                case BluetoothIBACService.STATE_NONE:
                    _title.setText(R.string.title_not_connected);
                    break;
                }
                break;
            case MESSAGE_WRITE:
                byte[] writeBuf = (byte[]) msg.obj;
                String writeMessage = new String(writeBuf);
                _conversationArrayAdapter.add("Me:  " + writeMessage);
                break;
            case MESSAGE_DEVICE_NAME:
                // save the connected device's name
                _connectedDeviceName = msg.getData().getString(DEVICE_NAME);
                break;
            case MESSAGE_TOAST:
                _conversationArrayAdapterBottom.clear();
                _conversationArrayAdapter.clear();
                _conversationArrayAdapter.add(msg.getData().getString(TOAST));
                break;
            case MESSAGE_TAKE_PHOTO:
                _conversationArrayAdapter.clear();
                _conversationArrayAdapter.add((String) msg.obj);
                if (ApplicationConstants.DebugMode) {
                    Log.d(ApplicationConstants.ApplicationTag, "Printing: " + (String) msg.obj);
                }
                startCamera();
                isCameraRunOnce = true;
                break;
            }
        }
    };

    /*
     * Handles messages from the iBac message service
     */
    public void MessageReceived(com.kjsaw.alcosys.ibacapp.MessageUtils.Message message) {
        _handler.obtainMessage(IBAC.ADD_MESSAGE, message.GetDescription(getResources())).sendToTarget();
    }

    /*
     * Handles state changed messages from the iBac message service
     */
    public void StateChanged(MessageProcessorStates oldState, MessageProcessorStates newState) {
        switch (newState) {
        case NotConnected:
            // Add this line if we should try and reconnect if we are not
            // connected
            // _iBACservice.Reset();

            _handler.obtainMessage(IBAC.ADD_BOTTOM_MESSAGE, getResources().getString(R.string.channel_closed))
                    .sendToTarget();
            ShutdownAction action = new ShutdownAction(_handler, 5, Session.isFullyExit);
            action.Invoke(null);
            break;
        case Connected:
            _handler.obtainMessage(IBAC.ADD_MESSAGE, getResources().getString(R.string.please_wait)).sendToTarget();
            break;
        case WaitingForResponse:
            // _handler.obtainMessage(IBAC.ADD_MESSAGE,
            // "Please wait...").sendToTarget();
            break;
        case Ready:
            _handler.obtainMessage(IBAC.MESSAGE_TAKE_PHOTO, getResources().getString(R.string.blow_into_device))
                    .sendToTarget();
            // _handler.obtainMessage(IBAC.ADD_MESSAGE, "Ready").sendToTarget();
            break;
        case TestInProgress:
            //
            // countdownHandler.postDelayed(countdownRunnable, 0);
            break;
        case TestReceived:

            com.kjsaw.alcosys.ibacapp.MessageUtils.Message resultMessage = _iBACservice._messageProcessor
                    .GetMessageSequence().GetLastMessage();
            if (resultMessage == null) {
                _handler.obtainMessage(IBAC.ADD_MESSAGE, getResources().getString(R.string.result_bad))
                        .sendToTarget();

                ShutdownAction shutDownAction = new ShutdownAction(_handler, 5, true);
                shutDownAction.Invoke(null);
                return;
            }

            float value = calibrateResult(SuccessRule.ParseValue(resultMessage));
            // Foks Comments
            // float value = calibrateResult(0.07f);

            String asString = StringHelper.PadString("" + value, 5, '0', false);

            if (value >= 0) {
                // countdownHandler.postDelayed(countdownRunnable, 0);
                capturePhoto();
                _handler.obtainMessage(IBAC.ADD_SUCCESS_MESSAGE,
                        getResources().getString(R.string.result_measured_to) + " " + asString + " "
                                + getResources().getString(R.string.alco_level_acronym))
                        .sendToTarget();
                _iBACservice.endOperation();
                boolean isWait = true;
                while (isWait) {
                    showImageEndTime = System.currentTimeMillis();
                    if (bitmapPhoto != null && (Session.IBAC_VERSION != null && !Session.IBAC_VERSION.equals(""))
                            && (Session.PHONE_NUMBER != null && !Session.PHONE_NUMBER.equals(""))
                            && ((showImageTime - (showImageEndTime - showImageStartTime) / 1000) < 0)
                            && deviceLocation.isGPSStoped()) {
                        Log.i("SAM", "Waiting while registering result ...");
                        positionLatitude = deviceLocation.getLatitude();
                        positionLongitude = deviceLocation.getLongitude();
                        positionAccuracy = deviceLocation.getAccuracy();
                        isWait = false;
                    }
                }
                Log.i("SAM", "Sending result to server...");
                //boolean sendResult = sendResultToServer(value);
                boolean sendResult = true;

                if (sendResult) {
                    Resources resources = getResources();
                    StringBuffer stringBuffer = new StringBuffer();
                    stringBuffer.append(resources.getString(R.string.result_success_title));
                    stringBuffer.append("\n");
                    stringBuffer.append(resources.getString(R.string.result_success_value) + " " + value + " "
                            + resources.getString(R.string.result_success_unit));
                    stringBuffer.append("\n");
                    stringBuffer.append(resources.getString(R.string.result_success_time_format_start)
                            + Session.REQUEST_DATE + resources.getString(R.string.result_success_time_format_end));
                    stringBuffer.append("\n");
                    stringBuffer.append(resources.getString(R.string.result_success_sent));

                    _handler.obtainMessage(IBAC.ADD_SENT_MESSAGE, stringBuffer.toString()).sendToTarget();
                } else {
                    _handler.obtainMessage(IBAC.ADD_SENT_MESSAGE,
                            getResources().getString(R.string.result_com_failure)).sendToTarget();
                }

                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } else {
                // bad result
                _handler.obtainMessage(IBAC.ADD_MESSAGE, getResources().getString(R.string.result_bad))
                        .sendToTarget();
            }

            _iBACservice._messageProcessor.messageCompleted();
            // ShutdownAction shutDownForReceived = new ShutdownAction(_handler, 5, false);
            // shutDownForReceived.Invoke(null);

            break;
        case Completed:
            Resources resources = getResources();
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append(resources.getString(R.string.result_completed_content1));
            stringBuffer.append("\n");
            stringBuffer.append(resources.getString(R.string.result_completed_content2));
            stringBuffer.append("\n");
            stringBuffer.append(resources.getString(R.string.result_completed_content3));
            _handler.obtainMessage(IBAC.COMPLETE_SENT_MESSAGE, stringBuffer.toString()).sendToTarget();

            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            ShutdownAction shutDownForReceived = new ShutdownAction(_handler, 5, false);
            shutDownForReceived.Invoke(null);
            break;
        case Error:
            String errorMessage = _iBACservice._messageProcessor.GetLastUserMessage()
                    .GetDescription(getResources());
            if (errorMessage == null || errorMessage == "") {
                _handler.obtainMessage(IBAC.ADD_MESSAGE, getResources().getString(R.string.unknown_error))
                        .sendToTarget();
            } else {
                _handler.obtainMessage(IBAC.ADD_MESSAGE, errorMessage).sendToTarget();
            }
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;
        default:
            break;
        }
    }

    private float calibrateResult(float value) {
        if (value <= 0.07f) {
            return 0.0f;
        }
        return value;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initItems();
        ActivityStackControlUtil.add(this);
    }

    protected void initOthers() {
        MODE m;
        Bundle extras = getIntent().getExtras();
        if (extras != null)
            m = (MODE) extras.getSerializable("mode");
        else
            m = MODE.SAMPLING;
        CreateComponents(m);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_BACK:
            Session.isKeepRunning = false;
            CancelAllServices();
            ActivityStackControlUtil.finishProgram(true);
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public synchronized void onResume() {
        super.onResume();
        // InitializeAllServices();
    }

    @Override
    public synchronized void onPause() {
        super.onPause();
    }

    protected void onDestroy() {
        super.onDestroy();
        CancelAllServices();
        ActivityStackControlUtil.remove(this);
    }

    /*
     * Creates all the components that we use during the app lifetime
     */
    private void CreateComponents(MODE mode) {
        InitializeUI();

        Session.APP_VERSION = getAppVersion();
        Session.MOBILE_OS = getOSVersion();
        initBeepSound();
        initCaptureSound();

        deviceLocation = new DeviceLocation(this, mode);
        //startBackendService();
    }

    private void startBackendService() {
        Session.isKeepRunning = true;
        Intent intent = new Intent("com.kjsaw.alcosys.ibacapp.BackendHTTPService");
        this.startService(intent);
    }

    public void initBluetooth(MODE mode) {
        // Get local Bluetooth adapter
        //       if(BluetoothIBACService.isBLEsupported(IBAC.this)){
        //         final BluetoothManager bluetoothManager =(BluetoothManager) IBAC.this.getSystemService(Context.BLUETOOTH_SERVICE);
        //         _bluetoothAdapter = bluetoothManager.getAdapter();
        //      }
        //      else
        _bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // If the adapter is null, then Bluetooth is not supported then exit
        if (_bluetoothAdapter == null) {
            Toast.makeText(this, getResources().getString(R.string.bt_not_supported), Toast.LENGTH_LONG).show();
            finish();
            android.os.Process.killProcess(android.os.Process.myPid());
            return;
        }

        _iBACservice = new BluetoothIBACService(this, _handler, mode);

        InitializeAllServices();
    }

    TextView logDebug;

    /*
     * Sets up the main UI for the app
     */
    private void InitializeUI() {
        // Set up the window layout
        //requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        setContentView(R.layout.main);
        //getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);

        // Set up ui
        TextView mHeader = (TextView) findViewById(R.id.mth);
        mHeader.setText(R.string.header);

        logDebug = (TextView) findViewById(R.id.debug_ascii);

        TextView mFooter = (TextView) findViewById(R.id.mtf);
        mFooter.setText(R.string.footer);

        _conversationArrayAdapterBottom = new ArrayAdapter<String>(this, R.layout.message);

        // Initialize the array adapter for the conversation thread
        _conversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
        _conversationView = (ListView) findViewById(R.id.in);
        //
        _conversationView.setAdapter(_conversationArrayAdapter);
        _conversationArrayAdapter.clear();

        _conversationViewBottom = (ListView) findViewById(R.id.in2);

        _conversationViewBottom.setAdapter(_conversationArrayAdapterBottom);
        _conversationArrayAdapterBottom.clear();
        _title = (TextView) findViewById(R.id.title_left_text);
        _title = (TextView) findViewById(R.id.title_right_text);
        _textCountdown = (TextView) findViewById(R.id.text_countdown);

        textViewAppVersion = (TextView) findViewById(R.id.text_app_version);
        showAppVersion();

        initialCamera();
    }

    /*
     * Initializes all our dependent components to their initial states
     */
    private void InitializeAllServices() {

        if (_isConfiguringPhone) {
            return;
        }

        if (!_bluetoothAdapter.isEnabled()) {
            // bluetooth is not enabled so wait until its enabled...then call this method again
            _isConfiguringPhone = true;
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        } else {
            _iBACservice._messageProcessor.RegisterStateListener(this);

            if (_iBACservice.getState() == 0 && _bluetoothAdapter.isEnabled()) {
                final Intent serverIntent = new Intent(this, BluetoothIBACDiscovery.class); //BluetoothIBACDiscoveryLTE
                _btDiscovery = new Runnable() {
                    public void run() {
                        startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
                    }
                };

                _handler.postDelayed(_btDiscovery, 1500); // 3000

                // change to the blue logo
                ImageView mAlcoLogo = (ImageView) findViewById(R.id.mti);
                mAlcoLogo.setImageResource(R.drawable.alcogreenbg);
                _conversationArrayAdapter.clear();
                _conversationArrayAdapterBottom.clear();
                _conversationArrayAdapter.add(getResources().getString(R.string.turn_on_ibac));
            }

            // Take an extra look on this
            if (_iBACservice != null) {
                if (_iBACservice.getState() == BluetoothIBACService.STATE_NONE) {
                    _iBACservice.start();
                }
            }
        }
    }

    // Cancels all our dependent components
    private void CancelAllServices() {

        if (_inDialog) {
            return;
        }

        if (_iBACservice != null)
            _iBACservice.shutDown();
        // if (_iBACservice != null) {
        // _iBACservice.ResetAndQuit();
        // }
        isCameraRunOnce = false;

        if (_iBACservice._messageProcessor != null) {
            _iBACservice._messageProcessor.UnRegisterStateListener(this);
        }

        if (_bluetoothAdapter != null && _bluetoothAdapter.isDiscovering()) {
            _bluetoothAdapter.cancelDiscovery();
        }

        if (_handler != null) {
            _handler.removeCallbacks(_btDiscovery);
        }

        if (deviceLocation != null) {
            deviceLocation.cancelGPSService();
            deviceLocation.turnOffGPS();
        }
    }

    /*
     * Called when a message is sent from an external component
     */
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        _inDialog = false;
        switch (requestCode) {
        case REQUEST_CONNECT_DEVICE:
            // When DeviceListActivity returns with a device to connect
            _conversationArrayAdapter.clear();
            if (resultCode == Activity.RESULT_OK) {

                // Get the device MAC address
                bluetoothMACAddress = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);

                // Get the BLuetoothDevice object
                BluetoothDevice device = _bluetoothAdapter.getRemoteDevice(bluetoothMACAddress);
                unpairDevice(device);
                pairDevice(device);
                // Attempt to connect to the device
                _iBACservice.connect(device);
            } else if (resultCode == Constant.RESULT_ERROR_MORE_IBAC) {
                _conversationArrayAdapter.add(getResources().getString(R.string.error_more_ibac));
                ShutdownAction shutdownAction = new ShutdownAction(_handler, 3, true);
                shutdownAction.Invoke(null);
            } else {
                if (ApplicationConstants.DebugMode)
                    Log.d(TAG, "No devices found");

                _conversationArrayAdapter.add(getResources().getString(R.string.none_found));
                ShutdownAction shutdownAction = new ShutdownAction(_handler, 3, true);
                shutdownAction.Invoke(null);
            }
            break;
        case REQUEST_ENABLE_BT:
            if (resultCode == Activity.RESULT_OK) {
                _isConfiguringPhone = false;
                InitializeAllServices();
            } else {
                // User did not enable Bluetooth or an error occured
                if (ApplicationConstants.DebugMode)
                    Log.d(ApplicationConstants.ApplicationTag, "Bluetooth is not enabled");

                _handler.obtainMessage(IBAC.ADD_MESSAGE, getResources().getString(R.string.bt_not_enabled_leaving))
                        .sendToTarget();

                ShutdownAction shutdownAction = new ShutdownAction(_handler, 3, true);
                shutdownAction.Invoke(null);
            }
            break;
        case ApplicationConstants.CALIBRATION:
            switch (resultCode) {
            case ApplicationConstants.REQUEST_CALIBRATE:
                if (_iBACservice._messageProcessor.GetState() == MessageProcessorStates.NotConnected) {
                    _handler.obtainMessage(CALIBRATION_ABORTED_NO_CONNECTION, null).sendToTarget();
                } else {
                    try {
                        _iBACservice._messageProcessor.SendMessage(Messages.RequestCalibration);
                        _handler.obtainMessage(CALIBRATING, null).sendToTarget();
                    } catch (Exception e) {
                        Log.e(ApplicationConstants.ApplicationTag,
                                "Failed to send calibration message: " + ExceptionHelper.GetTypeIfMessageEmpty(e));
                    }
                }

                break;
            case ApplicationConstants.ACTIVITY_ABORT:
                if (_iBACservice._messageProcessor.GetState() == MessageProcessorStates.NotConnected) {
                    _handler.obtainMessage(CALIBRATION_ABORTED_NO_CONNECTION, null).sendToTarget();
                } else {
                    _handler.obtainMessage(CALIBRATION_ABORTED, null).sendToTarget();
                }
                break;
            default:
                break;
            }
            break;
        // case REQUEST_ENABLE_GPS:
        // deviceLocation.runGPS();
        // initBluetooth();
        // break;
        default:
            break;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.option_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.exit:
            // Ensure this device is discoverable by others
            finish();
            android.os.Process.killProcess(android.os.Process.myPid());
            return true;
        case R.id.calibrate:
            _inDialog = true;
            // ask for a password
            Intent i = new Intent(this, CalibrationViewModel.class);
            startActivityForResult(i, ApplicationConstants.CALIBRATION);
            return true;
        case R.id.ChangePin:
            _inDialog = true;
            Intent i2 = new Intent(this, ChangePinViewModel.class);
            startActivityForResult(i2, ApplicationConstants.CHANGE_PIN);
            return true;
        }

        return false;
    }

    private boolean sendResultToServer(Float result) {
        boolean success = false;
        SendResultService sendResultService = ServiceFactory.getSendResultService();
        SendResultRequest sendResultRequest = new SendResultRequest();
        // hard code for testing
        sendResultRequest.setTextBluetoothAddress(bluetoothMACAddress);
        sendResultRequest.setTextPhoneNumber(Session.PHONE_NUMBER);
        sendResultRequest.setFloatAlcoholResult(result);
        sendResultRequest.setDoubleLatitude(positionLatitude);
        sendResultRequest.setDoubleLongitude(positionLongitude);
        sendResultRequest.setFloatAccuracy(positionAccuracy);
        sendResultRequest.setBitmapPhoto(bitmapPhoto);
        Session.REQUEST_DATE = TimeFormatter.getCurrentTime();
        sendResultRequest.setTextUTCTimestamp(TimeFormatter.getUTCTime());
        sendResultRequest.setTextAppVersion(Session.APP_VERSION);
        sendResultRequest.setTextIBACVersion(Session.IBAC_VERSION);
        sendResultRequest.setTextMobileVersion(Session.MOBILE_OS);
        String hmac = bluetoothMACAddress + positionLatitude + positionLongitude;
        sendResultRequest
                .setTextHmac(HttpsHmac.getHmacString(Constant.HMAC_REQUEST_KEY, hmac, Constant.HMAC_ALGORITHM));

        try {
            sendResultService.executeSendResultRequest(sendResultRequest, this);
            success = true;
            // do something in the further
        } catch (SmartphoneException e) {
            Logging.e(e.toString());
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return success;
    }

    // --------For Camera--------------
    private void initialCamera() {
        surfaceView = (SurfaceView) findViewById(R.id.camera);
        surfaceView.setOnClickListener(this);

        imageView = (ImageView) findViewById(R.id.mti);

        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    private void startCamera() {
        imageView.setVisibility(View.INVISIBLE);
        surfaceView.setVisibility(View.VISIBLE);
        if (isPreviewRunning) {
            camera.stopPreview();
        }
        camera.startPreview();
        isPreviewRunning = true;
    }

    private Bitmap processBitmap(Bitmap orginalBitmap, int degrees) {
        Matrix matrixRotate = new Matrix();
        matrixRotate.setRotate(degrees, (float) orginalBitmap.getWidth() / 2,
                (float) orginalBitmap.getHeight() / 2);
        Bitmap rotatedBitmap = Bitmap.createBitmap(orginalBitmap, 0, 0, orginalBitmap.getWidth(),
                orginalBitmap.getHeight(), matrixRotate, true);

        int width = rotatedBitmap.getWidth();
        int height = rotatedBitmap.getHeight();

        int newWidth = 240;
        int newHeight = 320;

        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;

        Matrix matrixResize = new Matrix();
        if (Session.isFacingCamera) {
            matrixResize.setScale(-1, 1);// reversal
        }
        matrixResize.postScale(scaleWidth, scaleHeight);

        return Bitmap.createBitmap(rotatedBitmap, 0, 0, width, height, matrixResize, true);
    }

    // PictureCallback pictureCallback = new PictureCallback() {
    //
    // public void onPictureTaken(byte[] data, Camera camera) {
    // Log.d("PictureCallback", "...onPictureTaken...");
    // if (data != null) {
    // // original picture
    // Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
    // // Bitmap bitmap = BitmapFactory.decodeByteArray(data,
    // // 0, data.length).copy(Bitmap.Config.RGB_565, true);
    //
    // Bitmap finalBitmap = null;
    //
    // if (Session.isFacingCamera) {
    // finalBitmap = processBitmap(bitmap, 270);
    // } else {
    // finalBitmap = processBitmap(bitmap, 90);
    // }
    // // savePhotos(bitmap);
    //
    // setPhotoValue(finalBitmap);
    //
    // showImageStartTime = System.currentTimeMillis();
    // surfaceView.setVisibility(View.INVISIBLE);
    //
    // imageView.setImageBitmap(finalBitmap);
    // imageView.setVisibility(View.VISIBLE);
    //
    // if (isPreviewRunning) {
    // camera.stopPreview();
    // isPreviewRunning = false;
    // isCameraRunOnce = false;
    // }
    // }
    // }
    //
    // };

    PreviewCallback previewCallback = new PreviewCallback() {
        public void onPreviewFrame(byte[] data, Camera camera) {

            int width = camera.getParameters().getPreviewSize().width;
            int height = camera.getParameters().getPreviewSize().height;

            YuvImage yuvi = new YuvImage(data, ImageFormat.NV21, width, height, null);
            Rect rect = new Rect(0, 0, yuvi.getWidth(), yuvi.getHeight());
            OutputStream out = new ByteArrayOutputStream();
            yuvi.compressToJpeg(rect, 100, out);
            byte[] dataBytes = ((ByteArrayOutputStream) out).toByteArray();

            Bitmap bitmap = BitmapFactory.decodeByteArray(dataBytes, 0, dataBytes.length);
            Bitmap finalBitmap = null;

            if (Session.isFacingCamera) {
                finalBitmap = processBitmap(bitmap, 270);
            } else {
                finalBitmap = processBitmap(bitmap, 90);
            }
            // savePhotos(bitmap);

            setPhotoValue(finalBitmap);

            showImageStartTime = System.currentTimeMillis();
            surfaceView.setVisibility(View.INVISIBLE);

            imageView.setImageBitmap(finalBitmap);
            imageView.setVisibility(View.VISIBLE);

            if (isPreviewRunning) {
                camera.stopPreview();
                isPreviewRunning = false;
                isCameraRunOnce = false;
            }
        }
    };

    private void setPhotoValue(Bitmap bitmap) {
        bitmapPhoto = bitmap;
    }

    private void savePhotos(Bitmap bitmap) {
        String localPath = getApplicationContext().getFilesDir().getAbsolutePath() + "/photos/";
        String fileName = localPath + "Captured.jpg";

        FileOutputStream fileOutputStream = null;
        File file = new File(localPath);
        file.mkdirs();

        try {
            fileOutputStream = new FileOutputStream(fileName);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.flush();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private Bitmap readPhotos() {
        String localPath = getApplicationContext().getFilesDir().getAbsolutePath() + "/photos/";
        String fileName = localPath + "Test.jpg";

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(fileName, options);
        options.inSampleSize = computeSampleSize(options, -1, 128 * 128);
        options.inJustDecodeBounds = false;
        try {
            return BitmapFactory.decodeFile(fileName, options);
        } catch (OutOfMemoryError err) {
            err.printStackTrace();
        }
        return null;
    }

    ShutterCallback shutterCallback = new ShutterCallback() {
        public void onShutter() {
            // just log ,do nothing
            Log.d("ShutterCallback", "...onShutter...");
        }
    };

    public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
        int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);
        int roundedSize;
        if (initialSize <= 8) {
            roundedSize = 1;
            while (roundedSize < initialSize) {
                roundedSize <<= 1;
            }
        } else {
            roundedSize = (initialSize + 7) / 8 * 8;
        }
        return roundedSize;
    }

    private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength,
            int maxNumOfPixels) {
        double w = options.outWidth;
        double h = options.outHeight;
        int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
        int upperBound = (minSideLength == -1) ? 128
                : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));
        if (upperBound < lowerBound) {
            return lowerBound;
        }
        if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
            return 1;
        } else if (minSideLength == -1) {
            return lowerBound;
        } else {
            return upperBound;
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // TODO Auto-generated method stub
        if (isPreviewRunning) {
            camera.stopPreview();
        }

        Parameters parameters = camera.getParameters();
        List<Size> previewSizes = parameters.getSupportedPreviewSizes();
        Size previewSize = previewSizes.get(previewSizes.size() - 1);
        parameters.setPreviewSize(previewSize.width, previewSize.height);

        parameters.setPictureFormat(ImageFormat.JPEG);
        List<Size> listPictureSizes = parameters.getSupportedPictureSizes();
        Size pictureSize = listPictureSizes.get(listPictureSizes.size() - 1);
        parameters.setPictureSize(pictureSize.width, pictureSize.height);

        camera.setParameters(parameters);

        try {
            camera.setPreviewDisplay(holder);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (isCameraRunOnce) {
            startCamera();
        }
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        int cameraCount = 0;
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras();

        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
            Camera.getCameraInfo(camIdx, cameraInfo);
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                try {
                    camera = Camera.open(camIdx);
                    camera.setDisplayOrientation(90);
                    Session.isFacingCamera = true;
                    return;
                } catch (RuntimeException re) {
                    Logging.d(re.toString());
                }
            }
        }

        camera = Camera.open();
        camera.setDisplayOrientation(90);
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera.stopPreview();
        isPreviewRunning = false;
        camera.release();
        camera = null;
    }

    public void onClick(View v) {
        // TODO Auto-generated method stub
        // camera.takePicture(shutterCallback, null, pictureCallback);
    }

    // -----------------App Version-----------
    public String getAppVersion() {
        try {
            PackageManager manager = this.getPackageManager();
            PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
            return info.versionName;
        } catch (NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "";
    }

    // --------------Mobile OS---------
    public String getOSVersion() {
        return "Android " + android.os.Build.VERSION.RELEASE;
    }

    // -----------------Count down--------------
    // private Runnable countdownRunnable = new Runnable() {
    // public void run() {
    // if (coutdownCount >= 0) {
    // _textCountdown.setText(Integer.toString(coutdownCount + 1));
    // // Foks Comments
    // playBeepSound();
    // countdownHandler.postDelayed(countdownRunnable, 1000);
    // coutdownCount--;
    // } else {
    // _textCountdown.setText("");
    // if (isPreviewRunning) {
    // // camera.takePicture(shutterCallback, null, pictureCallback);
    // playCaptureSound();
    // camera.setOneShotPreviewCallback(previewCallback);
    // } else {
    // ShutdownAction action = new ShutdownAction(_handler, 3, true);
    // action.Invoke(null);
    // }
    // }
    // }
    // };

    private void capturePhoto() {
        if (isPreviewRunning) {
            // camera.takePicture(shutterCallback, null, pictureCallback);
            playCaptureSound();
            camera.setOneShotPreviewCallback(previewCallback);
        } else {
            ShutdownAction action = new ShutdownAction(_handler, 3, true);
            action.Invoke(null);
        }
    }

    // ---------------Sound Beep------------------------
    private MediaPlayer mediaPlayerBeep;
    private static final float BEEP_VOLUME = 0.10f;

    private void initBeepSound() {
        if (mediaPlayerBeep == null) {
            setVolumeControlStream(AudioManager.STREAM_MUSIC);
            mediaPlayerBeep = new MediaPlayer();
            mediaPlayerBeep.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayerBeep.setOnCompletionListener(beepListener);

            AssetFileDescriptor fileBeep = getResources().openRawResourceFd(R.raw.beep);
            try {
                mediaPlayerBeep.setDataSource(fileBeep.getFileDescriptor(), fileBeep.getStartOffset(),
                        fileBeep.getLength());
                fileBeep.close();
                mediaPlayerBeep.setVolume(BEEP_VOLUME, BEEP_VOLUME);
                mediaPlayerBeep.prepare();
            } catch (IOException e) {
                mediaPlayerBeep = null;
            }
        }
    }

    private void playBeepSound() {
        if (mediaPlayerBeep != null) {
            if (mediaPlayerBeep.isPlaying()) {
                mediaPlayerBeep.pause();
            }
            mediaPlayerBeep.start();
        }
    }

    private final OnCompletionListener beepListener = new OnCompletionListener() {
        public void onCompletion(MediaPlayer mediaPlayer) {
            mediaPlayer.seekTo(0);
        }
    };

    // ---------Sound capture-----------
    private MediaPlayer mediaPlayerCapture;
    private static final float CAPTURE_VOLUME = 1.0f;

    private void initCaptureSound() {
        if (mediaPlayerCapture == null) {
            setVolumeControlStream(AudioManager.STREAM_MUSIC);
            mediaPlayerCapture = new MediaPlayer();
            mediaPlayerCapture.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayerCapture.setOnCompletionListener(captureListener);

            AssetFileDescriptor fileBeep = getResources().openRawResourceFd(R.raw.camera_flash);
            try {
                mediaPlayerCapture.setDataSource(fileBeep.getFileDescriptor(), fileBeep.getStartOffset(),
                        fileBeep.getLength());
                fileBeep.close();
                mediaPlayerCapture.setVolume(CAPTURE_VOLUME, CAPTURE_VOLUME);
                mediaPlayerCapture.prepare();
            } catch (IOException e) {
                mediaPlayerCapture = null;
            }
        }
    }

    private void playCaptureSound() {
        if (mediaPlayerCapture != null) {
            if (mediaPlayerCapture.isPlaying()) {
                mediaPlayerCapture.pause();
            }
            mediaPlayerCapture.start();
        }
    }

    private final OnCompletionListener captureListener = new OnCompletionListener() {
        public void onCompletion(MediaPlayer mediaPlayer) {
            mediaPlayer.seekTo(0);
        }
    };

    // ---------app version-------------
    private void showAppVersion() {
        try {
            PackageManager manager = this.getPackageManager();
            Resources resource = this.getResources();
            String versionLabel = resource.getString(R.string.app_version_label) + " ";
            PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
            String versionNumber = info.versionName;
            textViewAppVersion.setText(versionLabel + versionNumber);
        } catch (NameNotFoundException e) {
            Logging.d("AppVersionNotFound: " + e.getMessage());
        }
    }

    //For Pairing
    private void pairDevice(BluetoothDevice device) {
        try {
            Log.d("sam22", "Start Pairing...");
            Method m = device.getClass().getMethod("createBond", (Class[]) null);
            //device.getClass().getMethod("setTrust", boolean.class).invoke(device);
            device.getClass().getMethod("cancelPairingUserInput", boolean.class).invoke(device);

            /** byte[] pin = ByteBuffer.allocate(4).putInt(1234).array();
             //int pinn = 1234;
             //Entering pin programmatically:  
             Method ms = device.getClass().getMethod("setPin", byte[].class);
             //Method ms = device.getClass().getMethod("setPasskey", int.class);
             ms.invoke(device, pin); **/

            m.invoke(device, (Object[]) null);

            Log.d("sam22", "Pairing finished.");
        } catch (Exception e) {
            Log.e("pairDevice()", e.getMessage());
        }
    }

    //For UnPairing
    private void unpairDevice(BluetoothDevice device) {
        try {
            Log.d("sam22", "Start Un-Pairing...");
            Method m = device.getClass().getMethod("removeBond", (Class[]) null);
            m.invoke(device, (Object[]) null);
            Log.d("sam22", "Un-Pairing finished.");
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
    }
}