Strange issue with Bluetooth connectivity in android - android

I have a requirement of connecting to a bluetooth scanner from my android application. After it is connected the scanned RFID's will be added to local database.
The problem here is that the bluetooth scanner does not connect at times not sure when it fails to connect as there is no definite pattern to fail.
And at times it connects but does not read any RFID's. cannot figure out whay it fails. I only get one exception message
"read failed, socket might closed or timeout, read ret: -1"
Here is the code of BluetoothDeviceConnector:
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 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)
{
foreach (var uuid in uuidList)
{
try
{
_deviceConnector._log.Info(Tag + " connect with uuid: " + uuid);
tmp = device.CreateInsecureRfcommSocketToServiceRecord(uuid.Uuid);
tmp.Connect();
_deviceConnector._log.Info(Tag + " connect with uuid status: " + tmp.IsConnected);
if (tmp.IsConnected)
{
_deviceConnector._log.Info(Tag + " uuid success " + uuid);
break;
}
}
catch (Exception ex)
{
// ignored
}
}
}
_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()");
_mmSocket?.Close();
}
catch (IOException e)
{
_deviceConnector._log.Error(Tag + " close() of connect socket failed", e);
}
}
}
}
Can anybody please help me in figuring the issue, as the main function of the app I am working on is to connect to scanner and scan the RFID's.

Try changing your tmp = device.CreateInsecureRfcommSocketToServiceRecord(uuid.Uuid); to tmp = device.CreateRfcommSocketToServiceRecord(uuid.Uuid);

Related

UI blocks while connecting to Bluetooth scanner

I am facing a issue where in instead of using a thread the UI is blocked and shows blank screen. Here I am trying to connect to bluetooth scanner LPR device using my code but it somehow blocks the UI while it is connecting, which is little annoying. I tried to show toast which I thought will notify user while connecting. But no luck with that, it still shows blank screen till it connects and once its connected it shows connecting message.
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; }
}
Activity from where I am trying to connect to scanner:
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;
}
}
I am facing a issue where in instead of using a thread the UI is blocked and shows blank screen.
I think the reason is that you connect the Bluetooth in the UI thread.
Android is using single thread model.You should never perform long operations in the UI thread. They will block the UI. If the UI thread is blocked for more than 5 seconds, the ANR dialog will be shown. You could refer to this official documentation : Threads.
I found the issue, It was because I was trying to connect to Bluetooth from connectThread. Removing the connecting line did the magic, here is the working code:
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; }
}

BluetoothSocket not connecting to target device

