连接蓝牙扫描仪时UI阻止

时间:2018-04-12 08:11:58

标签: android xamarin bluetooth

我遇到的问题是,在不使用线程的情况下,UI被阻止并显示空白屏幕。在这里,我尝试使用我的代码连接到蓝牙扫描仪LPR设备,但它在连接时以某种方式阻止UI,这有点烦人。我试图在连接时显示我认为会通知用户的吐司。但没有运气,它仍然显示空白屏幕,直到它连接,一旦连接它显示连接消息。

public class BluetoothDeviceConnector : IDeviceConnector
{
    private const string Tag = nameof(BluetoothDeviceConnector);

    private const int StateNone = 0; // we're doing nothing
    private const int StateConnecting = 2; // now initiating an outgoing connection
    private const int StateConnected = 3; // now connected to a remote device

    protected readonly BluetoothAdapter BluetoothAdapter;
    private readonly IMessageHandler _handler;
    private readonly string _mAddress;
    private ConnectThread _mConnectThread;
    private ConnectedThread _mConnectedThread;
    private int _mState;
    private readonly ILog _log;

    ///<summary>
    /// Prepare a new Bluetooth session.
    /// @param handler A Handler to send messages back to the UI Activity
    ///</summary>

    public BluetoothDeviceConnector(IMessageHandler handler, string address, ILog log)
    {
        _log = log;
        BluetoothAdapter = BluetoothAdapter.DefaultAdapter;
        _mState = StateNone;
        _handler = handler;
        _mAddress = address;
    }

    /// <summary>
    /// Set the current state of the connection
    /// @param state An integer defining the current connection state
    /// </summary>

    [MethodImpl(MethodImplOptions.Synchronized)]
    private void SetState(int state)
    {
        _log.Info(Tag + " setState() " + _mState + " -> " + state);
        _mState = state;
    }

