br.liveo.ndrawer.ui.activity.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for br.liveo.ndrawer.ui.activity.MainActivity.java

Source

/*
 * Copyright 2015 Rudson Lima
 *
 * 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 br.liveo.ndrawer.ui.activity;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.location.Location;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import br.liveo.Model.HelpLiveo;
import br.liveo.interfaces.OnItemClickListener;
import br.liveo.interfaces.OnPrepareOptionsMenuLiveo;
import br.liveo.navigationliveo.NavigationLiveo;
import br.liveo.ndrawer.R;
import br.liveo.ndrawer.ui.adapter.BeaconDevice;
import br.liveo.ndrawer.ui.adapter.DeviceListAdapter;
import br.liveo.ndrawer.ui.adapter.PreTrackingAdapter;
import br.liveo.ndrawer.ui.adapter.RequestClass;
import br.liveo.ndrawer.ui.fragment.MainFragment31;
import br.liveo.ndrawer.ui.fragment.MainFragment32;
import br.liveo.ndrawer.ui.fragment.ViewPagerFragment;
//import br.liveo.ndrawer.ui.fragment.ViewPagerFragment2;
import br.liveo.ndrawer.ui.fragment.ViewPagerFragment3;
import br.liveo.ndrawer.ui.fragment.ViewPagerFragment4;
import br.liveo.ndrawer.ui.fragment.ViewPagerFragment5;
import br.liveo.ndrawer.ui.gcm.QuickstartPreferences;
import br.liveo.ndrawer.ui.gcm.RegistrationIntentService;
import br.liveo.ndrawer.ui.sensortag.DeviceInformationServiceProfile;
import br.liveo.ndrawer.ui.sensortag.GattInfo;
import br.liveo.ndrawer.ui.sensortag.GenericBluetoothProfile;
import br.liveo.ndrawer.ui.sensortag.HumidityProfile;
import br.liveo.ndrawer.ui.sensortag.IRTemperatureProfile;
import br.liveo.ndrawer.ui.sensortag.MovementProfile;
import br.liveo.ndrawer.ui.sensortag.TIOADProfile;

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class MainActivity extends NavigationLiveo implements OnItemClickListener,
        MainFragment32.OnMainFragment32SelectedListener, MainFragment31.OnMainFragment31SelectedListener {

    private HelpLiveo mHelpLiveo;

    private Timer mTimer = new Timer();
    private TimerTask mScanStartTimerTask = null;
    private TimerTask mScanStopTimerTask = null;
    private DeviceListAdapter mDeviceAdapter = null;

    private ArrayList<BeaconDevice> mDeviceList = new ArrayList<BeaconDevice>();

    public static MainActivity mainActivity = null;
    public static int startingPosition = 0;

    public BluetoothAdapter mBluetoothAdapter;
    private BluetoothManager mBluetoothManager;

    private LocationManager mLocationManager = null;

    public int REQUEET_ENABLE_BT = 1;
    private Handler mHandler;
    private BluetoothLeScanner mLEScanner;
    private ScanSettings settings;
    private volatile bleRequest curBleRequest = null;
    private BluetoothGatt mGatt;
    public String mRegisteredDevice = null;
    public int action = 0;
    private boolean mReceiving = false;
    private final Lock lock = new ReentrantLock();
    private List<BluetoothGattService> mServiceList = new ArrayList<BluetoothGattService>();
    private String mFwRev;
    private volatile boolean blocking = false;
    private volatile int lastGattStatus = 0; //Success

    // Queuing for fast application response.
    private volatile LinkedList<bleRequest> procQueue = new LinkedList<bleRequest>();
    private volatile LinkedList<bleRequest> nonBlockQueue = new LinkedList<bleRequest>();
    private List<GenericBluetoothProfile> mProfiles = new ArrayList<GenericBluetoothProfile>();
    private Thread mStatusThread = null;

    private IntentFilter mFilter;
    private Intent mDeviceIntent;
    private Timer timer;

    public static BroadcastReceiver mRegistrationBroadcastReceiver;
    private SharedPreferences prefs;
    private Intent intent;

    // const variables
    private final static long SCAN_PERIOD = 1000 * 3;
    private final static int REQ_DEVICE_ACT = 1;
    private final static int GATT_TIMEOUT = 150;

    public final static String ACTION_GATT_CONNECTED = "br.liveo.ndrawer.ACTION_GATT_CONNECTED";
    public final static String ACTION_GATT_DISCONNECTED = "br.liveo.ndrawer.ACTION_GATT_DISCONNECTED";
    public final static String ACTION_GATT_SERVICES_DISCOVERED = "br.liveo.ndrawer.ACTION_GATT_SERVICES_DISCOVERED";
    public final static String ACTION_DATA_READ = "br.liveo.ndrawer.ACTION_DATA_READ";
    public final static String ACTION_DATA_NOTIFY = "br.liveo.ndrawer.ACTION_DATA_NOTIFY";
    public final static String ACTION_DATA_WRITE = "br.liveo.ndrawer.ACTION_DATA_WRITE";
    public final static String EXTRA_DATA = "br.liveo.ndrawer.EXTRA_DATA";
    public final static String EXTRA_UUID = "br.liveo.ndrawer.EXTRA_UUID";
    public final static String EXTRA_STATUS = "br.liveo.ndrawer.EXTRA_STATUS";
    public final static String EXTRA_ADDRESS = "br.liveo.ndrawer.EXTRA_ADDRESS";

    public static int isRegister = 0;

    public ProgressDialog mProgressDialog = null;
    public ArrayList<BluetoothDevice> mBluetoothDeviceList = null;

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MovementProfile.status = 0;

        startingPosition = 0;

        registBroadcastReceiver();
        getInstanceIdToken();

        mDeviceAdapter = new DeviceListAdapter(this, R.layout.device_item);

        mHandler = new Handler();
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, "BLE Not Supported", Toast.LENGTH_SHORT).show();
            finish();
        }

        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = mBluetoothManager.getAdapter();
        timer = new Timer();

        mBluetoothDeviceList = new ArrayList<BluetoothDevice>();

        // Register the BroadcastReceiver
        mFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        mFilter.addAction(ACTION_GATT_CONNECTED);
        mFilter.addAction(ACTION_GATT_DISCONNECTED);
        mFilter.addAction(ACTION_GATT_SERVICES_DISCOVERED);
        mFilter.addAction(ACTION_DATA_NOTIFY);
        mFilter.addAction(ACTION_DATA_WRITE);
        mFilter.addAction(ACTION_DATA_READ);

        if (isRegister == 0) {
            registerReceiver(mReceiver, mFilter);
        }

        mainActivity = this;

        Thread queueThread = new Thread() {
            @Override
            public void run() {
                while (true) {
                    executeQueue();
                    try {
                        Thread.sleep(0, 100000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        queueThread.start();
    }

    private boolean checkPlayServices() {
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                GooglePlayServicesUtil.getErrorDialog(resultCode, this, 9000).show();
            } else {
                Log.i("msg", "This device is not supported.");
                finish();
            }
            return false;
        }
        return true;
    }

    public void getInstanceIdToken() {
        prefs = getSharedPreferences("PrefName", MODE_PRIVATE);
        String token = prefs.getString("token", "");

        if (token.equals("")) {
            if (checkPlayServices()) {
                // Start IntentService to register this application with GCM.
                Intent intent = new Intent(this, RegistrationIntentService.class);
                startService(intent);
            }
        } else {
            return;
        }
    }

    public void registBroadcastReceiver() {
        Log.i("?", "?");
        mRegistrationBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();

                if (action.equals(QuickstartPreferences.REGISTRATION_READY)) {

                } else if (action.equals(QuickstartPreferences.REGISTRATION_GENERATING)) {

                } else if (action.equals(QuickstartPreferences.REGISTRATION_COMPLETE)) {
                    String token = intent.getStringExtra("token");
                    Log.i("token", token);

                    prefs = getSharedPreferences("PrefName", MODE_PRIVATE);
                    SharedPreferences.Editor edit = prefs.edit();
                    edit.putString("token", token);
                    edit.commit();
                    String useremail = prefs.getString("useremail", "");

                    try {
                        String url = "http://125.131.73.198:3000/token";
                        RequestClass rc = new RequestClass(url);
                        rc.AddParam("useremail", useremail);
                        rc.AddParam("token", token);

                        rc.Execute(1);
                        String response = rc.getResponse();

                        if (response.length() == 0) {

                        } else {

                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }

            }
        };
    }

    @Override
    public void onResume() {
        super.onResume();

        MovementProfile.status = 0;

        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
                new IntentFilter(QuickstartPreferences.REGISTRATION_READY));
        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
                new IntentFilter(QuickstartPreferences.REGISTRATION_GENERATING));
        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
                new IntentFilter(QuickstartPreferences.REGISTRATION_COMPLETE));

        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEET_ENABLE_BT);
        } else {
            if (Build.VERSION.SDK_INT >= 21) {
                mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
                settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
            }
        }
    }

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

        /* unregisterReceiver(mReceiver);
         unregisterReceiver(mGattUpdateReceiver);*/

        LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);

        if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
            scanLeDevice(false);
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEET_ENABLE_BT) {
            if (resultCode == Activity.RESULT_CANCELED) {
                finish();
                return;
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    private void executeQueue() {
        // Everything here is done on the queue
        lock.lock();
        if (curBleRequest != null) {
            Log.d("BluetoothLeService", "executeQueue, curBleRequest running");
            try {
                curBleRequest.curTimeout++;
                if (curBleRequest.curTimeout > GATT_TIMEOUT) {
                    curBleRequest.status = bleRequestStatus.timeout;
                    curBleRequest = null;
                }
                Thread.sleep(10, 0);
            } catch (Exception e) {
                e.printStackTrace();
            }
            lock.unlock();
            return;
        }
        if (procQueue == null) {
            lock.unlock();
            return;
        }
        if (procQueue.size() == 0) {
            lock.unlock();
            return;
        }
        bleRequest procReq = procQueue.removeFirst();

        switch (procReq.operation) {
        case rd:
            //Read, do non blocking read
            break;
        case rdBlocking:
            //Normal (blocking) read
            if (procReq.timeout == 0) {
                procReq.timeout = GATT_TIMEOUT;
            }
            procReq.curTimeout = 0;
            curBleRequest = procReq;
            int stat = sendBlockingReadRequest(procReq);
            if (stat == -2) {
                Log.d("BluetoothLeService", "executeQueue rdBlocking: error, BLE was busy or device disconnected");
                lock.unlock();
                return;
            }
            break;
        case wr:
            //Write, do non blocking write (Ex: OAD)
            nonBlockQueue.add(procReq);
            sendNonBlockingWriteRequest(procReq);
            break;
        case wrBlocking:
            //Normal (blocking) write
            if (procReq.timeout == 0) {
                procReq.timeout = GATT_TIMEOUT;
            }
            curBleRequest = procReq;
            stat = sendBlockingWriteRequest(procReq);
            if (stat == -2) {
                Log.d("BluetoothLeService", "executeQueue wrBlocking: error, BLE was busy or device disconnected");
                lock.unlock();
                return;
            }
            break;
        case nsBlocking:
            if (procReq.timeout == 0) {
                procReq.timeout = GATT_TIMEOUT;
            }
            curBleRequest = procReq;
            stat = sendBlockingNotifySetting(procReq);
            if (stat == -2) {
                Log.d("BluetoothLeService", "executeQueue nsBlocking: error, BLE was busy or device disconnected");
                lock.unlock();
                return;
            }
            break;
        default:
            break;

        }
        lock.unlock();
    }

    public boolean checkGatt() {
        if (mBluetoothAdapter == null) {
            // Log.w(TAG, "BluetoothAdapter not initialized");
            return false;
        }
        if (mGatt == null) {
            // Log.w(TAG, "BluetoothGatt not initialized");
            return false;
        }
        if (this.blocking) {
            Log.d("BluetoothLeService", "Cannot start operation : Blocked");
            return false;
        }
        return true;

    }

    public void waitIdle(int timeout) {
        while (timeout-- > 0) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public int sendNonBlockingWriteRequest(bleRequest request) {
        request.status = bleRequestStatus.processing;
        if (!checkGatt()) {
            request.status = bleRequestStatus.failed;
            return -2;
        }
        mGatt.writeCharacteristic(request.characteristic);
        return 0;
    }

    public int sendBlockingReadRequest(bleRequest request) {
        request.status = bleRequestStatus.processing;
        int timeout = 0;
        if (!checkGatt()) {
            request.status = bleRequestStatus.failed;
            return -2;
        }
        mGatt.readCharacteristic(request.characteristic);
        this.blocking = true; // Set read to be blocking
        while (this.blocking) {
            timeout++;
            waitIdle(1);
            if (timeout > GATT_TIMEOUT) {
                this.blocking = false;
                request.status = bleRequestStatus.timeout;
                return -1;
            } //Read failed TODO: Fix this to follow connection interval !
        }
        request.status = bleRequestStatus.done;
        return lastGattStatus;
    }

    public int sendBlockingWriteRequest(bleRequest request) {
        request.status = bleRequestStatus.processing;
        int timeout = 0;
        if (!checkGatt()) {
            request.status = bleRequestStatus.failed;
            return -2;
        }
        mGatt.writeCharacteristic(request.characteristic);
        this.blocking = true; // Set read to be blocking
        while (this.blocking) {
            timeout++;
            waitIdle(1);
            if (timeout > GATT_TIMEOUT) {
                this.blocking = false;
                request.status = bleRequestStatus.timeout;
                return -1;
            } //Read failed TODO: Fix this to follow connection interval !
        }
        request.status = bleRequestStatus.done;
        return lastGattStatus;
    }

    public int sendBlockingNotifySetting(bleRequest request) {
        request.status = bleRequestStatus.processing;
        int timeout = 0;
        if (request.characteristic == null) {
            return -1;
        }
        if (!checkGatt())
            return -2;

        if (mGatt.setCharacteristicNotification(request.characteristic, request.notifyenable)) {

            BluetoothGattDescriptor clientConfig = request.characteristic
                    .getDescriptor(GattInfo.CLIENT_CHARACTERISTIC_CONFIG);
            if (clientConfig != null) {

                if (request.notifyenable) {
                    // Log.i(TAG, "Enable notification: " +
                    // characteristic.getUuid().toString());
                    clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                } else {
                    // Log.i(TAG, "Disable notification: " +
                    // characteristic.getUuid().toString());
                    clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
                }
                mGatt.writeDescriptor(clientConfig);
                // Log.i(TAG, "writeDescriptor: " +
                // characteristic.getUuid().toString());
                this.blocking = true; // Set read to be blocking
                while (this.blocking) {
                    timeout++;
                    waitIdle(1);
                    if (timeout > GATT_TIMEOUT) {
                        this.blocking = false;
                        request.status = bleRequestStatus.timeout;
                        return -1;
                    } //Read failed TODO: Fix this to follow connection interval !
                }
                request.status = bleRequestStatus.done;
                return lastGattStatus;
            }
        }
        return -3; // Set notification to android was wrong ...
    }

    private void broadcastUpdate(final String action, final String address, final int status) {
        final Intent intent = new Intent(action);
        intent.putExtra(EXTRA_ADDRESS, address);
        intent.putExtra(EXTRA_STATUS, status);
        sendBroadcast(intent);
    }

    private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic,
            final int status) {
        final Intent intent = new Intent(action);
        intent.putExtra(EXTRA_UUID, characteristic.getUuid().toString());
        intent.putExtra(EXTRA_DATA, characteristic.getValue());
        intent.putExtra(EXTRA_STATUS, status);
        sendBroadcast(intent);
    }

    private void unlockBlockingThread(int status) {
        this.lastGattStatus = status;
        this.blocking = false;
    }

    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            if (mGatt == null)
                return;

            BluetoothDevice device = gatt.getDevice();
            String address = device.getAddress();

            try {
                switch (newState) {
                case BluetoothProfile.STATE_CONNECTED:
                    broadcastUpdate(ACTION_GATT_CONNECTED, address, status);
                    break;
                case BluetoothProfile.STATE_DISCONNECTED:
                    broadcastUpdate(ACTION_GATT_DISCONNECTED, address, status);
                    break;
                default:
                    // Log.e(TAG, "New state not processed: " + newState);
                    break;
                }
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            BluetoothDevice device = gatt.getDevice();
            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED, device.getAddress(), status);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            broadcastUpdate(ACTION_DATA_NOTIFY, characteristic, BluetoothGatt.GATT_SUCCESS);
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
                int status) {
            if (blocking)
                unlockBlockingThread(status);
            if (nonBlockQueue.size() > 0) {
                lock.lock();
                for (int ii = 0; ii < nonBlockQueue.size(); ii++) {
                    bleRequest req = nonBlockQueue.get(ii);
                    if (req.characteristic == characteristic) {
                        req.status = bleRequestStatus.done;
                        nonBlockQueue.remove(ii);
                        break;
                    }
                }
                lock.unlock();
            }
            broadcastUpdate(ACTION_DATA_READ, characteristic, status);
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
                int status) {
            if (blocking)
                unlockBlockingThread(status);
            if (nonBlockQueue.size() > 0) {
                lock.lock();
                for (int ii = 0; ii < nonBlockQueue.size(); ii++) {
                    bleRequest req = nonBlockQueue.get(ii);
                    if (req.characteristic == characteristic) {
                        req.status = bleRequestStatus.done;
                        nonBlockQueue.remove(ii);
                        break;
                    }
                }
                lock.unlock();
            }
            broadcastUpdate(ACTION_DATA_WRITE, characteristic, status);
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            if (blocking)
                unlockBlockingThread(status);
            unlockBlockingThread(status);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            if (blocking)
                unlockBlockingThread(status);
        }
    };

    public void scanLeDevice(final boolean enable) {
        Log.i("dsfvfasdfv", "12125dsfdf");
        if (enable) {
            mHandler.postDelayed(new Runnable() {
                //  @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
                @Override
                public void run() {
                    //       if(Build.VERSION.SDK_INT < 21) {
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    //        }
                    //         else{
                    //            mLEScanner.stopScan(mScanCallback);

                    /*
                    if(mBtnStart.getVisibility() == View.VISIBLE) {
                        mlblMessage.setText("?  ?  .");
                        mBtnStart.setEnabled(true);
                    }
                    */
                    //     }
                }
            }, SCAN_PERIOD);
            //   if(Build.VERSION.SDK_INT < 21) {
            mBluetoothAdapter.startLeScan(mLeScanCallback);
            //  }else {
            //      mLEScanner.startScan(mScanCallback);
            //   }
        } else {
            //     if(Build.VERSION.SDK_INT < 21){
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
            //       } else {
            //          mLEScanner.stopScan(mScanCallback);
            //      }
        }
    }

    /*private ScanCallback mScanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        Log.i("callbackType", String.valueOf(callbackType));
        Log.i("result", result.toString());
        BluetoothDevice btDevice = result.getDevice();
        
        if(btDevice.getAddress().equals(mRegisteredDevice))
            connectToDevice(btDevice);
    }
        
    @Override
    public void onBatchScanResults(List<ScanResult> results){
        for(ScanResult st : results){
            Log.i("ScanResult - Results", st.toString());
        }
    }
        
    @Override
    public void onScanFailed(int errorCode) {
        Log.e("Scan Failed", "Error Code: " + errorCode);
    }
    };*/

    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {

            for (int i = 0; i < mDeviceList.size(); i++) {
                if (device.getAddress().equals(mDeviceList.get(i).getBdAddr())) {
                    mDeviceList.get(i).setRssi(rssi);
                    mDeviceList.get(i).setTxPower((int) scanRecord[29]);
                    return;
                }
            }
            // TODO:  ?  ? ?  rssi ??
            BeaconDevice newDevice = new BeaconDevice(device.getAddress(), device.getName(), rssi,
                    (int) scanRecord[29]);
            mDeviceList.add(newDevice);

            if (action == 1) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.i("onLeScan", device.toString() + " . " + device.getAddress());
                        connectToDevice(device);
                    }
                });
            }

        }
    };

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void connectToDevice(BluetoothDevice device) {
        try {
            int connState = mBluetoothManager.getConnectionState(device, BluetoothGatt.GATT);

            switch (connState) {
            case BluetoothGatt.STATE_CONNECTED: {
                if (mBluetoothAdapter == null)
                    return;

                final BluetoothDevice leDevice = mBluetoothAdapter.getRemoteDevice((String) null);
                int connectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);

                if (mGatt != null) {
                    if (connectionState != BluetoothProfile.STATE_DISCONNECTED) {
                        mGatt.disconnect();
                    }
                }
            }
                break;
            case BluetoothGatt.STATE_DISCONNECTED:
                if (mGatt == null) {
                    scanLeDevice(false);
                    mGatt = device.connectGatt(this, false, gattCallback);
                }
                break;
            default:
                Log.i("connect to device : ", "device busy");
                break;
            }
        } catch (Exception ex) {
            Log.i("Exception", "connectToDevice");
        }
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onInt(Bundle savedInstanceState) {
        // User Information
        this.userName.setText("DoubleS");
        this.userEmail.setText("onlyboys@kaist.ac.kr");
        this.userPhoto.setImageResource(R.drawable.ic_rudsonlive);
        this.userBackground.setImageResource(R.drawable.ic_user_background_first);

        // Creating items navigation
        mHelpLiveo = new HelpLiveo();
        mHelpLiveo.add("", R.drawable.tracking);
        //     mHelpLiveo.add("", R.drawable.recommend);
        mHelpLiveo.add("?", R.drawable.steal);
        mHelpLiveo.add("?", R.drawable.enroll);
        mHelpLiveo.add("", R.drawable.setting);

        with(this).startingPosition(startingPosition) //Starting position in the list
                .addAllHelpItem(mHelpLiveo.getHelp())

                .colorItemSelected(R.color.nliveo_blue_colorPrimary)
                .colorNameSubHeader(R.color.nliveo_blue_colorPrimary)

                .setOnClickUser(onClickPhoto).setOnPrepareOptionsMenu(onPrepare).build();

        int position = this.getCurrentPosition();
        this.setElevationToolBar(position != 2 ? 15 : 0);

        //-- shobeat_add 20/Oct/15
        // BLE
        BluetoothManager LEManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = LEManager.getAdapter();

        // BLE Callback method
        /* mLeScanCallback = new BluetoothAdapter.LeScanCallback(){
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord){
            //String msg = "NAME=" + device.getName() + "ADDRESS=" + device.getAddress() + "\nRSSI=" + rssi;
            //Log.d("BLE", msg);
            // TODO: local? arraylist   ?
            for(int i = 0; i < mDeviceList.size(); i++){
                if(device.getAddress().equals(mDeviceList.get(i).getBdAddr()))
                {
                    mDeviceList.get(i).setRssi(rssi);
                    mDeviceList.get(i).setTxPower((int)scanRecord[29]);
                    return;
                }
            }
            // TODO:  ?  ? ?  rssi ??
            BeaconDevice newDevice = new BeaconDevice(device.getAddress(), device.getName(), rssi, (int)scanRecord[29]);
            mDeviceList.add(newDevice);
        }
         };
            
         startTimerTask();*/
        //-- shobeat_end
    }

    public void onBtnListRefreshClicked() {
        // TODO: local? arrayList TextAdapter? ?
        mDeviceAdapter.setDeviceList(mDeviceList);
        // TODO: device list  
        mDeviceAdapter.notifyDataSetChanged();
    }

    public DeviceListAdapter getAdapter() {
        return mDeviceAdapter;
    }

    @Override
    public void onItemClick(int position) {
        Fragment mFragment;
        FragmentManager mFragmentManager = getSupportFragmentManager();

        if (position == 0) {
            mFragment = new ViewPagerFragment();
        } else if (position == 1) {
            mFragment = new ViewPagerFragment5();
        } else if (position == 2) {
            mFragment = new ViewPagerFragment3();
        } else {
            mFragment = new ViewPagerFragment4();
        }

        if (mFragment != null) {
            mFragmentManager.beginTransaction().replace(R.id.container, mFragment).commit();
        }

        setElevationToolBar(position != 2 ? 15 : 0);
    }

    private OnPrepareOptionsMenuLiveo onPrepare = new OnPrepareOptionsMenuLiveo() {
        @Override
        public void onPrepareOptionsMenu(Menu menu, int position, boolean visible) {
        }
    };

    private View.OnClickListener onClickPhoto = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(getApplicationContext(), "onClickPhoto :D", Toast.LENGTH_SHORT).show();
            closeDrawer();
        }
    };

    @Override
    protected void onDestroy() {
        mTimer.cancel();

        super.onDestroy();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);

    }

    private void stopTimerTask() {
        if (mScanStartTimerTask != null || mScanStopTimerTask != null) {
            mScanStartTimerTask.cancel();
            mScanStartTimerTask = null;
            mScanStopTimerTask.cancel();
            mScanStopTimerTask = null;
        }
    }

    private void startTimerTask() {
        stopTimerTask();

        mScanStartTimerTask = new TimerTask() {
            int mCount = 0;

            @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
            @Override
            public void run() {
                // TODO: local? arraylist clear
                if (!mDeviceList.isEmpty()) {
                    mDeviceList.clear();
                    String msg = "Clear=" + mDeviceList.size();
                    Log.d("BLE", msg);
                }

                mCount++;
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            }
        };

        mScanStopTimerTask = new TimerTask() {
            int mCount = 0;

            @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
            @Override
            public void run() {
                mCount++;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
                // TODO: local? arraylist GUI    adapter? 
            }
        };

        mTimer.schedule(mScanStartTimerTask, 0, 10000);
        mTimer.schedule(mScanStopTimerTask, 5000, 10000);
    };

    public void bleStop() {
        mBluetoothAdapter.stopLeScan(mLeScanCallback);

    }

    private static IntentFilter makeGattUpdateIntentFilter() {
        final IntentFilter fi = new IntentFilter();
        fi.addAction(ACTION_GATT_SERVICES_DISCOVERED);
        fi.addAction(ACTION_DATA_NOTIFY);
        fi.addAction(ACTION_DATA_WRITE);
        fi.addAction(ACTION_DATA_READ);
        fi.addAction(DeviceInformationServiceProfile.ACTION_FW_REV_UPDATED);
        fi.addAction(TIOADProfile.ACTION_PREPARE_FOR_OAD);
        return fi;
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void startDevice() {
        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        mProgressDialog.setIndeterminate(true);
        mProgressDialog.setTitle("? ?   ...");
        mProgressDialog.setMessage("");
        mProgressDialog.setMax(100);
        mProgressDialog.setProgress(0);
        mProgressDialog.show();

        /*
        mlblMessage.setText("??   .");
        mBtnStart.setEnabled(false);
        mBtnStart.setVisibility(View.INVISIBLE);
        */

        // GATT database
        Resources res = getResources();
        XmlResourceParser xpp = res.getXml(R.xml.gatt_uuid);
        new GattInfo(xpp);

        if (!mReceiving) {
            registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
            mReceiving = true;
        }

        if (mGatt != null) {
            if (mGatt.getServices().size() == 0)
                discoverServices();
            else {
            }
        }
    }

    private void stopDevice() {
        finishActivity(REQ_DEVICE_ACT);
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                // Bluetooth adapter state change
                switch (mBluetoothAdapter.getState()) {
                case BluetoothAdapter.STATE_ON:
                    //  ?
                    Log.i("BroadcastReceiver : ", "STATE_ON");
                    break;
                case BluetoothAdapter.STATE_OFF:
                    //  ?
                    Log.i("BroadcastReceiver : ", "STATE_OFF");
                    break;
                default:
                    // Log.w(TAG, "Action STATE CHANGED not processed ");
                    break;
                }
            } else if (ACTION_GATT_CONNECTED.equals(action)) {
                // GATT connect
                int status = intent.getIntExtra(EXTRA_STATUS, BluetoothGatt.GATT_FAILURE);
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    startDevice();

                } else
                    Log.i("Connect failed : ", "Status - " + status);

            } else if (ACTION_GATT_DISCONNECTED.equals(action)) {
                // GATT disconnect
                int status = intent.getIntExtra(EXTRA_STATUS, BluetoothGatt.GATT_FAILURE);
                stopDevice();
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    //mlblMessage.setText(GetMyDeviceAddress() + " disconnected.");
                }

            } else {
                // Log.w(TAG,"Unknown action: " + action);
            }

        }
    };

    public List<BluetoothGattService> getSupportedGattServices() {
        if (mGatt == null)
            return null;

        return mGatt.getServices();
    }

    public boolean refreshDeviceCache(BluetoothGatt gatt) {
        try {
            BluetoothGatt localBluetoothGatt = gatt;
            Method localMethod = localBluetoothGatt.getClass().getMethod("refresh", new Class[0]);
            if (localMethod != null) {
                boolean bool = ((Boolean) localMethod.invoke(localBluetoothGatt, new Object[0])).booleanValue();
                return bool;
            }
        } catch (Exception localException) {
            Log.e("BluetoothLeService : ", "An exception occured while refreshing device");
        }
        return false;
    }

    private void discoverServices() {
        if (mGatt.discoverServices()) {
            mServiceList.clear();
        }
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void disconnect(String address) {
        if (mBluetoothAdapter == null)
            return;

        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        int connectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);

        if (mGatt != null) {
            if (connectionState != BluetoothProfile.STATE_DISCONNECTED) {
                mGatt.disconnect();
            }
        }
    }

    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
        List<BluetoothGattService> serviceList;
        List<BluetoothGattCharacteristic> charList = new ArrayList<BluetoothGattCharacteristic>();

        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void onReceive(final Context context, Intent intent) {
            final String action = intent.getAction();
            final int status = intent.getIntExtra(EXTRA_STATUS, BluetoothGatt.GATT_SUCCESS);

            if (DeviceInformationServiceProfile.ACTION_FW_REV_UPDATED.equals(action)) {
                mFwRev = intent.getStringExtra(DeviceInformationServiceProfile.EXTRA_FW_REV_STRING);
                Log.d("DeviceActivity", "Got FW revision : " + mFwRev + " from DeviceInformationServiceProfile");
                for (GenericBluetoothProfile p : mProfiles) {
                    p.didUpdateFirmwareRevision(mFwRev);
                }
            }
            if (ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
                if (status == BluetoothGatt.GATT_SUCCESS) {

                    serviceList = getSupportedGattServices();
                    if (serviceList.size() > 0) {
                        for (int ii = 0; ii < serviceList.size(); ii++) {
                            BluetoothGattService s = serviceList.get(ii);
                            List<BluetoothGattCharacteristic> c = s.getCharacteristics();
                            if (c.size() > 0) {
                                for (int jj = 0; jj < c.size(); jj++) {
                                    charList.add(c.get(jj));
                                }
                            }
                        }
                    }
                    Log.d("DeviceActivity", "Total characteristics " + charList.size());
                    Thread worker = new Thread(new Runnable() {
                        @Override
                        public void run() {

                            //Iterate through the services and add GenericBluetoothServices for each service
                            int nrNotificationsOn = 0;
                            int maxNotifications;
                            int servicesDiscovered = 0;
                            int totalCharacteristics = 0;
                            //serviceList = getSupportedGattServices();
                            for (BluetoothGattService s : serviceList) {
                                List<BluetoothGattCharacteristic> chars = s.getCharacteristics();
                                totalCharacteristics += chars.size();
                            }

                            if (totalCharacteristics == 0) {
                                //Something bad happened, we have a problem
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        mProgressDialog.hide();
                                        mProgressDialog.dismiss();
                                        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
                                        alertDialogBuilder.setTitle("Error !");
                                        alertDialogBuilder.setMessage(serviceList.size()
                                                + " Services found, but no characteristics found, device will be disconnected !");
                                        alertDialogBuilder.setPositiveButton("Retry",
                                                new DialogInterface.OnClickListener() {
                                                    @Override
                                                    public void onClick(DialogInterface dialog, int which) {
                                                        refreshDeviceCache(mGatt);
                                                        //Try again
                                                        discoverServices();
                                                    }
                                                });
                                        alertDialogBuilder.setNegativeButton("Disconnect",
                                                new DialogInterface.OnClickListener() {
                                                    @Override
                                                    public void onClick(DialogInterface dialog, int which) {
                                                        disconnect(mRegisteredDevice);
                                                    }
                                                });
                                        AlertDialog a = alertDialogBuilder.create();
                                        a.show();
                                    }
                                });
                                return;
                            }
                            final int final_totalCharacteristics = totalCharacteristics;
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    mProgressDialog.setIndeterminate(false);
                                    mProgressDialog.setTitle("  ");
                                    mProgressDialog.setMessage("  ...");

                                }
                            });
                            if (Build.VERSION.SDK_INT > 18)
                                maxNotifications = 7;
                            else {
                                maxNotifications = 4;
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Toast.makeText(context,
                                                "Android version 4.3 detected, max 4 notifications enabled",
                                                Toast.LENGTH_LONG).show();
                                    }
                                });
                            }
                            for (int ii = 0; ii < serviceList.size(); ii++) {
                                BluetoothGattService s = serviceList.get(ii);
                                List<BluetoothGattCharacteristic> chars = s.getCharacteristics();
                                if (chars.size() == 0) {

                                    Log.d("DeviceActivity", "No characteristics found for this service !!!");
                                    return;
                                }
                                servicesDiscovered++;
                                final float serviceDiscoveredcalc = (float) servicesDiscovered;
                                final float serviceTotalcalc = (float) serviceList.size();
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        mProgressDialog.setProgress(
                                                (int) ((serviceDiscoveredcalc / (serviceTotalcalc - 1)) * 100));
                                    }
                                });
                                Log.d("DeviceActivity",
                                        "Configuring service with uuid : " + s.getUuid().toString());
                                if (HumidityProfile.isCorrectService(s)) {
                                    HumidityProfile hum = new HumidityProfile(context, s, mainActivity);
                                    mProfiles.add(hum);
                                    if (nrNotificationsOn < maxNotifications) {
                                        hum.configureService();
                                        nrNotificationsOn++;
                                    } else {
                                        hum.grayOutCell(true);
                                    }
                                    Log.d("DeviceActivity", "Found Humidity !");
                                }
                                /*
                                if (LuxometerProfile.isCorrectService(s)) {
                                LuxometerProfile lux = new LuxometerProfile(context, s, MainActivity.mainActivity);
                                mProfiles.add(lux);
                                if (nrNotificationsOn < maxNotifications) {
                                    lux.configureService();
                                    nrNotificationsOn++;
                                }
                                else {
                                    lux.grayOutCell(true);
                                }
                                }
                                */
                                if (IRTemperatureProfile.isCorrectService(s)) {
                                    IRTemperatureProfile irTemp = new IRTemperatureProfile(context, s,
                                            mainActivity);
                                    mProfiles.add(irTemp);
                                    if (nrNotificationsOn < maxNotifications) {
                                        irTemp.configureService();
                                    } else {
                                        irTemp.grayOutCell(true);
                                    }
                                    //No notifications add here because it is already enabled above ..
                                    Log.d("DeviceActivity", "Found IR Temperature !");
                                }
                                if (MovementProfile.isCorrectService(s)) {
                                    MovementProfile mov = new MovementProfile(context, s, mainActivity);
                                    mProfiles.add(mov);
                                    if (nrNotificationsOn < maxNotifications) {
                                        mov.configureService();
                                        nrNotificationsOn++;
                                    } else {
                                        mov.grayOutCell(true);
                                    }
                                    Log.d("DeviceActivity", "Found Motion !");
                                }
                                if (DeviceInformationServiceProfile.isCorrectService(s)) {
                                    DeviceInformationServiceProfile devInfo = new DeviceInformationServiceProfile(
                                            context, s, mainActivity);
                                    mProfiles.add(devInfo);
                                    devInfo.configureService();
                                    Log.d("DeviceActivity", "Found Device Information Service");
                                }
                                /*
                                if (TIOADProfile.isCorrectService(s)) {
                                TIOADProfile oad = new TIOADProfile(context, s, MainActivity.mainActivity);
                                mProfiles.add(oad);
                                oad.configureService();
                                Log.d("DeviceActivity","Found TI OAD Service");
                                }
                                */
                                if ((s.getUuid().toString()
                                        .compareTo("f000ccc0-0451-4000-b000-000000000000")) == 0) {
                                }
                            }
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    mProgressDialog.setTitle("   ...");
                                    mProgressDialog.setMax(mProfiles.size());
                                    mProgressDialog.setProgress(0);
                                }
                            });
                            for (final GenericBluetoothProfile p : mProfiles) {

                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        p.enableService();
                                        mProgressDialog.setProgress(mProgressDialog.getProgress() + 1);
                                    }
                                });
                                p.onResume();
                            }
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    mProgressDialog.hide();
                                    mProgressDialog.dismiss();
                                }
                            });
                        }
                    });
                    worker.start();
                } else {
                    Toast.makeText(getApplication(), "Service discovery failed", Toast.LENGTH_LONG).show();
                    return;
                }
            } else if (ACTION_DATA_NOTIFY.equals(action)) {
                // Notification
                byte[] value = intent.getByteArrayExtra(EXTRA_DATA);
                String uuidStr = intent.getStringExtra(EXTRA_UUID);
                //Log.d("DeviceActivity","Got Characteristic : " + uuidStr);
                for (int ii = 0; ii < charList.size(); ii++) {
                    BluetoothGattCharacteristic tempC = charList.get(ii);
                    if ((tempC.getUuid().toString().equals(uuidStr))) {
                        for (int jj = 0; jj < mProfiles.size(); jj++) {
                            GenericBluetoothProfile p = mProfiles.get(jj);
                            if (p.isDataC(tempC)) {
                                p.didUpdateValueForCharacteristic(tempC);
                                //Do MQTT
                                /*
                                Map<String,String> map = p.getMQTTMap();
                                if (map != null) {
                                for (Map.Entry<String, String> e : map.entrySet()) {
                                    if (mqttProfile != null)
                                        mqttProfile.addSensorValueToPendingMessage(e);
                                }
                                }
                                */
                            }
                        }
                        //Log.d("DeviceActivity","Got Characteristic : " + tempC.getUuid().toString());
                        break;
                    }
                }

                //onCharacteristicChanged(uuidStr, value);
            } else if (ACTION_DATA_WRITE.equals(action)) {
                // Data written
                byte[] value = intent.getByteArrayExtra(EXTRA_DATA);
                String uuidStr = intent.getStringExtra(EXTRA_UUID);
                for (int ii = 0; ii < charList.size(); ii++) {
                    BluetoothGattCharacteristic tempC = charList.get(ii);
                    if ((tempC.getUuid().toString().equals(uuidStr))) {
                        for (int jj = 0; jj < mProfiles.size(); jj++) {
                            GenericBluetoothProfile p = mProfiles.get(jj);
                            p.didWriteValueForCharacteristic(tempC);
                        }
                        //Log.d("DeviceActivity","Got Characteristic : " + tempC.getUuid().toString());
                        break;
                    }
                }
            } else if (ACTION_DATA_READ.equals(action)) {
                // Data read
                byte[] value = intent.getByteArrayExtra(EXTRA_DATA);
                String uuidStr = intent.getStringExtra(EXTRA_UUID);
                for (int ii = 0; ii < charList.size(); ii++) {
                    BluetoothGattCharacteristic tempC = charList.get(ii);
                    if ((tempC.getUuid().toString().equals(uuidStr))) {
                        for (int jj = 0; jj < mProfiles.size(); jj++) {
                            GenericBluetoothProfile p = mProfiles.get(jj);
                            p.didReadValueForCharacteristic(tempC);
                        }
                        //Log.d("DeviceActivity","Got Characteristic : " + tempC.getUuid().toString());
                        break;
                    }
                }
            } else {
                if (TIOADProfile.ACTION_PREPARE_FOR_OAD.equals(action)) {
                    new firmwareUpdateStart(mProgressDialog, context).execute();
                }
            }
            if (status != BluetoothGatt.GATT_SUCCESS) {
                Log.i("GATT error code : ", Integer.toString(status));
            }
        }
    };

    class firmwareUpdateStart extends AsyncTask<String, Integer, Void> {
        ProgressDialog pd;
        Context con;

        public firmwareUpdateStart(ProgressDialog p, Context c) {
            this.pd = p;
            this.con = c;
        }

        @Override
        protected void onPreExecute() {
            this.pd = new ProgressDialog(mainActivity);
            this.pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            this.pd.setIndeterminate(false);
            this.pd.setTitle("Starting firmware update");
            this.pd.setMessage("");
            this.pd.setMax(mProfiles.size());
            this.pd.show();
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(String... params) {
            Integer ii = 1;
            for (GenericBluetoothProfile p : mProfiles) {

                p.disableService();
                p.deConfigureService();
                publishProgress(ii);
                ii = ii + 1;
            }

            //final Intent i = new Intent(this.con, FwUpdateActivity_CC26xx.class);
            //startActivityForResult(i, FWUPDATE_ACT_REQ);

            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            this.pd.setProgress(values[0]);
        }

        @Override
        protected void onPostExecute(Void result) {
            this.pd.dismiss();
            super.onPostExecute(result);
        }

    }

    public boolean addRequestToQueue(bleRequest req) {
        lock.lock();
        if (procQueue.peekLast() != null) {
            req.id = procQueue.peek().id++;
        } else {
            req.id = 0;
            procQueue.add(req);
        }
        lock.unlock();
        return true;
    }

    public bleRequestStatus pollForStatusofRequest(bleRequest req) {
        lock.lock();
        if (req == curBleRequest) {
            bleRequestStatus stat = curBleRequest.status;
            if (stat == bleRequestStatus.done) {
                curBleRequest = null;
            }
            if (stat == bleRequestStatus.timeout) {
                curBleRequest = null;
            }
            lock.unlock();
            return stat;
        } else {
            lock.unlock();
            return bleRequestStatus.no_such_request;
        }
    }

    public int setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enable) {
        bleRequest req = new bleRequest();
        req.status = bleRequestStatus.not_queued;
        req.characteristic = characteristic;
        req.operation = bleRequestOperation.nsBlocking;
        req.notifyenable = enable;
        addRequestToQueue(req);
        boolean finished = false;
        while (!finished) {
            bleRequestStatus stat = pollForStatusofRequest(req);
            if (stat == bleRequestStatus.done) {
                finished = true;
                return 0;
            } else if (stat == bleRequestStatus.timeout) {
                finished = true;
                return -3;
            }
        }
        return -2;
    }

    public int readCharacteristic(BluetoothGattCharacteristic characteristic) {
        bleRequest req = new bleRequest();
        req.status = bleRequestStatus.not_queued;
        req.characteristic = characteristic;
        req.operation = bleRequestOperation.rdBlocking;
        addRequestToQueue(req);
        boolean finished = false;
        while (!finished) {
            bleRequestStatus stat = pollForStatusofRequest(req);
            if (stat == bleRequestStatus.done) {
                finished = true;
                return 0;
            } else if (stat == bleRequestStatus.timeout) {
                finished = true;
                return -3;
            }
        }
        return -2;
    }

    public int writeCharacteristic(BluetoothGattCharacteristic characteristic, byte b) {

        byte[] val = new byte[1];
        val[0] = b;
        characteristic.setValue(val);

        bleRequest req = new bleRequest();
        req.status = bleRequestStatus.not_queued;
        req.characteristic = characteristic;
        req.operation = bleRequestOperation.wrBlocking;
        addRequestToQueue(req);
        boolean finished = false;
        while (!finished) {
            bleRequestStatus stat = pollForStatusofRequest(req);
            if (stat == bleRequestStatus.done) {
                finished = true;
                return 0;
            } else if (stat == bleRequestStatus.timeout) {
                finished = true;
                return -3;
            }
        }
        return -2;
    }

    public int writeCharacteristic(BluetoothGattCharacteristic characteristic, byte[] b) {
        characteristic.setValue(b);
        bleRequest req = new bleRequest();
        req.status = bleRequestStatus.not_queued;
        req.characteristic = characteristic;
        req.operation = bleRequestOperation.wrBlocking;
        addRequestToQueue(req);
        boolean finished = false;
        while (!finished) {
            bleRequestStatus stat = pollForStatusofRequest(req);
            if (stat == bleRequestStatus.done) {
                finished = true;
                return 0;
            } else if (stat == bleRequestStatus.timeout) {
                finished = true;
                return -3;
            }
        }
        return -2;
    }

    public int writeCharacteristic(BluetoothGattCharacteristic characteristic) {
        bleRequest req = new bleRequest();
        req.status = bleRequestStatus.not_queued;
        req.characteristic = characteristic;
        req.operation = bleRequestOperation.wrBlocking;
        addRequestToQueue(req);
        boolean finished = false;
        while (!finished) {
            bleRequestStatus stat = pollForStatusofRequest(req);
            if (stat == bleRequestStatus.done) {
                finished = true;
                return 0;
            } else if (stat == bleRequestStatus.timeout) {
                finished = true;
                return -3;
            }
        }
        return -2;
    }

    public enum bleRequestOperation {
        wrBlocking, wr, rdBlocking, rd, nsBlocking,
    }

    public enum bleRequestStatus {
        not_queued, queued, processing, timeout, done, no_such_request, failed,
    }

    public class bleRequest {
        public int id;
        public BluetoothGattCharacteristic characteristic;
        public bleRequestOperation operation;
        public volatile bleRequestStatus status;
        public int timeout;
        public int curTimeout;
        public boolean notifyenable;
    }
}