I'm trying to connect my device to another one via Bluetooth, but when I select the device I want to connect with, I get an IOException saying
read failed, socket might closed or timeout, read ret: -1
Just to illustrate how my app works, I have a RecyclerView populated with the devices my Bluetooth scan has found, then when I click an item the app is supposed to connect with that device.
Below is my the code for my connection thread:
private val MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb")
private lateinit var device: BluetoothDevice
private lateinit var onDeviceActionListener: OnDeviceActionListener
private lateinit var socket: BluetoothSocket
fun init(device: BluetoothDevice,
onDeviceActionListener: OnDeviceActionListener): ConnectionThread {
this.device = device
this.onDeviceActionListener = onDeviceActionListener
try {
socket = device.createRfcommSocketToServiceRecord(MY_UUID)
} catch (e: IOException) {
Log.e(TAG, "Error creating socket", e)
}
return this
}
override fun run() {
try {
socket.connect()
} catch (openException: IOException) {
Log.e(TAG, "Error opening connection. Trying to close...", openException)
try {
socket.close()
} catch (closeException: IOException) {
Log.e(TAG, "Error closing socket", closeException)
}
return
}
onDeviceActionListener.onDeviceConnect(device)
}
My guess is there is something wrong with my UUID. I've tried some other values but still didn't work.
Any help will be much appreciated.
Well, I don't see exactly what you are doing wrong here. However, I have done quite a bit of Bluetooth work. More recently just focused in BLE. You should be able to discover your nearby BT devices and see their UUIDs.
I have written a helper class about 3 years ago so it's a little old, but should be mostly the same code. Happy to share it with you if it helps.
public class BluetoothConnector {
private static final String TAG = Globals.SEARCH_STRING + BluetoothConnector.class.getSimpleName();
private static final String DEFAULT_SERVER_NAME_FOR_APP = "tn_bt_default_server";
private static final int DEFAULT_DISCOVERABLE_DURATION_MS = 30000;
private static final UUID DEFAULT_UUID = UUID.fromString("6534c201-039c-4e4f-89f9-5ca8cfeb9667");
public static final int ENABLE_DISCOVER_INTENT = 1002;
protected boolean mIsToastEnabled = false; //Access from calling class to enable toasting of progress to screen if necessary
private Handler mUIHandler;
private static ServerSocketThread mServerSocketThread;
private static ClientSocketThread mClientSocketThread;
private ManageConnectionThread mManageConnectionThread;
private Context mContext;
private IBluetoothDataListener mBluetoothDataListener;
public final Object ServerSocketLock = new Object();
public final Object ClientSocketLock = new Object();
public final Object ManageConnectionLock = new Object();
public BluetoothConnector(Context context, IBluetoothDataListener listener){
this(context, new Handler(Looper.getMainLooper()), listener);
}
public BluetoothConnector(Context context, Handler UIHandler, IBluetoothDataListener listener){
Log.v(TAG, "BluetoothConnector(context=" + context + ", Handler=" + UIHandler.getClass().getSimpleName() + ", IBluetoothDataListener=" + listener.getClass().getSimpleName());
mContext = context;
mUIHandler = UIHandler;
mBluetoothDataListener = listener;
}
public void makeThisDeviceDiscoverable(Activity callingActivity){
makeThisDeviceDiscoverable(callingActivity, BluetoothAdapter.getDefaultAdapter(), DEFAULT_DISCOVERABLE_DURATION_MS);
}
public void makeThisDeviceDiscoverable(Activity callingActivity, BluetoothAdapter adapter){
makeThisDeviceDiscoverable(callingActivity, adapter, DEFAULT_DISCOVERABLE_DURATION_MS);
}
public void makeThisDeviceDiscoverable(Activity callingActivity, int durationInMs){
makeThisDeviceDiscoverable(callingActivity, BluetoothAdapter.getDefaultAdapter(), durationInMs);
}
public void makeThisDeviceDiscoverable(Activity callingActivity, BluetoothAdapter adapter, int durationInMs) {
Log.v(TAG, "makeThisDeviceDiscoverable(callingActivity=" + callingActivity.getClass().getSimpleName() + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()) + ", duration=" + String.valueOf(durationInMs));
if(adapter == null){
Log.v(TAG, "adapter is null");
}else if(adapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Log.v(TAG, "Launching Activity to request Discoverable Permission");
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, durationInMs);
callingActivity.startActivityForResult(discoverableIntent, ENABLE_DISCOVER_INTENT);
}else{
Log.v(TAG, "adapter is already in SCAN MODE");
}
}
public void awaitConnectionFromDevice(){
awaitConnectionFromDevice(DEFAULT_UUID, BluetoothAdapter.getDefaultAdapter());
}
public void awaitConnectionFromDevice(UUID commonKey){
awaitConnectionFromDevice(commonKey, BluetoothAdapter.getDefaultAdapter());
}
public void awaitConnectionFromDevice(BluetoothAdapter adapter){
awaitConnectionFromDevice(DEFAULT_UUID, adapter);
}
public void awaitConnectionFromDevice(UUID commonKey, BluetoothAdapter adapter){
Log.v(TAG, "awaitConnectionFromDevice for UUID: " + String.valueOf(commonKey) + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()));
cancelDiscovery();
synchronized (ServerSocketLock){
if(mServerSocketThread != null){
Log.v(TAG, "Server Socket Thread was not null so canceling current Thread");
mServerSocketThread.cancel();
}
Log.v(TAG, "Attempting to Start new ServerThread");
mServerSocketThread = new ServerSocketThread(commonKey, adapter);
mServerSocketThread.start();
}
}
public void cancelAwaitingConnectionFromDevice(){
Log.v(TAG, "cancelAwaitingConnectionFromDevice");
synchronized (ServerSocketLock){
if(mServerSocketThread != null){
mServerSocketThread.cancel();
mServerSocketThread = null;
Log.v(TAG, "canceling Server Socket Thread");
}else{
Log.v(TAG, "Server Socket null, so not canceling");
}
}
}
public void startDiscovery() {
startDiscovery(BluetoothAdapter.getDefaultAdapter());
}
public void startDiscovery(BluetoothAdapter adapter){
Log.v(TAG, "startDiscovery to find list of devices in range");
adapter.startDiscovery();
}
public void cancelDiscovery() {
cancelDiscovery(BluetoothAdapter.getDefaultAdapter());
}
public void cancelDiscovery(BluetoothAdapter adapter){
Log.v(TAG, "cancelDiscovery");
adapter.cancelDiscovery();
}
public void connectToDevice(BluetoothDevice device){
connectToDevice(device, DEFAULT_UUID);
}
public void connectToDevice(BluetoothDevice device, UUID commonKey){
Log.v(TAG, "connectToDevice(BluetoothDevice=" + (device == null ? "null" : device.getName()) + ", UUID=" + String.valueOf(commonKey));
synchronized (ClientSocketLock){
if(mClientSocketThread != null){
Log.v(TAG, "Client Socket Thread was not null so canceling current Thread");
mClientSocketThread.cancel();
}else{
Log.v(TAG, "Client Socket Thread is NULL so not canceling");
}
Log.v(TAG, "ClientSocketThread Starting");
mClientSocketThread = new ClientSocketThread(device, commonKey);
mClientSocketThread.start();
}
}
public BluetoothDevice getBluetoothDeviceByMac(String mac){
Log.v(TAG, "getBluetoothDeviceByMac(mac=" + mac);
return getBluetoothDeviceByMac(mac, BluetoothAdapter.getDefaultAdapter());
}
public BluetoothDevice getBluetoothDeviceByMac(String mac, BluetoothAdapter adapter) {
Log.v(TAG, "getBluetoothDeviceByMac(mac=" + mac + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()));
return adapter.getRemoteDevice(mac);
}
public ArrayList<KeyValueModel> getPairedDevices(){
return getPairedDevices(BluetoothAdapter.getDefaultAdapter());
}
public ArrayList<KeyValueModel> getPairedDevices(BluetoothAdapter adapter){
ArrayList<KeyValueModel> bondedDevices = new ArrayList<KeyValueModel>();
Set<BluetoothDevice> pairedDevices = adapter.getBondedDevices();
Log.v(TAG, "getPairedDevices Found " + pairedDevices.size() + " number of paired devices");
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
bondedDevices.add(new KeyValueModel(device.getAddress(), device.getName()));
}
}
return bondedDevices;
}
public static void unpairDevice(BluetoothDevice device){
Log.v(TAG, "unpairDevice");
try{
Method method = device.getClass().getMethod("removeBond", (Class[]) null);
method.invoke(device, (Object[]) null);
}catch (Exception ex){
Log.e(TAG, "Error Unpairing Device: " + ex.getMessage());
}
}
public boolean sendDataToConnectedDevice(byte[] data){
Log.v(TAG, "sendDataToConnectedDevice");
synchronized (ManageConnectionLock){
mManageConnectionThread.write(data);
return true;
}
}
public void setBluetoothDataListener(IBluetoothDataListener listener){
mBluetoothDataListener = listener;
}
public boolean getIsConnected(){
synchronized (ManageConnectionLock) {
return mManageConnectionThread != null && mManageConnectionThread.isAlive();
}
}
private void startManageConnectionThread(BluetoothSocket socket){
Log.v(TAG, "startManageConnectionThread for Socket: " + (socket == null ? "null" : socket.getClass().getSimpleName()));
synchronized (ManageConnectionLock) {
mManageConnectionThread = new ManageConnectionThread(socket);
mManageConnectionThread.start();
}
}
private void handleDataReceivedFromConnectedDevice(final byte[] bytes){
Log.v(TAG, "handleDataReceivedFromConnectedDevice");
Log.v(TAG, "bytes to Listener: " + new String(bytes));
if(mUIHandler != null && mBluetoothDataListener != null){
mUIHandler.post(new Runnable() {
#Override
public void run() {
if (mBluetoothDataListener != null) {
mBluetoothDataListener.onReceivedPayloadFromConnectedDevice(bytes);
}
}
});
}else{
Log.v(TAG, "UIHandler was null so skipped sending payload to listener");
}
}
private void handleConnected(){
Log.e(TAG, "handleConnected");
if(mUIHandler != null && mBluetoothDataListener != null){
mUIHandler.post(new Runnable() {
#Override
public void run() {
if(mBluetoothDataListener != null){
mBluetoothDataListener.onConnectedToTargetDevice();
}
}
});
}else{
Log.v(TAG, "UIHandler was null so skipped sending payload to listener");
}
}
private void handleDisconnected(){
Log.e(TAG, "handleDisconnected");
if(mUIHandler != null && mBluetoothDataListener != null){
mUIHandler.post(new Runnable() {
#Override
public void run() {
if(mBluetoothDataListener != null){
mBluetoothDataListener.onDisconnectedFromTargetDevice();
}
}
});
}else{
Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");
}
}
private void handleFailedToConnectAsServer(final Exception ex){
Log.e(TAG, "handleFailedToConnectAsServer ex: " + ex.getMessage());
if(mUIHandler != null && mBluetoothDataListener != null){
mUIHandler.post(new Runnable() {
#Override
public void run() {
if(mBluetoothDataListener != null){
mBluetoothDataListener.onFailedToReceiveConnectionFromTargetDevice(ex);
}
}
});
}else{
Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");
}
}
private void handleFailedToConnectAsClient(final Exception ex){
Log.e(TAG, "handleFailedToConnectAsClient ex: " + ex.getMessage());
if(mUIHandler != null && mBluetoothDataListener != null){
mUIHandler.post(new Runnable() {
#Override
public void run() {
if(mBluetoothDataListener != null){
mBluetoothDataListener.onFailedToConnectToTargetDevice(ex);
}
}
});
}else{
Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");
}
}
private void handleErrorInRetrievingData(final Exception ex){
Log.e(TAG, "handleErrorInRetrievingData ex: " + ex.getMessage());
if(mUIHandler != null && mBluetoothDataListener != null){
mUIHandler.post(new Runnable() {
#Override
public void run() {
if(mBluetoothDataListener != null){
mBluetoothDataListener.onErrorReceivingPayloadFromConnectedDevice(ex);
}
}
});
}else{
Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");
}
}
private void handleFailedToSendDataToConnectedDevice(final Exception ex){
Log.e(TAG, "handleFailedToSendDataToConnectedDevice ex: " + ex.getMessage());
if(mUIHandler != null && mBluetoothDataListener != null){
mUIHandler.post(new Runnable() {
#Override
public void run() {
if(mBluetoothDataListener != null){
mBluetoothDataListener.onFailedToSendDataToConnectedDevice(ex);
}
}
});
}else{
Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");
}
}
private void toastMessage(final String value){
if(!mIsToastEnabled || mUIHandler == null) {
return;
}
mUIHandler.post(new Runnable() {
#Override
public void run() {
try{
Toast.makeText(mContext, value, Toast.LENGTH_SHORT).show();
}catch(Exception ex){
Log.v(TAG, "Error Toasting, possibly bad handler, or context: " + ex.getMessage());
}
}
});
}
private class ServerSocketThread extends Thread{
private final String TAG = Globals.SEARCH_STRING + ServerSocketThread.class.getSimpleName();
private final BluetoothServerSocket mServerSocket;
public ServerSocketThread(UUID commonKey, BluetoothAdapter adapter) {
Log.v(TAG, "ServerSocketThread Constructor");
BluetoothServerSocket tmp = null;
try {
Log.v(TAG, "listening for RFComas Server: " + DEFAULT_SERVER_NAME_FOR_APP + ", and commonKey: " + String.valueOf(commonKey));
// MY_UUID is the app's UUID string, also used by the client code
tmp = adapter.listenUsingRfcommWithServiceRecord(DEFAULT_SERVER_NAME_FOR_APP, commonKey);
toastMessage("Listening for RFComm As Server on UUID: " + String.valueOf(commonKey));
} catch (IOException e) {
Log.e(TAG, "Error creating ServerSocket: " + e.getMessage());
toastMessage("Error Creating ServerSocket: " + e.getMessage());
}
mServerSocket = tmp;
}
public void run() {
Log.v(TAG, "ServerSocket run");
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (mServerSocket != null) {
try {
Log.v(TAG, "ServerSocket.accept()");
toastMessage("ServerSocket.accept()");
//Waits for Client Connection to pass Socket, then we close down
socket = mServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "ServerSocket.accept() Error: " + e.getMessage());
toastMessage("ServerSocket.accept() Error: " + e.getMessage());
handleFailedToConnectAsServer(e);
break;
}
// If a connection was accepted we don't need to keep server listening, so close unless multiple client/server connections is desired
if (socket != null) {
try{
Log.v(TAG, "ServerSocket Accepted Client Socket, Begin Listening Connect Thread");
toastMessage("ServerSocket Accepted Client Socket, Begin Listening Connect Thread");
// Do work to manage the connection (in a separate thread)
startManageConnectionThread(socket);
//mServerSocket.close();
}catch(Exception ex){
Log.e(TAG, "Exception closing Server Socket");
}
//break; //Add in Break if you want to shut down listening for connections
}else{
Log.v(TAG, "Socket wasn't accepted");
toastMessage("Socket wasn't accepted");
handleFailedToConnectAsServer(new Exception("Socket is Null"));
}
}
Log.v(TAG, "Exiting Server Accept Thread");
}
public void cancel() {
try {
Log.v(TAG, "ServerSocketThread Canceled");
mServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "ServerSocketThread Error: " + e.getMessage());
}
}
}
private class ClientSocketThread extends Thread{
private BluetoothSocket mSocket;
private final BluetoothDevice mDevice;
public ClientSocketThread(BluetoothDevice device, UUID commonKey) {
Log.v(TAG, "ClientSocketThread Constructor");
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
Log.v(TAG, "Client creating RFComm Socket to Server with UUID: " + String.valueOf(commonKey));
toastMessage("Client creating RFComm Socket to Server with UUID: " + String.valueOf(commonKey));
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(commonKey);
} catch (IOException e) {
Log.e(TAG, "Error creating Client Socket: " + e.getMessage());
toastMessage("Creating Socket Exception: " + e.getMessage());
handleFailedToConnectAsClient(e);
}
mSocket = tmp;
}
public void run() {
try {
if(mSocket == null){
Log.e(TAG, "Error Client Socket is Null, Canceling Client Thread");
return;
}
Log.v(TAG, "Client Connecting");
// Connect to the server, or timeout eventually
toastMessage("Client Connecting");
mSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and try the fallback method of reflection with port to connect
try {
Log.e("", "trying fallback...");
toastMessage("Client Connection Failed Exception: " + connectException.getMessage());
mSocket = (BluetoothSocket) mDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(mDevice, 1);
toastMessage("Client Connect Again Attempt 2, but with fall back Reflection and port");
Log.v(TAG, "Client Connect Again Attempt 2, but with fall back Reflection and port");
mSocket.connect();
Log.e("", "Connected");
toastMessage("Client Connected");
} catch (Exception ex) {
Log.e("", "Couldn't establish Bluetooth connection!");
toastMessage("Client Couldn't Establish Connection to Server: " + ex.getMessage());
handleFailedToConnectAsClient(ex);
return;
}
}
// Do work to manage the connection (in a separate thread)
startManageConnectionThread(mSocket);
}
public void cancel() {
try {
Log.v(TAG, "Client Socket cancel");
mSocket.close();
} catch (IOException e) {
Log.e(TAG, "Error Closing Socket");
}
}
}
private class ManageConnectionThread extends Thread {
/////////////
// MEMBERS //
/////////////
private final String TAG = Globals.SEARCH_STRING + ManageConnectionThread.class.getSimpleName();
private final BluetoothSocket mSocket;
private final InputStream mInStream;
private final OutputStream mOutStream;
//////////////////
// CONSTRUCTOR //
//////////////////
public ManageConnectionThread(BluetoothSocket socket) {
mSocket = socket;
handleConnected();
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
try {
Log.v(TAG, "ManageConnectionThread Constructor");
Log.v(TAG, "Connected to Socket = " + String.valueOf(socket.isConnected()));
toastMessage("Listening for input or output Stream");
Log.v(TAG, "Get InputStream");
tmpIn = socket.getInputStream();
Log.v(TAG, "Get OutputStream");
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "Error getting Socket Streams: " + e.getMessage());
toastMessage("Connect Thread: Error: " + e.getMessage());
handleErrorInRetrievingData(e);
}
mInStream = tmpIn;
mOutStream = tmpOut;
}
///////////////
// OVERRIDES //
///////////////
public void run() {
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
byte[] data = new byte[16384];
int nRead;
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
while ((nRead = mInStream.read(data, 0, data.length)) != -1) {
//Log.v(TAG, "bytes Read: " + String.valueOf(nRead));
buffer.write(data, 0, nRead);
//TODO Find better way to find End Of Message rather than looking for }
String temp = new String(buffer.toByteArray());
//Log.v(TAG, "current Data: " + temp);
if(temp.contains("}")){
Log.v(TAG, "bytes reading complete");
handleDataReceivedFromConnectedDevice(buffer.toByteArray());
buffer.flush();
buffer = new ByteArrayOutputStream();
}else{
Log.v(TAG, "More bytes Available");
}
}
} catch (IOException e) {
Log.e(TAG, "Error reading inputStream");
handleErrorInRetrievingData(e);
break;
}
}
Log.v(TAG, "Exiting Managed Connection Thread");
handleDisconnected();
}
/////////////
// METHODS //
/////////////
public void write(byte[] bytes) {
try {
Log.v(TAG, "ManageConnectionThread write(bytes)");
mOutStream.write(bytes);
} catch (IOException e) {
Log.e(TAG, "Error Writing Stream: " + e.getMessage());
handleFailedToSendDataToConnectedDevice(e);
}
}
public void cancel() {
try {
Log.v(TAG, "ManageConnectionThread cancel");
handleDisconnected();
mSocket.close();
} catch (IOException e) {
Log.e(TAG, "Error Closing BluetoothSocket: " + e.getMessage());
}
}
}
public interface IBluetoothDataListener{
//////////////////////
// OVERRIDE METHODS //
//////////////////////
void onReceivedPayloadFromConnectedDevice(byte[] payload);
void onErrorReceivingPayloadFromConnectedDevice(Exception ex);
void onFailedToConnectToTargetDevice(Exception ex);
void onFailedToReceiveConnectionFromTargetDevice(Exception ex);
void onFailedToSendDataToConnectedDevice(Exception ex);
void onConnectedToTargetDevice();
void onDisconnectedFromTargetDevice();
}
}
Then of course you will want to make sure you have your broadcast receivers setup:
<receiver
android:name=".receivers.BluetoothChangedReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
<action android:name="android.bluetooth.adapter.action.SCAN_MODE_CHANGED" />
<action android:name="android.bluetooth.adapter.action.DISCOVERY_STARTED" />
<action android:name="android.bluetooth.adapter.action.DISCOVERY_FINISHED" />
<action android:name="android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED" />
<action android:name="android.bluetooth.device.action.FOUND" />
<action android:name="android.bluetooth.device.action.DISAPPEARED" />
</intent-filter>
</receiver>
<receiver
android:name=".receivers.BluetoothDeviceReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.bluetooth.device.action.FOUND" />
<action android:name="android.bluetooth.device.action.DISAPPEARED" />
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
<action android:name="android.bluetooth.device.action.ACTION_ACL_DISCONNECT_REQUESTED" />
<action android:name="android.bluetooth.device.action.BOND_STATE_CHANGED" />
<action android:name="android.bluetooth.device.action.UUID" />
</intent-filter>
</receiver>