    private BluetoothAdapter GetBluetoothAdapter()
    {
        return BluetoothAdapter.DefaultAdapter;
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void Connect()
    {
        var device = GetBluetoothAdapter().GetRemoteDevice(_mAddress);
        Connect(device);
    }

    ///<summary>
    /// Start the ConnectThread to initiate a connection to a remote device.
    /// @param device The BluetoothDevice to connect
    /// </summary>

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void Connect(BluetoothDevice device)
    {
        _log.Info(Tag + " connecting to: " + device);

        // Cancel any thread attempting to make a connection
        if (_mState == StateConnecting)
        {
            if (_mConnectThread != null)
            {
                _mConnectThread.Cancel();
                _mConnectThread = null;
            }
        }

        // Cancel any thread currently running a connection
        if (_mConnectedThread != null)
        {
            _mConnectedThread.Cancel();
            _mConnectedThread = null;
        }

        // Start the thread to connect with the given device
        try
        {
            _mConnectThread = new ConnectThread(device, this);
            _mConnectThread.Start();
            SetState(StateConnecting);
            _handler.SendConnectingTo(device.Name);
        }
        catch (SecurityException e)
        {

            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
        catch (IllegalArgumentException e)
        {
            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
        catch (NoSuchMethodException e)
        {
            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
        catch (IllegalAccessException e)
        {
            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
        catch (InvocationTargetException e)
        {
            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
        catch (Exception e)
        {
            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
    }

    ///<summary>
    /// Start the ConnectedThread to begin managing a Bluetooth connection
    /// @param socket The BluetoothSocket on which the connection was made
    /// @param device The BluetoothDevice that has been connected
    /// </summary>

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void Connected(BluetoothSocket socket, BluetoothDevice device)
    {
        _log.Info(Tag + " connected");

        // Cancel the thread that completed the connection
        if (_mConnectThread != null)
        {
            _mConnectThread.Cancel();
            _mConnectThread = null;
        }

        // Cancel any thread currently running a connection
        if (_mConnectedThread != null)
        {
            _mConnectedThread.Cancel();
            _mConnectedThread = null;
        }

        // Start the thread to manage the connection and perform transmissions
        _mConnectedThread = new ConnectedThread(socket, this);
        _mConnectedThread.Start();

        SetState(StateConnected);
        _handler.SendConnectedTo(device.Name);
    }

    ///<summary>
    /// Stop all threads
    /// </summary>

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void Disconnect()
    {
        _log.Info(Tag + " Disconnect");

        if (_mConnectThread != null)
        {
            _mConnectThread.Cancel();
            _mConnectThread = null;
        }

        if (_mConnectedThread != null)
        {
            _mConnectedThread.Shutdown();
            _mConnectedThread.Cancel();
            _mConnectedThread = null;
        }

        SetState(StateNone);
        _handler.SendNotConnected();
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void SendAsciiMessage(string chars)
    {
        //Write((chars + "\n").GetBytes());
    }

    ///<summary>
    /// Write to the ConnectedThread in an unsynchronized manner
    /// @param out The bytes to write
    /// @see ConnectedThread#Write(byte[])
    /// </summary>

    private void Write(byte[] value)
    {
        // Create temporary object

        // Synchronize a copy of the ConnectedThread
        if (_mState != StateConnected) return;

        // Perform the write unsynchronized
        Task.Run(() =>
        {
            _mConnectedThread.Write(value);
        });
    }

    ///<summary>
    /// Indicate that the connection attempt failed and notify the UI Activity.
    /// </summary>
    private void ConnectionFailed()
    {
        SetState(StateNone);
        _handler.SendConnectionFailed();
        _log.Info(Tag + " ConnectionFailed");
    }

    ///<summary>
    /// Indicate that the connection was lost and notify the UI Activity.
    /// </summary>

    private void ConnectionLost()
    {
        SetState(StateNone);
        _handler.SendConnectionLost();
        _log.Info(Tag + " ConnectionLost");
    }

    /// <summary>
    /// This thread runs while attempting to make an outgoing connection
    /// with a device. It runs straight through; the connection either
    /// succeeds or fails.
    /// SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
    /// </summary>
    private class ConnectThread : Thread
    {
        private readonly BluetoothSocket _mmSocket;
        private readonly BluetoothDevice _mmDevice;
        private readonly BluetoothDeviceConnector _deviceConnector;
        //public ISharedPreferences prefs = Application.Context.GetSharedPreferences("Aglive_SharedPreferences", FileCreationMode.Private);


        public ConnectThread(BluetoothDevice device, BluetoothDeviceConnector deviceConnector)
        {
            _mmDevice = device;
            BluetoothSocket tmp = null;
            _deviceConnector = deviceConnector;
            if (DeviceListActivity.deviceActivity != null)
            {
                Toast.MakeText(DeviceListActivity.deviceActivity, AgliveResource.Connecting + "...", ToastLength.Long).Show();

            }
            _deviceConnector._log.Info(Tag + " calling device.createRfcommSocket with channel 1 ...");

            try
            {
                //tmp = device.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805F9B34FB"));
                //tmp = device.CreateRfcommSocketToServiceRecord(device.GetUuids()[0].Uuid);
                deviceConnector.BluetoothAdapter.CancelDiscovery();
                var createRfcommSocket = JNIEnv.GetMethodID(device.Class.Handle, "createInsecureRfcommSocket", "(I)Landroid/bluetooth/BluetoothSocket;");
                var socket = JNIEnv.CallObjectMethod(device.Handle, createRfcommSocket, new JValue(1));
                tmp = GetObject<BluetoothSocket>(socket, JniHandleOwnership.TransferLocalRef);
                _deviceConnector._log.Info(Tag + " calling device.createRfcommSocket with channel 2 ...");
                var uuidList = device.GetUuids();
                if (uuidList != null)
                {
                    int count = 0;
                    while(count < 10)//true)//10 attempts
                    //foreach (var uuid in uuidList)
                    {
                        try
                        {
                            //_deviceConnector._log.Info(Tag + " connect with uuid: " + uuid);
                            //tmp = device.CreateInsecureRfcommSocketToServiceRecord(uuid.Uuid);
                            // tmp = (BluetoothSocket)device.Class.GetMethod("createRfcommSocket", new Class[] { }).Invoke(device,1);
                            //if (BluetoothDevice.DeviceTypeLe == device.GetType())
                            //{.

                            if ((int)Build.VERSION.SdkInt >= 10)
                            {
                                try
                                {
                                    Method m = device.Class.GetMethod("createRfcommSocket", new Class[] { Integer.Type });
                                    tmp = (BluetoothSocket)m.Invoke(device, 1);
                                }
                                catch (Exception e)
                                {
                                    //Log.e(TAG, "Could not create Insecure RFComm Connection",e);
                                }
                            }
                            if (isconnected.isConnected != true)
                            {
                                tmp.Connect();
                                isconnected.isConnected = true;
                            }
                            else
                            {
                                break;
                            }
                            //}
                            _deviceConnector._log.Info(Tag + " connect with uuid status: " + tmp.IsConnected);
                            if (tmp.IsConnected)
                            {

                                //_deviceConnector._log.Info(Tag + " uuid success " + uuid);
                                break;
                            }
                            //ISharedPreferencesEditor editor = prefs.Edit();
                            //editor.PutBoolean("isConnected", tmp.IsConnected);
                            //editor.Apply();
                        }
                        catch (Exception e)
                        {
                            // ignored
                        }
                        count++;
                    }
                }

                _deviceConnector._log.Info(Tag + " setting socket to result of createRfcommSocket");
                _deviceConnector._log.Info(Tag + " setting socket Status" + tmp.IsConnected);
            }
            catch (Exception e)
            {
                _deviceConnector._log.Error(Tag + " ConnectThread", e);
            }
            _mmSocket = tmp;
        }

        public override void Run()
        {
            base.Run();
            _deviceConnector._log.Info(Tag + " BEGIN mConnectThread");
            //setName("ConnectThread");

            // Always cancel discovery because it will slow down a connection
            _deviceConnector.BluetoothAdapter.CancelDiscovery();

            // Make a connection to the BluetoothSocket
            try
            {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                _deviceConnector._log.Info(Tag + " Run() => " + _mmSocket.IsConnected);
                if (!_deviceConnector.BluetoothAdapter.IsDiscovering && !_mmSocket.IsConnected)
                {
                    _deviceConnector._log.Info(Tag + " BEGIN mConnectThread 1");
                    _mmSocket.Connect();
                    _deviceConnector._log.Info(Tag + " BEGIN mConnectThread 2");
                }
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " ConnectThread => Run Function", e);
                _deviceConnector.ConnectionFailed();
                try
                {
                    _mmSocket.Close();
                }
                catch (IOException e2)
                {
                    _deviceConnector._log.Error(Tag + " unable to close() socket during connection failure", e2);
                }
                return;
            }

            // Reset the ConnectThread because we're done
            _deviceConnector._mConnectThread = null;

            // Start the connected thread
            _deviceConnector.Connected(_mmSocket, _mmDevice);
            _deviceConnector._log.Info(Tag + " END mConnectThread");
        }

        [Obsolete("deprecated")]
        public override void Destroy()
        {
            try
            {
                _deviceConnector._log.Info(Tag + " Destory()");
                _mmSocket?.Close();
                _deviceConnector._log.Info(Tag + " Destroy");
                base.Destroy();
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " close() of connect socket failed", e);
            }
        }

        public void Cancel()
        {
            try
            {
                _deviceConnector._log.Info(Tag + " Cancel()");
                _mmSocket?.Close();
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " close() of connect socket failed", e);
            }
        }
    }

    ///<summary>
    /// This thread runs during a connection with a remote device.
    /// It handles all incoming and outgoing transmissions.
    /// </summary>
    private class ConnectedThread : Thread
    {
        private readonly BluetoothSocket _mmSocket;
        private readonly Stream _mmInStream;
        private readonly Stream _mmOutStream;
        private readonly BluetoothDeviceConnector _deviceConnector;

        public ConnectedThread(BluetoothSocket socket, BluetoothDeviceConnector deviceConnector)
        {
            _deviceConnector = deviceConnector;
            _mmSocket = socket;
            _deviceConnector._log.Info(Tag + " create ConnectedThread");
            // Get the BluetoothSocket input and output streams
            try
            {
                _mmInStream = _mmSocket?.InputStream;
                _mmOutStream = _mmSocket?.OutputStream;
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " temp sockets not created", e);
            }
        }

        private bool _stop;
        private readonly bool _hasReadAnything = false;

        public void Shutdown()
        {
            _stop = true;
            if (!_hasReadAnything) return;

            try
            {
                _deviceConnector._log.Info(Tag + " Shutdown ConnectedThread");
                _mmInStream?.Close();
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " close() of InputStream failed.", e);
            }
        }

        public override void Run()
        {
            base.Run();
            _deviceConnector._log.Info(Tag + " BEGIN mConnectedThread");

            var reader = new Java.IO.BufferedReader(new Java.IO.InputStreamReader(_mmInStream));

            while (!_stop)
            {
                try
                {
                    var rfid = reader.ReadLine();
                    if (!string.IsNullOrEmpty(rfid?.Trim()))
                    {
                        _deviceConnector._handler.SendLineRead(rfid);
                    }
                }
                catch (IOException e)
                {
                    _deviceConnector._log.Error(Tag + " disconnected", e);
                    _deviceConnector.ConnectionLost();
                    break;
                }
            }
        }

        ///<summary>
        /// Write to the connected OutStream.
        /// @param bytes The bytes to write
        /// </summary>

        public void Write(byte[] bytes)
        {
            try
            {
                _mmOutStream.Write(bytes, 0, bytes.Length);
                _deviceConnector._handler.SendBytesWritten(bytes);
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " Exception during write", e);
            }
        }

        public void Cancel()
        {
            try
            {
                _deviceConnector._log.Error(Tag + " ConnectedThread() => Cancel()");
                _mmInStream.Close();
                _mmOutStream.Close();
                _mmSocket?.Close();
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " close() of connect socket failed", e);
            }
        }
    }
}

public static class isconnected
{
    public static bool isConnected { get; set; }
}

我尝试连接扫描仪的位置的活动:

