我遇到的问题是,在不使用线程的情况下,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;
}
}
答案 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; }
}