Android Bluetooth do not connect

I am creating an application that connects via bluetooth to a custom hardware device that uses the SPP protocol. The problem is that I can't connect with the device. Before testing it I tried:
connect with my application to another phone that write me with via a bluetooth chat application;
connect the custom device with a bluetooth terminal application: https://play.google.com/store/apps/details?id=Qwerty.BluetoothTerminal
Both tests were successful, but when I tried to connect the custom device with my application the connect procedure get the exception
IOException: read failed, socket might closed
I searched everywhere, but I couldn't find anything that makes the app connect the device. In particular I read:
IOException: read failed, socket might closed - Bluetooth on Android 4.3
Android Bluetooh Socket IOException: 'read failed, socket might be closed or timeout'
Here is the class that I use to connect, in particular I think that the error is in the subclass connectThread (the method that return the exception is mmSocket.connect()) which is in the second half of the code.
public class BluetoothChatService {
// Debugging
private static final String TAG = "BluetoothChatService";
// Name for the SDP record when creating server socket
private static final String NAME_SECURE = "BluetoothChatSecure";
private static final String NAME_INSECURE = "BluetoothChatInsecure";
// Unique UUID for this application
private static final UUID MY_UUID_SECURE =
UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final UUID MY_UUID_INSECURE =
UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mSecureAcceptThread;
private AcceptThread mInsecureAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;
private int mNewState;
// Constants that indicate the current connection state
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_LISTEN = 1; // now listening for incoming connections
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
/**
* Constructor. Prepares a new BluetoothChat session.
*
* #param context The UI Activity Context
* #param handler A Handler to send messages back to the UI Activity
*/
public BluetoothChatService(Context context, Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mNewState = mState;
mHandler = handler;
}
/**
* Update UI title according to the current state of the chat connection
*/
private synchronized void updateUserInterfaceTitle() {
mState = getState();
//Log.d(TAG, "updateUserInterfaceTitle() " + mNewState + " -> " + mState);
mNewState = mState;
// Give the new state to the Handler so the UI Activity can update
mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, mNewState, -1).sendToTarget();
}
/**
* Return the current connection state.
*/
public synchronized int getState() {
return mState;
}
/**
* Start the chat service. Specifically start AcceptThread to begin a
* session in listening (server) mode. Called by the Activity onResume()
*/
public synchronized void start() {
//Log.d(TAG, "start");
// Cancel any thread attempting to make a 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 listen on a BluetoothServerSocket
if (mSecureAcceptThread == null) {
mSecureAcceptThread = new AcceptThread(true);
mSecureAcceptThread.start();
}
if (mInsecureAcceptThread == null) {
mInsecureAcceptThread = new AcceptThread(false);
mInsecureAcceptThread.start();
}
// Update UI title
updateUserInterfaceTitle();
}
/**
* Start the ConnectThread to initiate a connection to a remote device.
*
* #param device The BluetoothDevice to connect
* #param secure Socket Security type - Secure (true) , Insecure (false)
*/
public synchronized void connect(BluetoothDevice device, boolean secure) {
//Log.d(TAG, "connect to: " + device);
// Cancel any thread attempting to make a connection
if (mState == STATE_CONNECTING) {
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
mConnectThread = new ConnectThread(device, secure);
mConnectThread.start();
// Update UI title
updateUserInterfaceTitle();
}
/**
* 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
*/
public synchronized void connected(BluetoothSocket socket, BluetoothDevice
device, final String socketType) {
//Log.d(TAG, "connected, Socket Type:" + socketType);
// 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;
}
// Cancel the accept thread because we only want to connect to one device
if (mSecureAcceptThread != null) {
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread.cancel();
mInsecureAcceptThread = null;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket, socketType);
mConnectedThread.start();
// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(Constants.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
// Update UI title
updateUserInterfaceTitle();
}
/**
* Stop all threads
*/
public synchronized void stop() {
//Log.d(TAG, "stop");
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mSecureAcceptThread != null) {
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread.cancel();
mInsecureAcceptThread = null;
}
mState = STATE_NONE;
// Update UI title
updateUserInterfaceTitle();
}
/**
* Write to the ConnectedThread in an unsynchronized manner
*
* #param out The bytes to write
* #see ConnectedThread#write(byte[])
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
/**
* Indicate that the connection attempt failed and notify the UI Activity.
*/
private void connectionFailed() {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST, "Unable to connect device");
msg.setData(bundle);
mHandler.sendMessage(msg);
mState = STATE_NONE;
// Update UI title
updateUserInterfaceTitle();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
}
/**
* Indicate that the connection was lost and notify the UI Activity.
*/
private void connectionLost() {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST, "Device connection was lost");
msg.setData(bundle);
mHandler.sendMessage(msg);
mState = STATE_NONE;
// Update UI title
updateUserInterfaceTitle();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
}
/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted
* (or until cancelled).
*/
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
private String mSocketType;
public AcceptThread(boolean secure) {
BluetoothServerSocket tmp = null;
mSocketType = secure ? "Secure" : "Insecure";
// Create a new listening server socket
try {
if (secure) {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
MY_UUID_SECURE);
} else {
tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
NAME_INSECURE, MY_UUID_INSECURE);
}
} catch (IOException e) {
//Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
}
mmServerSocket = tmp;
mState = STATE_LISTEN;
}
public void run() {
//Log.d(TAG, "Socket Type: " + mSocketType + "BEGIN mAcceptThread" + this);
setName("AcceptThread" + mSocketType);
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (IOException e) {
//Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (BluetoothChatService.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice(),
mSocketType);
break;
case STATE_NONE:
case STATE_CONNECTED:
// Either not ready or already connected. Terminate new socket.
try {
socket.close();
} catch (IOException e) {
//Log.e(TAG, "Could not close unwanted socket", e);
}
break;
}
}
}
}
//Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);
}
public void cancel() {
//Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
try {
mmServerSocket.close();
} catch (IOException e) {
//Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
}
}
}
/**
* This thread runs while attempting to make an outgoing connection
* with a device. It runs straight through; the connection either
* succeeds or fails.
*/
private class ConnectThread extends Thread {
private BluetoothSocket mmSocket;
private BluetoothDevice mmDevice;
private String mSocketType;
public ConnectThread(BluetoothDevice device, boolean secure) {
mmDevice = device;
BluetoothSocket tmp = null;
mSocketType = secure ? "Secure" : "Insecure";
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(
MY_UUID_INSECURE);
}
} catch (IOException e) {
//Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
mmSocket = tmp;
mState = STATE_CONNECTING;
}
public void run() {
//Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
setName("ConnectThread" + mSocketType);
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
}
catch (IOException e) {
e.printStackTrace();
try {
mmSocket =(BluetoothSocket) mmDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(mmDevice,1);
mmSocket.connect();
}
catch (IOException e2) {
e2.printStackTrace();
// Close the socket
try{
mmSocket.close();
}
catch(IOException e3) {
e3.printStackTrace();
}
connectionFailed();
}
catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
catch (IllegalAccessException e1) {
e1.printStackTrace();
}
catch (InvocationTargetException e1) {
e1.printStackTrace();
}
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothChatService.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice, mSocketType);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
//Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
}
}
}
/**
* This thread runs during a connection with a remote device.
* It handles all incoming and outgoing transmissions.
*/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType) {
//Log.d(TAG, "create ConnectedThread: " + socketType);
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
//Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
mState = STATE_CONNECTED;
}
public void run() {
//Log.i(TAG, "BEGIN mConnectedThread");
// Keep listening to the InputStream while connected
while (mState == STATE_CONNECTED) {
byte[] buffer = new byte[14];
byte[] out_buffer = new byte[6];
try {
// Read from the InputStream
//bytes = mmInStream.read(buffer);
buffer[0] = (byte) mmInStream.read();
if(buffer[0] == 0x53) {
for (int i = 1; i < 7; i++) {
buffer[i] = (byte) mmInStream.read();
}
}
if (buffer[1] == 0x68 && buffer[2] == 0x65 && buffer[3] == 0x6C && buffer[4] == 0x6D && buffer[5] == 0x65 && buffer[6] ==0x74) {// if i found "Shelmet"
mmInStream.read();
for (int i = 0; i < 6; i++) {
out_buffer[i] = (byte) mmInStream.read();
}
/*out_buffer[0] = buffer[8];
out_buffer[1] = buffer[9];
out_buffer[2] = buffer[10];
out_buffer[3] = buffer[11];
out_buffer[4] = buffer[12];
out_buffer[5] = buffer[13];*/
}
else {
out_buffer[0] = 0;
out_buffer[1] = 0;
out_buffer[2] = 0;
out_buffer[3] = 0;
out_buffer[4] = 0;
out_buffer[5] = 0;
}
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_READ, 6, -1, out_buffer).sendToTarget();
}
catch (IOException e) {
//Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
/**
* Write to the connected OutStream.
*
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
//Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
//Log.e(TAG, "close() of connect socket failed", e);
}
}
}
}
I connect as client and I tried both Insecure and Secure connection. I really don't know what to do.

Sharing data over bluetooth in Android

I want to create an android app where I can send and receive simple strings over bluetooth. I am connecting the 2 devices manually/beforehand i.e from the settings and now want to send and receive text. I can't find a simple code to do this.
A simple and step by step explanation of the code would be appreciated.
you can refer to bluetooth chat application from git hub .. and also google provide sample for bluetooth data transfer by using of handler in bluetooth there they use socket to set data over bluetooh please refer this link to start :
https://github.com/googlesamples/android-BluetoothChat
firstly you need bluetootchatservice.java class
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
public class BluetoothChatService {
// Debugging
private static final String TAG = "BluetoothChatService";
private static final boolean D = true;
// Name for the SDP record when creating server socket
private static final String NAME_SECURE = "BluetoothChatSecure";
private static final String NAME_INSECURE = "BluetoothChatInsecure";
// Unique UUID for this application
private static final UUID MY_UUID_SECURE =
UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final UUID MY_UUID_INSECURE =
UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mSecureAcceptThread;
private AcceptThread mInsecureAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;
// Constants that indicate the current connection state
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_LISTEN = 1; // now listening for incoming connections
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
/**
* Constructor. Prepares a new BluetoothChat session.
* #param context The UI Activity Context
* #param handler A Handler to send messages back to the UI Activity
*/
public BluetoothChatService(Context context, Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
}
/**
* Set the current state of the chat connection
* #param state An integer defining the current connection state
*/
private synchronized void setState(int state) {
if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
mState = state;
// Give the new state to the Handler so the UI Activity can update
mHandler.obtainMessage(com.RSABluetooth.BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
/**
* Return the current connection state. */
public synchronized int getState() {
return mState;
}
/**
* Start the chat service. Specifically start AcceptThread to begin a
* session in listening (server) mode. Called by the Activity onResume() */
public synchronized void start() {
if (D) Log.d(TAG, "start");
// Cancel any thread attempting to make a connection
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
setState(STATE_LISTEN);
// Start the thread to listen on a BluetoothServerSocket
if (mSecureAcceptThread == null) {
mSecureAcceptThread = new AcceptThread(true);
mSecureAcceptThread.start();
}
if (mInsecureAcceptThread == null) {
mInsecureAcceptThread = new AcceptThread(false);
mInsecureAcceptThread.start();
}
}
/**
* Start the ConnectThread to initiate a connection to a remote device.
* #param device The BluetoothDevice to connect
* #param secure Socket Security type - Secure (true) , Insecure (false)
*/
public synchronized void connect(BluetoothDevice device, boolean secure) {
if (D) Log.d(TAG, "connect to: " + device);
// Cancel any thread attempting to make a connection
if (mState == STATE_CONNECTING) {
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
mConnectThread = new ConnectThread(device, secure);
mConnectThread.start();
setState(STATE_CONNECTING);
}
/**
* 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
*/
public synchronized void connected(BluetoothSocket socket, BluetoothDevice
device, final String socketType) {
if (D) Log.d(TAG, "connected, Socket Type:" + socketType);
// 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;}
// Cancel the accept thread because we only want to connect to one device
if (mSecureAcceptThread != null) {
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread.cancel();
mInsecureAcceptThread = null;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket, socketType);
mConnectedThread.start();
// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(com.RSABluetooth.BluetoothChat.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(com.RSABluetooth.BluetoothChat.DEVICE_NAME, device.getName());
bundle.putString("DEVICEADDRESS", device.getAddress());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
/**
* Stop all threads
*/
public synchronized void stop() {
if (D) Log.d(TAG, "stop");
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mSecureAcceptThread != null) {
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread.cancel();
mInsecureAcceptThread = null;
}
setState(STATE_NONE);
}
/**
* Write to the ConnectedThread in an unsynchronized manner
* #param out The bytes to write
* #see ConnectedThread#write(byte[])
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
/**
* Indicate that the connection attempt failed and notify the UI Activity.
*/
private void connectionFailed() {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(com.RSABluetooth.BluetoothChat.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(com.RSABluetooth.BluetoothChat.TOAST, "Unable to connect device");
msg.setData(bundle);
mHandler.sendMessage(msg);
// Start the service over to restart listening mode
BluetoothChatService.this.start();
}
/**
* Indicate that the connection was lost and notify the UI Activity.
*/
private void connectionLost() {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(com.RSABluetooth.BluetoothChat.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(com.RSABluetooth.BluetoothChat.TOAST, "Device connection was lost");
msg.setData(bundle);
mHandler.sendMessage(msg);
// Start the service over to restart listening mode
BluetoothChatService.this.start();
}
/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted
* (or until cancelled).
*/
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
private String mSocketType;
public AcceptThread(boolean secure) {
BluetoothServerSocket tmp = null;
mSocketType = secure ? "Secure":"Insecure";
// Create a new listening server socket
try {
if (secure) {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
MY_UUID_SECURE);
} else {
tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
NAME_INSECURE, MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
}
mmServerSocket = tmp;
}
public void run() {
if (D) Log.d(TAG, "Socket Type: " + mSocketType +
"BEGIN mAcceptThread" + this);
setName("AcceptThread" + mSocketType);
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (BluetoothChatService.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice(),
mSocketType);
break;
case STATE_NONE:
case STATE_CONNECTED:
// Either not ready or already connected. Terminate new socket.
try {
socket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close unwanted socket", e);
}
break;
}
}
}
}
if (D) Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);
}
public void cancel() {
if (D) Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
}
}
}
/**
* This thread runs while attempting to make an outgoing connection
* with a device. It runs straight through; the connection either
* succeeds or fails.
*/
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String mSocketType;
public ConnectThread(BluetoothDevice device, boolean secure) {
mmDevice = device;
BluetoothSocket tmp = null;
mSocketType = secure ? "Secure" : "Insecure";
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(
MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
setName("ConnectThread" + mSocketType);
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() " + mSocketType +
" socket during connection failure", e2);
}
connectionFailed();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothChatService.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice, mSocketType);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
}
}
}
/**
* This thread runs during a connection with a remote device.
* It handles all incoming and outgoing transmissions.
*/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType) {
Log.d(TAG, "create ConnectedThread: " + socketType);
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(com.RSABluetooth.BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
break;
}
}
}
/**
* Write to the connected OutStream.
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(com.RSABluetooth.BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
}
and you can send message by creating this method in your main activity there you have to send message by converting string to byte ..
private void sendMessage(String message) {
if (message.length() > 0) {
byte[] send = message.getBytes();
mChatService.write(send);
}
}
you can get response of your message in handler that you make in you main activity .. this is basic concept for sending data over blueootth and for more information please refer to google sample bluetooth application.
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if (D)
Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case BluetoothChatService.STATE_CONNECTED:
break;
case BluetoothChatService.STATE_CONNECTING:
connection.setTextColor(Color.BLACK);
connection.setText("Connecting...");
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
connection.setTextColor(Color.RED);
connection.setText("Not connected to another device");
break;
}
break;
case MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
mConversationArrayAdapter.add("Me: " + writeMessage);
break;
case MESSAGE_READ:
/*
* SOME PRETTY IMPORTANT STUFF HERE! This is the code for read
*/
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
DeviceAddress = msg.getData().getString("DEVICEADDRESS");
/* Toast.makeText(getApplicationContext(),
"Connected to " + mConnectedDeviceName,
Toast.LENGTH_SHORT).show();*/
break;
case MESSAGE_TOAST:
Toast.makeText(getApplicationContext(),
msg.getData().getString(TOAST), Toast.LENGTH_SHORT)
.show();
break;
}
}
};
you can get google sample bluetooth app from above link..