 public class MenuActivity : BaseActivity
{
    Button _dashboard_menuItem, _sync_menuItem, _scan_menuItem, _activity_menuItem, _settings_menuItem, _contact_menuItem, _signout_menuItem;
    Switch _connectScannerSwitch;
    public IRFIDReader RFIDReader =Dependencies.Container.Get<IRFIDReader>();
    private bool isCalled=false;
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.activity_menu);
        InitializeComponant();
        InitializeEvents();           
        _connectScannerSwitch.Checked = isconnected.isConnected;
        _scan_menuItem.Text = isconnected.isConnected ? AgliveResource.DisconnectScanner : AgliveResource.ConnectScanner;            
    }


    private void InitializeEvents()
    {
        _connectScannerSwitch.CheckedChange += _connectScannerSwitch_Click;
        _connectScannerSwitch.Click += _connectScannerSwitch_Click;
    }
    private void _connectScannerSwitch_Click(object sender, EventArgs e)
    {
        if (!_connectScannerSwitch.Checked)
        {
            if (!isconnected.isConnected)
            {
                _scan_menuItem.Text = "Connecting";
            }
        }
        ConnectDisconnectWand();
    }

    public void SetWandConnectValue(bool value)
    {
        _connectScannerSwitch.Checked = value;
       ConnectDisconnectWand();
    }

    private void ConnectDisconnectWand()
    {
        if (string.IsNullOrEmpty(prefs.GetString("BluetoothDeviceName", null)))
        {
            if (isCalled == false)
            {
                _connectScannerSwitch.Checked = false;

                var intent = new Intent(this, typeof(DeviceListActivity));
                 StartActivityForResult(intent, RequestCode.RequestConnectDevice);
                isCalled = true;
            }
            return;
        }

        TokenExpiredSubscriptionToken = TinyMessenger.Subscribe<RFIDReaderStateChangedEvent>(StateChangedEvent);

        if (_connectScannerSwitch.Checked)
        {
            if (!isconnected.isConnected)
            {
                _scan_menuItem.Text = AgliveResource.Connecting;
                RFIDReader.ConnectDevice();
            }
        }
        else if (RFIDReader.IsConnected)
        {
            RFIDReader.DisConnectDevice();
        }
    }
    private void InitializeComponant()
    {
        prefs = Application.Context.GetSharedPreferences("SharedPreferences", FileCreationMode.Private);
        _scan_menuItem = FindViewById<Button>(Resource.Id.ScanMenuItem);
        _connectScannerSwitch=FindViewById<Switch>(Resource.Id.connectScannerSwitch);
    }
    public override bool OnOptionsItemSelected(IMenuItem item)
    {
        switch (item.ItemId)
        {
            // case Android.Resource.Id.Home:
            case Resource.Id.back:
                OnBackPressed();
                return true;
            case Resource.Id.menuIcon:
                {
                    StartActivity(typeof(MenuActivity));
                    return true;
                }
            default:
                return base.OnOptionsItemSelected(item);
        }
    }
    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        base.OnActivityResult(requestCode, resultCode, data);
        isCalled = false;
        _scan_menuItem.Text = _connectScannerSwitch.Checked ? AgliveResource.DisconnectScanner : AgliveResource.ConnectScanner;//"Disconnect RFID Scanner" : "Connect to Scanner";

        if (resultCode != Result.Ok)
            return;

        switch (requestCode)
        {
            case RequestCode.RequestConnectDevice:
                isCalled = false;
                //_connectScannerSwitch.Checked = true;
                //_scan_menuItem.Text = "connected";
                if (!string.IsNullOrEmpty(prefs.GetString("BluetoothDeviceName", null)))
                {
                    Toast.MakeText(this, AgliveResource.Connecting + "...", ToastLength.Long).Show();
                    SetWandConnectValue(true);
                }

                break;
        }
    }

    private void StateChangedEvent(RFIDReaderStateChangedEvent rfidReaderStateChangedEvent)
    {
        if (_connectScannerSwitch.Checked && !RFIDReader.IsConnected)
        {
            if (!string.IsNullOrEmpty(RFIDReader.ErrorMessage))
            {
                Toast.MakeText(this, RFIDReader.ErrorMessage, ToastLength.Long).Show();
                isCalled = false;
            }
            TinyMessenger.Unsubscribe<RFIDReaderStateChangedEvent>(TokenExpiredSubscriptionToken);
            isconnected.isConnected = false;
        }
        SetWandConnectionLabel();
    }

    private void SetWandConnectionLabel()
    {
        _connectScannerSwitch.Checked = RFIDReader.IsConnected;
        _scan_menuItem.Text = _connectScannerSwitch.Checked ? AgliveResource.DisconnectScanner : AgliveResource.ConnectScanner;
    }
}

