0 Replies - 563 Views - Last Post: 19 December 2014 - 06:47 AM

#1 Ahleki   User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 55
  • Joined: 01-June 10

Connecting to two bluetooth serial devices concurrently

Posted 19 December 2014 - 06:47 AM

I am trying to connect to two bluetooth serail devices; one is a weighing scale the other is a printer.

To connect to the printer, I have to first connect to the weiging scale which is working well then connnect to the printer which is failing . Am running two services to handle both connections after failing with multiple threads in one service.

The Weighing.java class starts the PrintingService upon successfull connection
as seen below:

    	private final Handler mHandler = new Handler() {
		@Override
		public void handleMessage(final Message msg) {
			switch (msg.what) {
			case MESSAGE_STATE_CHANGE:
				switch (msg.arg1) {
				case WeighingService.STATE_CONNECTED:
					Weighing.mProcessDialog.setMessage("Connected to Scale");
					try {
						Weighing.mProcessDialog.setMessage("Attempting connection to printer");
						Thread.sleep(3000);
					} catch (InterruptedException e2) {
						e2.printStackTrace();
					}

					Intent printingIntent = new Intent(getApplicationContext(),PrintingService.class);
					startService(printingIntent);

					bindService(printingIntent, printerConnection, Context.BIND_AUTO_CREATE);

					mPrinterMessenger = new Messenger(printerHandler);

					Message printerMessage = Message.obtain(null,PrintingService.MSG_REG_CLIENT);

					Bundle printerBundle = new Bundle();
					printerBundle.putInt(DEVICE_TYPE, 2);
					printerBundle.putString(DEVICE_NAME, "ACC6243");

					printerMessage.setData(printerBundle);
					printerMessage.replyTo = mPrinterMessenger;

					try {
						mPrinterService.send(printerMessage);
					} catch (RemoteException e1) {
						e1.printStackTrace();
					}

					break;



Here is the code for the PrintingService

    package com.octagon.easyweigh;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.Set;
    import java.util.UUID;
    
    import android.annotation.SuppressLint;
    import android.app.ProgressDialog;
    import android.app.Service;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothDevice;
    import android.bluetooth.BluetoothSocket;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.util.Log;
    
    public class PrintingService extends Service {
    	@SuppressLint("NewApi")
    	// Debugging
    	private static final String TAG = "PrintingService";
    	private static final boolean D = true;
    
    	// Name for the SDP record when creating server socket
    	private static final String NAME_SECURE = "PrintingSecure";
    
    	// Unique UUID for this application
    	private static final UUID MY_UUID_INSECURE = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
    
    	// Member fields
    	//private final BluetoothAdapter mAdapter;
    	//private final Handler mHandler;
    	private ConnectThread mConnectThread;
    	private ConnectedThread mConnectedThread;
    	public static 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
    	//public static final int CONNECT_DEVICE = 5; //Connect to device
    
    	// Message codes received from the UI client.
    	// Register client with this service.
    	public static final int MSG_REG_CLIENT = 200;
    	// Unregister client from this service.
    	public static final int MSG_UNREG_CLIENT = 201;
    
    	public static final int RETRY = 500;
    	public static final int RECONNECT = 501;
    	
    	public static final int PRINT = 502;  
    	private int mChannelId;
    
    	private Messenger mClient;
    	private BluetoothDevice mDevice;
    	private BluetoothAdapter mBluetoothAdapter;
    	ProgressDialog mProcessDialog;
    
    	String deviceAddress,deviceName;
    	ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
    
    	/**
    	 * Constructor. Prepares a new Weighing session.
    	 * @param context  The UI Activity Context
    	 * @param handler  A Handler to send messages back to the UI Activity
    	 */
    
    	// Handles events sent by {@link HealthHDPActivity}.
    	private class IncomingHandler extends Handler {
    		@Override
    		public void handleMessage(Message msg) {
    			switch (msg.what) {
    			// Register UI client to this service so the client can receive messages.
    			case MSG_REG_CLIENT:
    				Log.d(TAG, "Activity client registered");
    				mClient = msg.replyTo;
    
    				Log.i(TAG, "Got Address [" + Weighing.getAddress() + "]");
    				//String deviceAddress = Weighing.getAddress().toString();
    
    				Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
    
    				Log.i(TAG, "Device name in PrintingService is " + deviceName);
    
    				deviceName = msg.getData().getString(Weighing.DEVICE_NAME);
    
    				for (BluetoothDevice device : pairedDevices) {
    					if (device.getName().equals(deviceName)) { // Only display specific devices the rest nah not interested!
    						deviceAddress =  device.getAddress();	
    						Log.i(TAG, "Printer address " + deviceAddress);
    					}
    				}
    				mDevice = mBluetoothAdapter.getRemoteDevice(deviceAddress);
    				connect(mDevice,false);
    				break;
    				// Unregister UI client from this service.
    			case MSG_UNREG_CLIENT:
    				mClient = null;
    				break;
    			case RETRY:
    				try {
    					deviceAddress = msg.getData().getString(Weighing.EXTRA_DEVICE_ADDRESS);
    
    
    					mDevice = mBluetoothAdapter.getRemoteDevice(deviceAddress);
    					connect(mDevice,false);
    
    				} catch (Exception e) {
    					Log.e(TAG, "Unable to reach client to request address " + e.getMessage());
    				}
    				break;
    			case RECONNECT:
    				deviceAddress = msg.getData().getString(Weighing.EXTRA_DEVICE_ADDRESS);
    
    				if (deviceAddress.equals("") || deviceAddress.equals(null)) {
    					//Complete failure
    					Message totalFailure  = Message.obtain(null,Weighing.COMPLETE_FAILURE);
    					tumaMessage(totalFailure);
    				} else {
    					mDevice = mBluetoothAdapter.getRemoteDevice(deviceAddress);
    					connect(mDevice,false);
    				}
    				break;
    			case PRINT:
    
    				String message;
    				message = "     *** RECEIPT SLIP ***\r\n";
    				message+= "     OCTAGON DATA SYSTEMS LTD \r\n";
    				message+="       P.O.BOX 1618 - 00100\r\n";
    				message+="\r\n";
    				message+="  RECEIPT  : " + msg.getData().getString(Weighing.RECEIPT_NO) + "\r\n";
    				message+="  DATE     : " + msg.getData().getInt(Weighing.DATE) + "\r\n";
    				message+="	TIME     : "+ msg.getData().getInt(Weighing.TIME) + "\r\n";
    				message+="	TERMINAL : " + msg.getData().getInt(Weighing.TERMINAL) + "\r\n";
    				message+="	FARMER NO: " + msg.getData().getInt(Weighing.FARMER_NO) + "\r\n";
    				message+="  NAME     : " + msg.getData().getInt(Weighing.NAME) + "\r\n";
    				message+="  ROUTE    : " + msg.getData().getInt(Weighing.ROUTE) + "\r\n";
    				message+="  SHED     : " + msg.getData().getInt(Weighing.SHED) + "\r\n";
    				message+="  BATCH    : " + msg.getData().getInt(Weighing.BATCH) + "\r\n";
    				message+="------------------------\r\n";
    				message+="  CAN      : " + msg.getData().getInt(Weighing.CAN) + "\r\n";
    				message+="  GROSS WT : " + msg.getData().getInt(Weighing.GROSS_WEIGHT) + "\r\n";
    				message+="  TARE WT  :  " + msg.getData().getInt(Weighing.TARE_WEIGHT) + "\r\n";
    				message+="  NET WT   : " + msg.getData().getInt(Weighing.NET_WEIGHT) + "\r\n";
    				message+="  TOTAL KGS: " + msg.getData().getInt(Weighing.TOTAL_WEIGHT) + "\r\n";
    				message+="------------------------\r\n";
    				message+="  CLERK NAME: Octagon Data Systems \r\n";
    				message+="\r\n";
    				message+="\r\n";
    				message+="\r\n";
    				message+="\r\n";
    				message+="\r\n";
    
    				byte[] send = message.getBytes();
    				write(send);
    
    				//deviceType = 2; //it's a printer
    				break;
    			default:
    				super.handleMessage(msg);
    			}
    		}
    	}
    
    	final Messenger mMessenger = new Messenger(new IncomingHandler());
    
    	/**
    	 * Make sure Bluetooth and health profile are available on the Android device.  Stop service
    	 * if they are not available.
    	 */
    	@Override
    	public void onCreate() {
    		super.onCreate();
    		Log.d(TAG, "Printer Service is running.");
    		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    		if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
    			// Bluetooth adapter isn't available.  The client of the service is supposed to
    			// verify that it is available and activate before invoking this service.
    			stopSelf();
    			return;
    		} 
    	}
    
    	@Override
    	public int onstartCommand(Intent intent, int flags, int startId) {
    		try {
    			//Bundle b = intent.getExtras();
    			//deviceAddress = b.getString(Weighing.EXTRA_DEVICE_ADDRESS);
    		} catch (Exception e) {
    			Log.e(TAG, "Failure on Bundle" + e.toString());
    		}
    		return START_STICKY;	
    	}
    
    	@Override
    	public IBinder onBind(Intent arg0) {
    
    		return mMessenger.getBinder();
    	}
    
    	private void tumaMessage(Message msg) {
    		if (mClient == null) {
    			Log.d(TAG,"No Clients Registered");
    			return;
    		}
    
    		try {
    			mClient.send(msg);
    		} catch (RemoteException e) {
    			// Unable to reach client.
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 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(Weighing.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
    		Message msg = Message.obtain(null,Weighing.MESSAGE_STATE_CHANGE, state, -1);
    		tumaMessage(msg);
    	}
    
    	/**
    	 * 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 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;}
    
    		// 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(Weighing.MESSAGE_DEVICE_NAME);
    		Message msg  = Message.obtain(null, Weighing.MESSAGE_DEVICE_NAME);
    		Bundle bundle = new Bundle();
    		bundle.putString(Weighing.DEVICE_NAME, device.getName());
    		msg.setData(bundle);
    		tumaMessage(msg);
     
    		setState(STATE_CONNECTED);
    
    		new Thread()
    		{
    			@Override
    			public void run()
    			{
    				try
    				{
    					//Keep sending R to get readings from BT Scale
    					/*while (true) {
    						String message = "R" + "\r" + "\n";
    						byte[] send = message.getBytes();
    						write(send);
    						sleep(100); 
    						//return;
    					}*/
    				}
    				finally
    				{
    					//mProcessDialog.cancel();
    				}
    			}
    		}
    		.start();
    	}
    
    	/**
    	 * Stop all threads
    	 */
    	public synchronized void stop() {
    		setState(STATE_NONE);
    		if (mConnectThread != null) {
    			mConnectThread.cancel();
    			mConnectThread = null;
    		}
    
    		if (mConnectedThread != null) {
    			mConnectedThread.cancel();
    			mConnectedThread = null;
    		}
    		if (mBluetoothAdapter != null) {
    			mBluetoothAdapter.cancelDiscovery();
    		}
    		stopSelf();
    	}
    
    	/**
    	 * 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(Weighing.MESSAGE_TOAST);
    		Message msg = Message.obtain(null,Weighing.MESSAGE_TOAST);
    		Bundle bundle = new Bundle();
    		bundle.putString(Weighing.TOAST, "Unable to connect printer");
    		msg.setData(bundle);
    		tumaMessage(msg);
    		//mHandler.sendMessage(msg);
    
    		// Start the service over to restart listening mode
    		PrintingService.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(Weighing.MESSAGE_TOAST);
    		Message msg = Message.obtain(null,Weighing.MESSAGE_TOAST);
    		Bundle bundle = new Bundle();
    		bundle.putString(Weighing.TOAST, "Device connection was lost");
    		msg.setData(bundle);
    		tumaMessage(msg);
    
    		setState(STATE_NONE);
    		// Start the service overs to restart listening mode
    
    	}
    	/**
    	 * 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) {
    					try {
    						Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
    						tmp = (BluetoothSocket) m.invoke(device, Integer.valueOf(1));
    					} catch (Exception e) {
    						Log.e(TAG, "Error at HTC/createRfcommSocket: " + e);
    						e.printStackTrace();
    					}
    				} else {
    					tmp = device.createRfcommSocketToServiceRecord(
    							MY_UUID_INSECURE);
    				}
    			} catch (IOException e) {
    				Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
    			}
    			mmSocket = tmp;
    		}
    
    		@Override
    		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 (PrintingService.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;
    		}
    
    		@Override
    		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);
    					//bytes = mmInStream.read(buffer, 0, buffer.length);
    					// Send the obtained bytes to the UI Activity
    					/*mHandler.obtainMessage(Weighing.MESSAGE_READ, bytes, -1, buffer)
    					.sendToTarget();*/
    					Message msg = Message.obtain(null,Weighing.MESSAGE_READ, bytes, -1, buffer);
    					tumaMessage(msg);
    				} 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
    				Message msg = Message.obtain(null,Weighing.MESSAGE_WRITE, -1, -1, buffer);
    				tumaMessage(msg);
    			} 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);
    			}
    		}
    	}
    }



