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>
Related
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; }
}
I have the following implementation of ToyVpnService which I got frome here
public class ToyVpnService extends VpnService implements Handler.Callback, Runnable {
private static final String TAG = "ToyVpnService";
private Handler mHandler;
private Thread mThread;
private ParcelFileDescriptor mInterface;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
// Stop the previous session by interrupting the thread.
if (mThread != null) {
mThread.interrupt();
}
// Start a new session by creating a new thread.
mThread = new Thread(this, "ToyVpnThread");
mThread.start();
return START_STICKY;
}
#Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
}
#Override
public boolean handleMessage(Message message) {
if (message != null) {
Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
}
return true;
}
#Override
public synchronized void run() {
Log.i(TAG, "running vpnService");
try {
runVpnConnection();
} catch (Exception e) {
e.printStackTrace();
//Log.e(TAG, "Got " + e.toString());
} finally {
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = null;
mHandler.sendEmptyMessage(R.string.disconnected);
Log.i(TAG, "Exiting");
}
}
private boolean runVpnConnection() throws Exception {
configure();
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
// We keep forwarding packets till something goes wrong.
while (true) {
// Assume that we did not make any progress in this iteration.
boolean idle = true;
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
Log.i(TAG, "************new packet");
System.exit(-1);
while (packet.hasRemaining()) {
Log.i(TAG, "" + packet.get());
//System.out.print((char) packet.get());
}
packet.limit(length);
// tunnel.write(packet);
packet.clear();
// There might be more outgoing packets.
idle = false;
}
Thread.sleep(50);
}
}
public String getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = enumIpAddr.nextElement();
Log.i(TAG, "****** INET ADDRESS ******");
Log.i(TAG, "address: " + inetAddress.getHostAddress());
Log.i(TAG, "hostname: " + inetAddress.getHostName());
Log.i(TAG, "address.toString(): " + inetAddress.getHostAddress().toString());
if (!inetAddress.isLoopbackAddress()) {
//IPAddresses.setText(inetAddress.getHostAddress().toString());
Log.i(TAG, "IS NOT LOOPBACK ADDRESS: " + inetAddress.getHostAddress().toString());
return inetAddress.getHostAddress().toString();
} else {
Log.i(TAG, "It is a loopback address");
}
}
}
} catch (SocketException ex) {
String LOG_TAG = null;
Log.e(LOG_TAG, ex.toString());
}
return null;
}
private void configure() throws Exception {
// If the old interface has exactly the same parameters, use it!
if (mInterface != null) {
Log.i(TAG, "Using the previous interface");
return;
}
// Configure a builder while parsing the parameters.
Builder builder = new Builder();
builder.setMtu(1500);
builder.addAddress(getLocalIpAddress(), 24);
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = builder.establish();
}
}
It seems to be receiving packets but I have no idea on how to read the data in the paclkets. the code seems to be incomplete (hence the tunnel.write(packet) that's commented out cause there isn't a variable tunnel). Is this the right way? or is there a better way of doing this?
I'm trying to get two android phones to connect via bluetooth. I'm following the instructions here from the android online howto's, and I'm following pretty closely.
http://developer.android.com/guide/topics/connectivity/bluetooth.html
I can get bluetooth to connect once, but I have to restart the android device or the app itself in order to get it to connect a second time. This is not a problem during development because with each edit of the code the android studio program re-loads the app. It starts it and restarts it, so that during testing I can connect over and over. During actual use I have to restart the android phone or go to the applications manager option under settings and physically stop that app.
From the code below I can connect if I call these lines:
generateDefaultAdapter();
startDiscovery();
startThreadAccept();
startThreadConnect();
How do I get it so that the bluetooth connection can be initiated over and over again? I see the message 'unable to connect' from the inner class 'ConnectThread' and an IO error from a 'printStackTrace()' from that part of the code. The second time I try, I seem to be able to call the method 'stopConnection()' and then the lines above (starting with 'generateDefaultAdapter()') but I find I cannot connect.
package org.test;
//some import statements here...
public class Bluetooth {
public boolean mDebug = true;
public BluetoothAdapter mBluetoothAdapter;
public UUID mUUID = UUID.fromString(BLUETOOTH_UUID);
public Thread mAcceptThread;
public Thread mConnectThread;
public ConnectedThread mManageConnectionAccept;
public ConnectedThread mManageConnectionConnect;
public APDuellingBluetooth() {
}
public void generateDefaultAdapter() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}
if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled() ) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
(mDialogDuel.getActivity()).startActivityForResult(enableBtIntent, INTENT_ACTIVITY_BLUETOOTH_REQUEST_ENABLE);
}
}
public void cancelDiscovery() { if (mBluetoothAdapter != null) mBluetoothAdapter.cancelDiscovery();}
public void startDiscovery() { mBluetoothAdapter.startDiscovery();}
public BluetoothAdapter getBluetoothAdapter() {return mBluetoothAdapter;}
public void stopConnection () {
try {
if (mAcceptThread != null) {
mAcceptThread.interrupt();
//mAcceptThread.join();
mAcceptThread = null;
}
if (mConnectThread != null) {
mConnectThread.interrupt();
//mConnectThread.join();
mConnectThread = null;
}
if (mManageConnectionConnect != null) {
mManageConnectionConnect.cancel();
mManageConnectionConnect.interrupt();
mManageConnectionConnect = null;
}
if (mManageConnectionAccept != null) {
mManageConnectionAccept.cancel();
mManageConnectionAccept.interrupt();
mManageConnectionAccept = null;
}
}
catch(Exception e) {
e.printStackTrace();
}
}
public void startThreadAccept () {
if (mAcceptThread != null && !mAcceptThread.isInterrupted()) {
if (mDebug) System.out.println("server already open");
//return;
mAcceptThread.interrupt();
mAcceptThread = new AcceptThread();
}
else {
mAcceptThread = new AcceptThread();
}
if (mAcceptThread.getState() == Thread.State.NEW ){
//mAcceptThread.getState() == Thread.State.RUNNABLE) {
mAcceptThread.start();
}
}
public void startThreadConnect () {
BluetoothDevice mDevice = mBluetoothAdapter.getRemoteDevice(mChosen.getAddress());
//if (mDebug) System.out.println(mDevice.getAddress() + " -- " + mChosen.getAddress() );
if (mConnectThread != null && !mConnectThread.isInterrupted()) {
if (mDebug) System.out.println("client already open");
//return;
mConnectThread.interrupt();
mConnectThread = new ConnectThread(mDevice);
}
else {
mConnectThread = new ConnectThread(mDevice);
}
if (mConnectThread.getState() == Thread.State.NEW){// ||
//mConnectThread.getState() == Thread.State.RUNNABLE) {
mConnectThread.start();
}
}
public void manageConnectedSocketAccept(BluetoothSocket socket) {
String mTemp = mBluetoothAdapter.getName();
if (mDebug) {
System.out.println("socket accept from " + mTemp);
System.out.println("info accept " + socket.getRemoteDevice().toString());
}
if (mManageConnectionAccept != null && !mManageConnectionAccept.isInterrupted()) {
//mManageConnectionAccept.cancel();
//mManageConnectionAccept.interrupt();
if (mAcceptThread == null) System.out.println(" bad thread accept");
}
else {
mManageConnectionAccept = new ConnectedThread(socket, "accept");
}
if (mManageConnectionAccept.getState() == Thread.State.NEW ){//||
//mManageConnectionAccept.getState() == Thread.State.RUNNABLE) {
mManageConnectionAccept.start();
}
}
public void manageConnectedSocketConnect(BluetoothSocket socket) {
String mTemp = mBluetoothAdapter.getName();
if (mDebug) {
System.out.println("socket connect from " + mTemp);
System.out.println("info connect " + socket.getRemoteDevice().toString());
}
if (mManageConnectionConnect != null && !mManageConnectionConnect.isInterrupted()) {
//mManageConnectionConnect.cancel();
//mManageConnectionConnect.interrupt();
if (mConnectThread == null) System.out.print(" bad thread connect ");
}
else {
mManageConnectionConnect = new ConnectedThread(socket, "connect");
}
if (mManageConnectionConnect.getState() == Thread.State.NEW){// ||
//mManageConnectionConnect.getState() == Thread.State.RUNNABLE) {
mManageConnectionConnect.start();
}
}
public void decodeInput (String mIn, ConnectedThread mSource) {
// do something with info that is returned to me...
}
public void encodeOutput (String mMac1, String mMac2, int mLR1, int mLR2) {
String mTemp = composeOutputString ( mServer, mMac1,mMac2, mLR1, mLR2);
if (mManageConnectionConnect != null && mManageConnectionConnect.isConnected()) {
mManageConnectionConnect.write(mTemp.getBytes());
mManageConnectionConnect.flush();
}
if (mManageConnectionAccept != null && mManageConnectionAccept.isConnected()) {
mManageConnectionAccept.write(mTemp.getBytes());
mManageConnectionAccept.flush();
}
mTemp = composeOutputString ( mClient, mMac1,mMac2, mLR1, mLR2);
if (mManageConnectionConnect != null && mManageConnectionConnect.isConnected()) {
mManageConnectionConnect.write(mTemp.getBytes());
mManageConnectionConnect.flush();
}
if (mManageConnectionAccept != null && mManageConnectionAccept.isConnected()) {
mManageConnectionAccept.write(mTemp.getBytes());
mManageConnectionAccept.flush();
}
}
public String composeOutputString (SocketConnectData mData, String mMac1, String mMac2, int mLR1, int mLR2) {
// make a string here with the data I want to send...
String mTemp = new String();
return mTemp;
}
/////////////////////////////////////////////
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
private boolean mLoop = true;
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
mLoop = true;
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(mServiceNameReceive, mUUID );
} catch (IOException e) {
System.out.println("rfcomm problem ");
}
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (mLoop) {
try {
if (mmServerSocket != null) {
socket = mmServerSocket.accept();
}
} catch (IOException e) {
if (mDebug) System.out.println("rfcomm accept problem");
e.printStackTrace();
break;
}
// If a connection was accepted
if (socket != null && ! isConnectionOpen() ) {
// Do work to manage the connection (in a separate thread)
manageConnectedSocketAccept(socket);
try {
mmServerSocket.close();
}
catch (IOException e) {}
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mLoop = false;
mmServerSocket.close();
} catch (IOException e) { }
}
}
/////////////////////////////////////////////
private class ConnectThread extends Thread {
//private final BluetoothSocket mmSocket;
private BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
try {
tmp = device.createRfcommSocketToServiceRecord(mUUID);
if (mDebug) System.out.println("connect -- rf socket to service record " + tmp);
} catch (Exception e) {
System.out.println("exception -- rf socket to service record problem " + tmp);
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
}
//catch (InterruptedException e ) {System.out.println("interrupted exception");}
catch (IOException e) {
// Unable to connect; close the socket and get out
if (mDebug) System.out.println("unable to connect ");
e.printStackTrace(); // <---- I see output from this spot!!
try {
mmSocket.close();
} catch (IOException closeException) {
System.out.println("unable to close connection ");
}
return;
}
// Do work to manage the connection (in a separate thread)
if (mmSocket.isConnected() && ! isConnectionOpen()) {
manageConnectedSocketConnect(mmSocket);
}
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
public boolean isConnected() {
return mmSocket.isConnected();
}
}
/////////////////////////////////////////////
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public String mTypeName = "";
private boolean mLoop = true;
public StringWriter writer;
public ConnectedThread(BluetoothSocket socket, String type) {
mTypeName = type;
mLoop = true;
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
try {
writer = new StringWriter();
}
catch (Exception e) {}
}
public void run() {
byte[] buffer = new byte[1024]; //
int bytes; // bytes returned from read()
String [] mLines ;
// Keep listening to the InputStream until an exception occurs
while (mLoop) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
if (bytes == -1 || bytes == 0) {
if (mDebug) System.out.println("zero read");
return;
}
writer.append(new String(buffer, 0, bytes));
mLines = writer.toString().split("!");
if (mDebug) System.out.println( "lines " +mLines.length);
for (int i = 0; i < mLines.length; i ++ ) {
if (true) {
if (mDebug) System.out.println(" " + mLines[i]);
decodeInput (mLines[i], this);
}
}
} catch (Exception e) {
e.printStackTrace();
if (mDebug) System.out.println("read buffer problem");
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
if (mDebug) System.out.println("bad write");
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mLoop = false;
mmSocket.close();
mmOutStream.close();
mmInStream.close();
} catch (IOException e) { }
}
public boolean isConnected() {
boolean mIsOpen = false;
try {
mIsOpen = mmSocket.isConnected() ;
} catch (Exception e) {}
return mIsOpen;
}
public void flush() {
try {
mmOutStream.flush();
}
catch (IOException e) {e.printStackTrace();}
}
}
///////////////////////////////////////////////
}
Thanks for your time.
EDIT: this is the error msg:
W/System.err﹕ java.io.IOException: read failed, socket might closed or timeout, read ret: -1
W/System.err﹕ at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:553)
W/System.err﹕ at android.bluetooth.BluetoothSocket.waitSocketSignal(BluetoothSocket.java:530)
W/System.err﹕ at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:357)
W/System.err﹕ at org.davidliebman.test.Bluetooth$ConnectThread.run(Bluetooth.java:761)
Try this:
Instead of restarting the app. Turn off the Bluetooth on the Android device and turn it back on after a 5-sec delay. If you could make the connection successfully, it typically a sign that you did not close the connection and socket completely. Log your code. Make sure the closing socket routine is smoothly executed. Check if the IOException you have in your cancel method of your ConnectedThread is not catching any exception:
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
// ADD LOG
mLoop = false;
mmSocket.close();
mmOutStream.close();
mmInStream.close();
// ADD LOG
} catch (IOException e) {
// ADD LOG}
}
outStream.write(msgBuffer);
It writes only first bit. how to write 8 bit out of it.If we are sending 00000001 means it writes only 0. But we want to write whole 8 bit how to achieve it.
public class MainActivity extends ActionBarActivity {
private ToggleButton power, simulation, reset, pause, replay, diagnose,
abs, emergency;
private static final String TAG = "bluetooth1";
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
// SPP UUID service
private static final UUID MY_UUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
// MAC-address of Bluetooth module (you must edit this line)
private static String address = "00:12:02:28:75:34";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
power = (ToggleButton) findViewById(R.id.toggleButton1);
simulation = (ToggleButton) findViewById(R.id.simulation_tb);
reset = (ToggleButton) findViewById(R.id.reset_bt);
pause = (ToggleButton) findViewById(R.id.pause_bt);
replay = (ToggleButton) findViewById(R.id.replay_bt);
diagnose = (ToggleButton) findViewById(R.id.diagnose_bt);
abs = (ToggleButton) findViewById(R.id.abs_bt);
emergency = (ToggleButton) findViewById(R.id.emergency_bt);
btAdapter = BluetoothAdapter.getDefaultAdapter();
checkBTState();
power.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
if (power.isChecked()) {
String str = "1";
int i = Integer.parseInt(str);
String binarystr = Integer.toBinaryString(i);
char[] buffer = new char[binarystr.length()];
binarystr.getChars(0, binarystr.length(), buffer, 0);
System.out.println("char array:: "
+ Arrays.toString(buffer));
byte[] binaryFormat = getbyteFromString(buffer);
for (byte b : binaryFormat) {
sendData(Integer.toBinaryString(b & 255 | 256)
.substring(1));
}
Toast.makeText(getApplicationContext(), "LED ON",
Toast.LENGTH_LONG).show();
} else {
sendData("0");
Toast.makeText(getApplicationContext(), "LED OFF",
Toast.LENGTH_LONG).show();
}
}
});
}
#Override
public void onBackPressed() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.const_closeApp))
.setPositiveButton(getString(R.string.const_yes),
dialogClickListener)
.setNegativeButton(getString(R.string.const_no),
dialogClickListener).show();
}
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
// LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(new
// BTStateChangedBroadcastReceiver());
System.exit(0);
finish();
break;
case DialogInterface.BUTTON_NEGATIVE:
// No button clicked
break;
}
}
};
private void checkBTState() {
// Check for Bluetooth support and then check to make sure it is turned
// on
// Emulator doesn't support Bluetooth and will return null
if (btAdapter == null) {
errorExit("Fatal Error", "Bluetooth not support");
} else {
if (btAdapter.isEnabled()) {
Log.d(TAG, "...Bluetooth ON...");
} else {
// Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
}
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device)
throws IOException {
if (Build.VERSION.SDK_INT >= 10) {
try {
final Method m = device.getClass().getMethod(
"createInsecureRfcommSocketToServiceRecord",
new Class[] { UUID.class });
return (BluetoothSocket) m.invoke(device, MY_UUID);
} catch (Exception e) {
Log.e(TAG, "Could not create Insecure RFComm Connection", e);
}
}
return device.createRfcommSocketToServiceRecord(MY_UUID);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private void sendData(String message) {
byte[] msgBuffer = message.getBytes();
Log.d(TAG, "...Send data: " + message + "...");
try {
outStream.write(msgBuffer);
Log.d(TAG, "...This is the value byte: " + msgBuffer);
} catch (IOException e) {
String msg = "In onResume() and an exception occurred during write: "
+ e.getMessage();
if (address.equals("00:00:00:00:00:00"))
msg = msg
+ ".\n\nUpdate your server address from 00:00:00:00:00:00 to the correct address on line 35 in the java code";
msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString()
+ " exists on server.\n\n";
errorExit("Fatal Error", msg);
}
}
private void errorExit(String title, String message) {
Toast.makeText(getBaseContext(), title + " - " + message,
Toast.LENGTH_LONG).show();
finish();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public static byte[] getbyteFromString(char[] binarystr) {
int length = binarystr.length / 8;
if (binarystr.length % 8 > 0)
length++;
int iterationCount = length;
byte[] binaryFormat = new byte[iterationCount];
int iter = iterationCount - 1;
for (int i = binarystr.length - 1; i >= 0;) {
byte byt = 0x0;
for (int j = 0; j < 8; j++) {
if (i < 0)
break;
int b = binarystr[i] - 48;
byt = (byte) (byt + (b << j));
i--;
}
binaryFormat[iter] = byt;
iter--;
}
return binaryFormat;
}
#Override
public void onResume() {
super.onResume();
Log.d(TAG, "...onResume - try connect...");
// Set up a pointer to the remote node using it's address.
BluetoothDevice device = btAdapter.getRemoteDevice(address);
// Two things are needed to make a connection:
// A MAC address, which we got above.
// A Service ID or UUID. In this case we are using the
// UUID for SPP.
try {
btSocket = createBluetoothSocket(device);
} catch (IOException e1) {
errorExit("Fatal Error", "In onResume() and socket create failed: "
+ e1.getMessage() + ".");
}
/*
* try { btSocket = device.createRfcommSocketToServiceRecord(MY_UUID); }
* catch (IOException e) { errorExit("Fatal Error",
* "In onResume() and socket create failed: " + e.getMessage() + "."); }
*/
// Discovery is resource intensive. Make sure it isn't going on
// when you attempt to connect and pass your message.
btAdapter.cancelDiscovery();
// Establish the connection. This will block until it connects.
Log.d(TAG, "...Connecting...");
try {
btSocket.connect();
Log.d(TAG, "...Connection ok...");
} catch (IOException e) {
try {
btSocket.close();
} catch (IOException e2) {
errorExit("Fatal Error",
"In onResume() and unable to close socket during connection failure"
+ e2.getMessage() + ".");
}
}
// Create a data stream so we can talk to server.
Log.d(TAG, "...Create Socket...");
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
errorExit(
"Fatal Error",
"In onResume() and output stream creation failed:"
+ e.getMessage() + ".");
}
}
#Override
public void onPause() {
super.onPause();
Log.d(TAG, "...In onPause()...");
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e) {
errorExit(
"Fatal Error",
"In onPause() and failed to flush output stream: "
+ e.getMessage() + ".");
} catch (NullPointerException e) {
e.printStackTrace();
}
}
try {
btSocket.close();
} catch (IOException e2) {
errorExit("Fatal Error", "In onPause() and failed to close socket."
+ e2.getMessage() + ".");
}
}
}
It looks like your code is not complete. Anyway, I suggest to use the DataInputStream / DataOutputStream of Android. Just wrap your streams into them. They provide methods for writing any kind of primitive datatype up to String with arbitrary encoding. All you need to do is use the writeString(...) method and use the read String method on the other side. This way you don't need to convert the String in order to write it into you stream and you don't need to care about how to reconstruct it from the stream.
If you only want to write Strings you can use the BufferedWriter which allows you to only write Strings to an stream, you can use it like this to stick it onto a 'OutputStream'
OutputStreamWriter osw = new OutputStreamWriter(outStream);
BufferedWriter writer = new BufferedWriter(osw);
I need to create RFCOMM Bluetooth socket for send request and get response from server using blutooth. need to creat bluetooth socket in client side for request and response using android bluetooth api.
How can i create this..
I tried like this
public class MainActivity extends Activity {
TextView out;
private static final int REQUEST_ENABLE_BT = 1;
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
// Well known SPP UUID
private static final UUID MY_UUID =
UUID.fromString("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
// Insert your server's MAC address
private static String address = "xxxxxxxxxxxxxxxx";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
out = (TextView) findViewById(R.id.out);
// out.append("\n...In onCreate()...");
btAdapter = BluetoothAdapter.getDefaultAdapter();
CheckBTState();
}
#Override
public void onStart() {
super.onStart();
// out.append("\n...In onStart()...");
}
#Override
public void onResume() {
super.onResume();
out.append("\n...In onResume...\n...Attempting client connect...");
// Set up a pointer to the remote node using it's address.
BluetoothDevice device = btAdapter.getRemoteDevice(address);
// Two things are needed to make a connection:
// A MAC address, which we got above.
// A Service ID or UUID. In this case we are using the
// UUID for SPP.
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
AlertBox("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
}
// Discovery is resource intensive. Make sure it isn't going on
// when you attempt to connect and pass your message.
btAdapter.cancelDiscovery();
// Establish the connection. This will block until it connects.
try {
btSocket.connect();
out.append("\n...Connection established and data link opened...");
} catch (IOException e) {
try {
btSocket.close();
} catch (IOException e2) {
AlertBox("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
}
}
// Create a data stream so we can talk to server.
out.append("\n...Sending message to server...");
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
AlertBox("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + ".");
}
String message = "DECapabilities?$format=json";
byte[] msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
} catch (IOException e) {
String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
if (address.equals("00:00:00:00:00:00"))
msg = msg + ".\n\nUpdate your server address from 08:ED:B9:48:EE:C0 to the correct address on line 37 in the java code";
msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";
AlertBox("Fatal Error", msg);
}
}
#Override
public void onPause() {
super.onPause();
out.append("\n...In onPause()...");
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e) {
AlertBox("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
}
}
try {
btSocket.close();
} catch (IOException e2) {
AlertBox("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
}
}
#Override
public void onStop() {
super.onStop();
out.append("\n...In onStop()...");
}
#Override
public void onDestroy() {
super.onDestroy();
out.append("\n...In onDestroy()...");
}
private void CheckBTState() {
// Check for Bluetooth support and then check to make sure it is turned on
// Emulator doesn't support Bluetooth and will return null
if(btAdapter==null) {
AlertBox("Fatal Error", "Bluetooth Not supported. Aborting.");
} else {
if (btAdapter.isEnabled()) {
out.append("\n...Bluetooth is enabled...");
} else {
//Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(btAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
}
public void AlertBox( String title, String message ){
new AlertDialog.Builder(this)
.setTitle( title )
.setMessage( message + " Press OK to exit." )
.setPositiveButton("OK", new OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
finish();
}
}).show();
}
}
but getting socket closed exception.
I solved this by BluetoothChat code its help me very much.
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/2.1_r2/com/example/android/BluetoothChat/BluetoothChat.java