Null pointer exception while sending message

I build android app voice recognition command to control devices over embedded bluetooth, i use example code BluetoothChat to send voice recognition result. but i got an error like this.
enter FATAL EXCEPTION: main
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=100, result=-1, data=Intent { (has extras) }} to activity {com.embox.rumahpintar/com.embox.rumahpintar.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.deliverResults(ActivityThread.java:3378)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3421)
at android.app.ActivityThread.access$1100(ActivityThread.java:148)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1311)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5162)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:756)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:572)
at miui.dexspy.DexspyInstaller.main(DexspyInstaller.java:171)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.embox.rumahpintar.MainActivity.sendMessage(MainActivity.java:102)
at com.embox.rumahpintar.MainActivity.onActivityResult(MainActivity.java:89)
at android.app.Activity.dispatchActivityResult(Activity.java:5324)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3374)
at android.app.ActivityThread.access$1100(ActivityThread.java:148)
            
this is MainActivity class:
public class MainActivity extends ActionBarActivity {
private static final String TAG = "voice";
private final int REQ_CODE_SPEECH_INPUT = 100;
private TextView speakInput;
ArrayList<String> result;
Button tapSpeak;
String perintah = "hidupkan lampu kamar";
BluetoothService mService = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
BluetoothFragment fragment = new BluetoothFragment();
transaction.replace(R.id.sample_content_fragment, fragment);
transaction.commit();
}
Toast.makeText(this, "Smart Home #Created by Akmal Fadli", Toast.LENGTH_LONG).show();
speakInput = (TextView) findViewById(R.id.speakInput);
tapSpeak = (Button) findViewById(R.id.tapSpeak);
tapSpeak.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "Speak recognition open....");
promptSpeechInput();
}
});
}
public void promptSpeechInput() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
getString(R.string.speech_prompt));
try {
startActivityForResult(intent, REQ_CODE_SPEECH_INPUT);
} catch (ActivityNotFoundException a) {
Toast.makeText(getApplicationContext(),
getString(R.string.speech_not_supported),
Toast.LENGTH_SHORT).show();
}
}
/**
* Receiving speech input
*/
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQ_CODE_SPEECH_INPUT: {
if (resultCode == RESULT_OK && null != data) {
result = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
speakInput.setText(result.get(0));
BluetoothFragment m = new BluetoothFragment();
if (result.contains(perintah)) {
Toast.makeText(this, "Perintah terkirim . . .", Toast.LENGTH_LONG).show();
sendMessage(perintah);
}
break;
}
}
}
}
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mService.getState() != BluetoothService.STATE_CONNECTED) {
Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mService.write(send);
}
}
And this is SendMessage method:
public void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mService.getState() != BluetoothService.STATE_CONNECTED) {
Toast.makeText(getActivity(), R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mService.write(send);
}
}
give me advice please . . .
BluetoothService Class:
public class BluetoothService {
// Debugging
private static final String TAG = "BluetoothChatService";
// Name for the SDP record when creating server socket
private static final String NAME_INSECURE = "BluetoothChatInsecure";
// Unique UUID for this application
private static final UUID MY_UUID_SECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
//UUID uuid = device.getUuids()[0].getUuid();
//MY_UUID_SECURE = uuid;
// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mSecureAcceptThread;
private AcceptThread mInsecureAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;
// Constants that indicate the current connection state
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_LISTEN = 1; // now listening for incoming connections
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
/**
* Constructor. Prepares a new BluetoothChat session.
*
* #param context The UI Activity Context
* #param handler A Handler to send messages back to the UI Activity
*/
public BluetoothService(Context context, Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
}
/**
* Set the current state of the chat connection
*
* #param state An integer defining the current connection state
*/
private synchronized void setState(int state) {
Log.d(TAG, "setState() " + mState + " -> " + state);
mState = state;
// Give the new state to the Handler so the UI Activity can update
mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
/**
* Return the current connection state.
*/
public synchronized int getState() {
return mState;
}
/**
* Start the chat service. Specifically start AcceptThread to begin a
* session in listening (server) mode. Called by the Activity onResume()
*/
public synchronized void start() {
Log.d(TAG, "start");
// Cancel any thread attempting to make a connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
setState(STATE_LISTEN);
// Start the thread to listen on a BluetoothServerSocket
if (mSecureAcceptThread == null) {
mSecureAcceptThread = new AcceptThread(true);
mSecureAcceptThread.start();
}
if (mInsecureAcceptThread == null) {
mInsecureAcceptThread = new AcceptThread(false);
mInsecureAcceptThread.start();
}
}
/**
* Start the ConnectThread to initiate a connection to a remote device.
*
* #param device The BluetoothDevice to connect
*
*/
public synchronized void connect(BluetoothDevice device) {
Log.d(TAG, "connect to: " + device);
mAdapter.cancelDiscovery();
// Cancel any thread attempting to make a connection
if (mState == STATE_CONNECTING) {
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
mConnectThread = new ConnectThread(device);
mConnectThread.start();
setState(STATE_CONNECTING);
}
/**
* 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
*/
public synchronized void connected(BluetoothSocket socket, BluetoothDevice
device) {
// Log.d(TAG, "connected, Socket Type:" + socketType);
// 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;
}
// Cancel the accept thread because we only want to connect to one device
if (mSecureAcceptThread != null) {
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread.cancel();
mInsecureAcceptThread = null;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
String konek = "Device connected...";
byte[] pesan = konek.getBytes();
mConnectedThread.write(pesan);
// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(Constants.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
/**
* Stop all threads
*/
public synchronized void stop() {
Log.d(TAG, "stop");
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mSecureAcceptThread != null) {
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread.cancel();
mInsecureAcceptThread = null;
}
setState(STATE_NONE);
}
/**
* Write to the ConnectedThread in an unsynchronized manner
*
* #param out The bytes to write
* #see ConnectedThread#write(byte[]) (java.lang.String)
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
/**
* Indicate that the connection attempt failed and notify the UI Activity.
*/
private void connectionFailed() {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST, "Unable to connect device");
msg.setData(bundle);
mHandler.sendMessage(msg);
// Start the service over to restart listening mode
// BluetoothService.this.start();
}
/**
* Indicate that the connection was lost and notify the UI Activity.
*/
private void connectionLost() {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST, "Device connection was lost");
msg.setData(bundle);
mHandler.sendMessage(msg);
// Start the service over to restart listening mode
//BluetoothService.this.start();
}
/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted
* (or until cancelled).
*/
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
private String mSocketType;
public AcceptThread(boolean secure) {
BluetoothServerSocket tmp = null;
mSocketType = secure ? "Secure" : "Insecure";
// Create a new listening server socket
try {
tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
NAME_INSECURE, MY_UUID_SECURE);
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
}
mmServerSocket = tmp;
}
public void run() {
Log.d(TAG, "Socket Type: " + mSocketType +
"BEGIN mAcceptThread" + this);
setName("AcceptThread" + mSocketType);
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (BluetoothService.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice());
break;
case STATE_NONE:
case STATE_CONNECTED:
// Either not ready or already connected. Terminate new socket.
try {
socket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close unwanted socket", e);
}
break;
}
}
}
}
Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);
}
public void cancel() {
Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
}
}
}
/**
* This thread runs while attempting to make an outgoing connection
* with a device. It runs straight through; the connection either
* succeeds or fails.
*/
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// mSocketType = secure ? "Secure" : "Insecure";
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() " +
" socket during connection failure", e2);
}
connectionFailed();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothService.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect " + " socket failed", e);
}
}
}
/**
* This thread runs during a connection with a remote device.
* It handles all incoming and outgoing transmissions.
*/
//public class dulunya private
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
// Log.d(TAG, "create ConnectedThread: " + socketType);
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothService.this.start();
break;
}
}
}
/**
* Write to the connected OutStream.
*
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
SOLVED, I modified my code into one activity (MainActivity.class), so i moved BluetoothService into MainActivity.
You never initialize kirimPesan so it has null value. So you have NullPointerException (exception that tells you that something is null).
You need to initialize kirimPesan with constructor before you able to send messages.
Alternatively you can put method sendMessage in your own class MainActivity, then you will not need kirimPesan object at all.

Categories

Resources