The second connection won't work even having used two differenct connections as below:

    	private ServiceConnection scaleConnection = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			mWeighingServiceBound = true;

			Bundle myBundle = new Bundle();
			myBundle.putInt(DEVICE_TYPE,1);

			Message msg = Message.obtain(null, WeighingService.MSG_REG_CLIENT);

			msg.setData(myBundle);

			msg.replyTo = mMessenger;

			mWeighingService = new Messenger(service);
			//mPrinterService = new Messenger(service);

			try {
				mWeighingService.send(msg);
			} catch (RemoteException e) {
				Log.w(TAG, "Unable to register client to service.");
				e.printStackTrace();
			}
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			mWeighingService = null;

			mWeighingServiceBound = false;
			mPrintingServiceBounnd = false;
		}
	};

	// Sets up communication with {@link WeighingService}.
	private ServiceConnection printerConnection = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			mPrintingServiceBounnd = true;

			/*Bundle myBundle = new Bundle();
			myBundle.putInt(DEVICE_TYPE,2);
			myBundle.putString(DEVICE_NAME, "ACC7709");*/

			mPrinterService = new Messenger(service);

			/*Message msg = Message.obtain(null, PrintingService.MSG_REG_CLIENT);

			msg.setData(myBundle);

			msg.replyTo = mMessenger;


			try {
				mPrinterService.send(msg);
			} catch (RemoteException e) {
				Log.w(TAG, "Unable to register client to service.");
				e.printStackTrace();
			}*/
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			mPrinterService = null;
			mPrintingServiceBounnd = false;
		}
	};	




Is there a way I can connect to both devices without losing connection to either.

Thanks in advance.

This post has been edited by Ahleki: 19 December 2014 - 06:50 AM


Is This A Good Question/Topic? 0
  • +

Page 1 of 1