2 个答案:

答案 0 :(得分:1)

  

我遇到的问题是,在不使用线程的情况下,UI被阻止并显示空白屏幕。

我认为原因是你在UI线程中连接蓝牙。

Android正在使用单线程模型。您永远不应该在UI线程中执行长操作。他们将阻止UI。如果UI线程被阻止超过5秒,将显示ANR对话框。您可以参考此官方文档:Threads

答案 1 :(得分:0)

我发现了这个问题,原因是我试图通过connectThread连接到蓝牙。删除连接线是神奇的,这是工作代码:

public class BluetoothDeviceConnector : IDeviceConnector
{
    private const string Tag = nameof(BluetoothDeviceConnector);

    private const int StateNone = 0; // we're doing nothing
    private const int StateConnecting = 2; // now initiating an outgoing connection
    private const int StateConnected = 3; // now connected to a remote device

    protected readonly BluetoothAdapter BluetoothAdapter;
    private readonly IMessageHandler _handler;
    private readonly string _mAddress;
    private ConnectThread _mConnectThread;
    private ConnectedThread _mConnectedThread;
    private int _mState;
    private readonly ILog _log;

    ///<summary>
    /// Prepare a new Bluetooth session.
    /// @param handler A Handler to send messages back to the UI Activity
    ///</summary>

    public BluetoothDeviceConnector(IMessageHandler handler, string address, ILog log)
    {
        _log = log;
        BluetoothAdapter = BluetoothAdapter.DefaultAdapter;
        _mState = StateNone;
        _handler = handler;
        _mAddress = address;
    }

    /// <summary>
    /// Set the current state of the connection
    /// @param state An integer defining the current connection state
    /// </summary>

    [MethodImpl(MethodImplOptions.Synchronized)]
    private void SetState(int state)
    {
        _log.Info(Tag + " setState() " + _mState + " -> " + state);
        _mState = state;
    }

    private BluetoothAdapter GetBluetoothAdapter()
    {
        return BluetoothAdapter.DefaultAdapter;
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void Connect()
    {
        var device = GetBluetoothAdapter().GetRemoteDevice(_mAddress);
        Connect(device);
    }

    ///<summary>
    /// Start the ConnectThread to initiate a connection to a remote device.
    /// @param device The BluetoothDevice to connect
    /// </summary>

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void Connect(BluetoothDevice device)
    {
        _log.Info(Tag + " connecting to: " + device);

        // Cancel any thread attempting to make a connection
        if (_mState == StateConnecting)
        {
            if (_mConnectThread != null)
            {
                _mConnectThread.Cancel();
                _mConnectThread = null;
            }
        }

        // Cancel any thread currently running a connection
        if (_mConnectedThread != null)
        {
            _mConnectedThread.Cancel();
            _mConnectedThread = null;
        }

        // Start the thread to connect with the given device
        try
        {
            _mConnectThread = new ConnectThread(device, this);
            _mConnectThread.Start();
            SetState(StateConnecting);
            _handler.SendConnectingTo(device.Name);
        }
        catch (SecurityException e)
        {

            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
        catch (IllegalArgumentException e)
        {
            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
        catch (NoSuchMethodException e)
        {
            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
        catch (IllegalAccessException e)
        {
            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
        catch (InvocationTargetException e)
        {
            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
        catch (Exception e)
        {
            _log.Error(Tag + " Connect(BluetoothDevice device) :", e);
        }
    }

    ///<summary>
    /// Start the ConnectedThread to begin managing a Bluetooth connection
    /// @param socket The BluetoothSocket on which the connection was made
    /// @param device The BluetoothDevice that has been connected
    /// </summary>

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void Connected(BluetoothSocket socket, BluetoothDevice device)
    {
        _log.Info(Tag + " connected");

        // Cancel the thread that completed the connection
        if (_mConnectThread != null)
        {
            _mConnectThread.Cancel();
            _mConnectThread = null;
        }

        // Cancel any thread currently running a connection
        if (_mConnectedThread != null)
        {
            _mConnectedThread.Cancel();
            _mConnectedThread = null;
        }

        // Start the thread to manage the connection and perform transmissions
        _mConnectedThread = new ConnectedThread(socket, this);
        _mConnectedThread.Start();

        SetState(StateConnected);
        _handler.SendConnectedTo(device.Name);
    }

    ///<summary>
    /// Stop all threads
    /// </summary>

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void Disconnect()
    {
        _log.Info(Tag + " Disconnect");

        if (_mConnectThread != null)
        {
            _mConnectThread.Cancel();
            _mConnectThread = null;
        }

        if (_mConnectedThread != null)
        {
            _mConnectedThread.Shutdown();
            _mConnectedThread.Cancel();
            _mConnectedThread = null;
        }

        SetState(StateNone);
        _handler.SendNotConnected();
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public void SendAsciiMessage(string chars)
    {
        //Write((chars + "\n").GetBytes());
    }

    ///<summary>
    /// Write to the ConnectedThread in an unsynchronized manner
    /// @param out The bytes to write
    /// @see ConnectedThread#Write(byte[])
    /// </summary>

    private void Write(byte[] value)
    {
        // Create temporary object

        // Synchronize a copy of the ConnectedThread
        if (_mState != StateConnected) return;

        // Perform the write unsynchronized
        Task.Run(() =>
        {
            _mConnectedThread.Write(value);
        });
    }

    ///<summary>
    /// Indicate that the connection attempt failed and notify the UI Activity.
    /// </summary>
    private void ConnectionFailed()
    {
        SetState(StateNone);
        _handler.SendConnectionFailed();
        _log.Info(Tag + " ConnectionFailed");
    }

    ///<summary>
    /// Indicate that the connection was lost and notify the UI Activity.
    /// </summary>

    private void ConnectionLost()
    {
        SetState(StateNone);
        _handler.SendConnectionLost();
        _log.Info(Tag + " ConnectionLost");
    }

    /// <summary>
    /// This thread runs while attempting to make an outgoing connection
    /// with a device. It runs straight through; the connection either
    /// succeeds or fails.
    /// SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
    /// </summary>
    private class ConnectThread : Thread
    {
        private readonly BluetoothSocket _mmSocket;
        private readonly BluetoothDevice _mmDevice;
        private readonly BluetoothDeviceConnector _deviceConnector;
        //public ISharedPreferences prefs = Application.Context.GetSharedPreferences("Aglive_SharedPreferences", FileCreationMode.Private);


        public ConnectThread(BluetoothDevice device, BluetoothDeviceConnector deviceConnector)
        {
            _mmDevice = device;
            BluetoothSocket tmp = null;
            _deviceConnector = deviceConnector;

            _deviceConnector._log.Info(Tag + " calling device.createRfcommSocket with channel 1 ...");

            try
            {
                //tmp = device.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805F9B34FB"));
                //tmp = device.CreateRfcommSocketToServiceRecord(device.GetUuids()[0].Uuid);
                deviceConnector.BluetoothAdapter.CancelDiscovery();
                var createRfcommSocket = JNIEnv.GetMethodID(device.Class.Handle, "createInsecureRfcommSocket", "(I)Landroid/bluetooth/BluetoothSocket;");
                var socket = JNIEnv.CallObjectMethod(device.Handle, createRfcommSocket, new JValue(1));
                tmp = GetObject<BluetoothSocket>(socket, JniHandleOwnership.TransferLocalRef);
                _deviceConnector._log.Info(Tag + " calling device.createRfcommSocket with channel 2 ...");
                var uuidList = device.GetUuids();
                if (uuidList != null)
                {
                    int count = 0;
                    while(count < 10)//true)//10 attempts
                    //foreach (var uuid in uuidList)
                    {
                        try
                        {
                            //_deviceConnector._log.Info(Tag + " connect with uuid: " + uuid);
                            //tmp = device.CreateInsecureRfcommSocketToServiceRecord(uuid.Uuid);
                            // tmp = (BluetoothSocket)device.Class.GetMethod("createRfcommSocket", new Class[] { }).Invoke(device,1);
                            //if (BluetoothDevice.DeviceTypeLe == device.GetType())
                            //{.

                            if ((int)Build.VERSION.SdkInt >= 10)
                            {
                                try
                                {
                                    Method m = device.Class.GetMethod("createRfcommSocket", new Class[] { Integer.Type });
                                    tmp = (BluetoothSocket)m.Invoke(device, 1);
                                }
                                catch (Exception e)
                                {
                                    //Log.e(TAG, "Could not create Insecure RFComm Connection",e);
                                }
                            }
                            if (isconnected.isConnected != true)
                            {
                                tmp.Connect();
                                isconnected.isConnected = true;
                            }
                            else
                            {
                                break;
                            }
                            //}
                            _deviceConnector._log.Info(Tag + " connect with uuid status: " + tmp.IsConnected);
                            if (tmp.IsConnected)
                            {

                                //_deviceConnector._log.Info(Tag + " uuid success " + uuid);
                                break;
                            }
                            //ISharedPreferencesEditor editor = prefs.Edit();
                            //editor.PutBoolean("isConnected", tmp.IsConnected);
                            //editor.Apply();
                        }
                        catch (Exception e)
                        {
                            // ignored
                        }
                        count++;
                    }
                }

                _deviceConnector._log.Info(Tag + " setting socket to result of createRfcommSocket");
                _deviceConnector._log.Info(Tag + " setting socket Status" + tmp.IsConnected);
            }
            catch (Exception e)
            {
                _deviceConnector._log.Error(Tag + " ConnectThread", e);
            }
            _mmSocket = tmp;
        }

        public override void Run()
        {
            base.Run();
            _deviceConnector._log.Info(Tag + " BEGIN mConnectThread");
            //setName("ConnectThread");

            // Always cancel discovery because it will slow down a connection
            _deviceConnector.BluetoothAdapter.CancelDiscovery();

            // Make a connection to the BluetoothSocket
            try
            {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                _deviceConnector._log.Info(Tag + " Run() => " + _mmSocket.IsConnected);
                if (!_deviceConnector.BluetoothAdapter.IsDiscovering && !_mmSocket.IsConnected)
                {
                    _deviceConnector._log.Info(Tag + " BEGIN mConnectThread 1");
                    _mmSocket.Connect();
                    _deviceConnector._log.Info(Tag + " BEGIN mConnectThread 2");
                }
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " ConnectThread => Run Function", e);
                _deviceConnector.ConnectionFailed();
                try
                {
                    _mmSocket.Close();
                }
                catch (IOException e2)
                {
                    _deviceConnector._log.Error(Tag + " unable to close() socket during connection failure", e2);
                }
                return;
            }

            // Reset the ConnectThread because we're done
            _deviceConnector._mConnectThread = null;

            // Start the connected thread
            _deviceConnector.Connected(_mmSocket, _mmDevice);
            _deviceConnector._log.Info(Tag + " END mConnectThread");
        }

        [Obsolete("deprecated")]
        public override void Destroy()
        {
            try
            {
                _deviceConnector._log.Info(Tag + " Destory()");
                _mmSocket?.Close();
                _deviceConnector._log.Info(Tag + " Destroy");
                base.Destroy();
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " close() of connect socket failed", e);
            }
        }

        public void Cancel()
        {
            try
            {
                _deviceConnector._log.Info(Tag + " Cancel()");
                _mmSocket?.Close();
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " close() of connect socket failed", e);
            }
        }
    }

    ///<summary>
    /// This thread runs during a connection with a remote device.
    /// It handles all incoming and outgoing transmissions.
    /// </summary>
    private class ConnectedThread : Thread
    {
        private readonly BluetoothSocket _mmSocket;
        private readonly Stream _mmInStream;
        private readonly Stream _mmOutStream;
        private readonly BluetoothDeviceConnector _deviceConnector;

        public ConnectedThread(BluetoothSocket socket, BluetoothDeviceConnector deviceConnector)
        {
            _deviceConnector = deviceConnector;
            _mmSocket = socket;
            _deviceConnector._log.Info(Tag + " create ConnectedThread");
            // Get the BluetoothSocket input and output streams
            try
            {
                _mmInStream = _mmSocket?.InputStream;
                _mmOutStream = _mmSocket?.OutputStream;
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " temp sockets not created", e);
            }
        }

        private bool _stop;
        private readonly bool _hasReadAnything = false;

        public void Shutdown()
        {
            _stop = true;
            if (!_hasReadAnything) return;

            try
            {
                _deviceConnector._log.Info(Tag + " Shutdown ConnectedThread");
                _mmInStream?.Close();
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " close() of InputStream failed.", e);
            }
        }

        public override void Run()
        {
            base.Run();
            _deviceConnector._log.Info(Tag + " BEGIN mConnectedThread");

            var reader = new Java.IO.BufferedReader(new Java.IO.InputStreamReader(_mmInStream));

            while (!_stop)
            {
                try
                {
                    var rfid = reader.ReadLine();
                    if (!string.IsNullOrEmpty(rfid?.Trim()))
                    {
                        _deviceConnector._handler.SendLineRead(rfid);
                    }
                }
                catch (IOException e)
                {
                    _deviceConnector._log.Error(Tag + " disconnected", e);
                    _deviceConnector.ConnectionLost();
                    break;
                }
            }
        }

        ///<summary>
        /// Write to the connected OutStream.
        /// @param bytes The bytes to write
        /// </summary>

        public void Write(byte[] bytes)
        {
            try
            {
                _mmOutStream.Write(bytes, 0, bytes.Length);
                _deviceConnector._handler.SendBytesWritten(bytes);
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " Exception during write", e);
            }
        }

        public void Cancel()
        {
            try
            {
                _deviceConnector._log.Error(Tag + " ConnectedThread() => Cancel()");
                _mmInStream.Close();
                _mmOutStream.Close();
                _mmSocket?.Close();
            }
            catch (IOException e)
            {
                _deviceConnector._log.Error(Tag + " close() of connect socket failed", e);
            }
        }
    }
}

public static class isconnected
{
    public static bool isConnected { get; set; }
}