From 2282a47967a066d89fa298deeae6b1ee6de4c095 Mon Sep 17 00:00:00 2001 From: Paul T Date: Tue, 12 Jan 2016 23:00:15 -0500 Subject: [PATCH] Updated BluetoothService and added some new methods to SimpleBluetooth and BluetoothUtility. --- .idea/modules.xml | 1 - app/app.iml | 12 +- .../bluetoothutilitydemo/TestActivity.java | 2 +- btutillib/btutillib.iml | 11 +- .../bluetoothutillib/SimpleBluetooth.java | 40 ++- .../utils/BluetoothService.java | 333 +++++++++++++++++- .../utils/BluetoothUtility.java | 32 ++ 7 files changed, 393 insertions(+), 38 deletions(-) diff --git a/.idea/modules.xml b/.idea/modules.xml index a82c253..95184eb 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,7 +3,6 @@ - diff --git a/app/app.iml b/app/app.iml index 906d843..3a92e28 100644 --- a/app/app.iml +++ b/app/app.iml @@ -65,22 +65,12 @@ - - - - - - - - - - - + diff --git a/app/src/main/java/com/devpaul/bluetoothutilitydemo/TestActivity.java b/app/src/main/java/com/devpaul/bluetoothutilitydemo/TestActivity.java index 8018327..6bb1b70 100644 --- a/app/src/main/java/com/devpaul/bluetoothutilitydemo/TestActivity.java +++ b/app/src/main/java/com/devpaul/bluetoothutilitydemo/TestActivity.java @@ -13,7 +13,7 @@ public class TestActivity extends BaseBluetoothActivity { @Override - public SimpleBluetoothListener getListener() { + public SimpleBluetoothListener getSimpleBluetoothListener() { return new SimpleBluetoothListener() { @Override public void onBluetoothDataReceived(byte[] bytes, String data) { diff --git a/btutillib/btutillib.iml b/btutillib/btutillib.iml index 2c423e4..db33ebe 100644 --- a/btutillib/btutillib.iml +++ b/btutillib/btutillib.iml @@ -65,23 +65,16 @@ + - - - - - - - - - + diff --git a/btutillib/src/main/java/com/devpaul/bluetoothutillib/SimpleBluetooth.java b/btutillib/src/main/java/com/devpaul/bluetoothutillib/SimpleBluetooth.java index 1cb345d..6b14cfe 100644 --- a/btutillib/src/main/java/com/devpaul/bluetoothutillib/SimpleBluetooth.java +++ b/btutillib/src/main/java/com/devpaul/bluetoothutillib/SimpleBluetooth.java @@ -21,8 +21,9 @@ import static com.devpaul.bluetoothutillib.utils.BluetoothUtility.InputStreamType; /** - * Created by Paul Tsouchlos - * Class for easily setting up bluetooth connections. + * Created by Paul T + * Class for easily setting up and managing bluetooth connections. Takes care of all the hard + * stuff for you. */ public class SimpleBluetooth { @@ -170,12 +171,6 @@ public SimpleBluetooth(Context context, Activity refActivity) { this.bluetoothUtility = new BluetoothUtility(mContext, mActivity, mHandler); //register the state change receiver. this.curType = InputStreamType.NORMAL; - - /* - Trying onActivityResult instead of this for now. - */ -// this.bluetoothBroadcastReceiver = BluetoothBroadcastReceiver -// .register(mContext, bluetoothBroadcastRecieverCallback); this.bluetoothStateReceiver = BluetoothStateReceiver .register(mContext, stateRecieverCallback); @@ -204,12 +199,6 @@ public SimpleBluetooth(Context context, Activity refActivity, BluetoothHandler h new NullPointerException("Custom BluetoothHandler cannot be null!"); this.bluetoothUtility = new BluetoothUtility(mContext, mActivity, customHandler); //register the state change receiver. - /* - Trying onActivityResult instead of this method. - */ -// this.bluetoothBroadcastReceiver = BluetoothBroadcastReceiver -// .register(mContext, bluetoothBroadcastRecieverCallback); - this.bluetoothStateReceiver = BluetoothStateReceiver .register(mContext, stateRecieverCallback); this.bluetoothPairingReceiver = BluetoothPairingReceiver @@ -277,7 +266,7 @@ public void handleMessage(Message message) { }; /** - * Method that must be called to set everything up for this service. + * Method that must be called to set everything up for this class. */ public boolean initializeSimpleBluetooth() { if(!bluetoothUtility.checkIfEnabled()) { @@ -285,6 +274,20 @@ public boolean initializeSimpleBluetooth() { } else { isInitialized = true; } + return isInitialized; + } + + /** + * Method that must be called (or initializeSimpleBluetooth()) to setup + * the simplebluetooth class. + * @return + */ + public boolean initializeSimpleBluetoothSilent() { + if(!bluetoothUtility.checkIfEnabled()) { + bluetoothUtility.enableBluetoothSilent(); + } else { + isInitialized = true; + } return isInitialized; } @@ -306,6 +309,13 @@ public void sendData(int data) { bluetoothUtility.sendData(data); } + /** + * Sends byte array data to the connected bluetooth device. + * @param data the data to send. + */ + public void sendData(byte[] data) { + bluetoothUtility.sendData(data); + } /** * Starts the device dialog to get a device to connect to. diff --git a/btutillib/src/main/java/com/devpaul/bluetoothutillib/utils/BluetoothService.java b/btutillib/src/main/java/com/devpaul/bluetoothutillib/utils/BluetoothService.java index 55e6c3d..2625a9a 100644 --- a/btutillib/src/main/java/com/devpaul/bluetoothutillib/utils/BluetoothService.java +++ b/btutillib/src/main/java/com/devpaul/bluetoothutillib/utils/BluetoothService.java @@ -1,17 +1,348 @@ package com.devpaul.bluetoothutillib.utils; +import android.app.NotificationManager; import android.app.Service; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; import android.content.Intent; +import android.os.Binder; import android.os.IBinder; +import com.devpaul.bluetoothutillib.handlers.BluetoothHandler; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.UUID; + /** - * Created by Paul Tsouchlos + * Created by Paul T. + * + * Bluetooth service class so you can connect to bluetooth devices persistently in an app + * background. */ public class BluetoothService extends Service { + /** + * Callback for the service. + */ + public interface BluetoothServiceCallback { + public void onDeviceConnected(BluetoothDevice device); + } + + /** + * Local binder + */ + private LocalBinder mLocalBinder = new LocalBinder(); + + /** + * Bluetooth device. + */ + private BluetoothDevice device; + + /** + * BluetoothAdapter instance for the service. + */ + private BluetoothAdapter adapter; + + /** + * The connect device thread for connecting to a device. + */ + private ConnectDeviceThread connectDeviceThread; + + /** + * Connected thread for when handling when the device is connected. + */ + private ConnectedThread connectedThread; + + /** + * Bluetooth socket holder for the created socket. + */ + private BluetoothSocket bluetoothSocket; + + /** + * Instance of a callback. + */ + private BluetoothServiceCallback callback; + + /** + * Notification Manager for if the service is sticky. + */ + private NotificationManager notificationManager; + + /** + * Handler for bluetooth. + */ + private BluetoothHandler bluetoothHandler; + + /** + * Stream type. + */ + private BluetoothUtility.InputStreamType streamType; + + /** + * Command for connecting to a device. + */ + public static final String CONNECT_BLUETOOTH_DEVICE = "startListeningToSocket"; + + /** + * Address of device. + */ + public static final String DEVICE_ADDRESS_EXTRA = "deviceAddressExtra"; + + /** + * Notification ID. + */ + public static final int FOREGROUND_NOTIFICATION_ID = 1; + + /** + * Stop service command. + */ + public static final String STOP_SERVICE_ACTION = "stopBluetoothServiceAction"; + + /** + * {@code UUID} for a normal device connection. + */ + private static final UUID NORMAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); + + @Override + public void onCreate() { + super.onCreate(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return super.onStartCommand(intent, flags, startId); + } @Override public IBinder onBind(Intent intent) { return null; } + + @Override + public void onRebind(Intent intent) { + super.onRebind(intent); + } + + @Override + public boolean onUnbind(Intent intent) { + return super.onUnbind(intent); + } + + public class LocalBinder extends Binder { + public BluetoothService getService() { + return BluetoothService.this; + } + } + + /** + * Write value to the connected device. + * @param message + */ + public void write(String message) { + if(connectedThread != null) { + if(connectedThread.isAlive()) { + connectedThread.write(message); + } + } + + } + + /** + * Used to connect a device a generic socket. + */ + private class ConnectDeviceThread extends Thread { + + private final BluetoothSocket mmSocket; + private final BluetoothDevice mmDevice; + + public ConnectDeviceThread(BluetoothDevice device) { + // Use a temporary object that is later assigned to mmSocket, + // because mmSocket is final + + BluetoothSocket tmp = null; + mmDevice = device; + + // Get a BluetoothSocket to connect with the given BluetoothDevice + try { + // MY_UUID is the app's UUID string, also used by the server code + tmp = device.createRfcommSocketToServiceRecord(NORMAL_UUID); + } catch (IOException e) { + + } + mmSocket = tmp; + } + + public void run() { + // Cancel discovery because it will slow down the connection + adapter.cancelDiscovery(); + + try { + // Connect the device through the socket. This will block + // until it succeeds or throws an exception + mmSocket.connect(); + } catch (IOException connectException) { + // Unable to connect; close the socket and get out + try { + mmSocket.close(); + } catch (IOException closeException) { } + return; + } + if(callback != null) { + callback.onDeviceConnected(mmDevice); + } + // Do work to manage the connection (in a separate thread) + manageConnectedSocket(mmSocket); + } + + /** Will cancel an in-progress connection, and close the socket */ + public void cancel() { + try { + mmSocket.close(); + } catch (IOException e) { } + } + } + + /** + * Helper method for managing a connected socket. + * @param mmSocket + */ + private void manageConnectedSocket(BluetoothSocket mmSocket) { + connectedThread = new ConnectedThread(mmSocket); + connectedThread.start(); + } + + /** + * Thread for when you're connected. + */ + private class ConnectedThread extends Thread { + private final BluetoothSocket mmSocket; + private final InputStream mInputStream; + private final OutputStream mOutputStream; + + public ConnectedThread(BluetoothSocket socket) { + mmSocket = socket; + bluetoothSocket = 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) { +// Log.d("ConnectedThread", e.getMessage()); + } + + mInputStream = tmpIn; + mOutputStream = tmpOut; + } + + public void run() { + byte[] buffer; // buffer store for the stream + int bytes; // bytes returned from read() + BufferedReader reader; + + if(streamType == BluetoothUtility.InputStreamType.NORMAL) { + // Keep listening to the InputStream until an exception occurs + while (true) { + try { + bytes = mInputStream.available(); + if(bytes > 0) { + buffer = new byte[bytes]; + // Read from the InputStream + bytes = mInputStream.read(buffer); + // Send the obtained bytes to the UI activity + bluetoothHandler.obtainMessage(BluetoothHandler.MESSAGE_READ, bytes, -1, buffer) + .sendToTarget(); + } + } catch (IOException e) { + break; + } + } + //Buffered reader. + } else { + reader = new BufferedReader(new InputStreamReader(mInputStream)); + // Keep listening to the InputStream until an exception occurs + while (true) { + try { + if(reader.ready()) { + String message = reader.readLine(); + bluetoothHandler.obtainMessage(BluetoothHandler.MESSAGE_READ, -1, -1, message) + .sendToTarget(); + } +// bytes = mInputStream.available(); +// if(bytes > 0) { +// buffer = new byte[bytes]; +// // Read from the InputStream +// bytes = mInputStream.read(buffer); +// // Send the obtained bytes to the UI activity +// bluetoothHandler.obtainMessage(BluetoothHandler.MESSAGE_READ, bytes, -1, buffer) +// .sendToTarget(); +// } + } catch (IOException e) { + break; + } + } + } + + + } + + /** + * Called to send a string across the bluetooth socket. + * @param string the string to send. + */ + public void write(String string) { + if(mOutputStream != null) { + try { +// Log.d("ConnectedThread", "Writing data: " + string); + mOutputStream.write(string.getBytes()); + } catch (IOException e) { +// Log.d("ConnectedThread",e.getMessage()); + } + } + } + + /** + * Called to send bytes across the bluetooth socket. + * @param bytes the bytes to send. + */ + public void write(byte[] bytes) { + if(mOutputStream != null) { + try { + mOutputStream.write(bytes); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public void write(int i) { + if(mOutputStream != null) { + + try { + mOutputStream.write(i); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /* Call this from the main activity to shutdown the connection */ + public void cancel() { + try { + mmSocket.close(); + } catch (IOException e) { } + } + } } diff --git a/btutillib/src/main/java/com/devpaul/bluetoothutillib/utils/BluetoothUtility.java b/btutillib/src/main/java/com/devpaul/bluetoothutillib/utils/BluetoothUtility.java index b64610f..ed1b946 100644 --- a/btutillib/src/main/java/com/devpaul/bluetoothutillib/utils/BluetoothUtility.java +++ b/btutillib/src/main/java/com/devpaul/bluetoothutillib/utils/BluetoothUtility.java @@ -278,6 +278,17 @@ public void enableBluetooth() { } } + /** + * Enables bluetooth silently. I.e. without user interaction. + */ + public void enableBluetoothSilent() { + if(bluetoothAdapter != null) { + if(!checkIfEnabled()) { + bluetoothAdapter.enable(); + } + } + } + /** * Sets the input stream type for the bluetooth device input stream. * @param type, the input stream type. @@ -446,6 +457,27 @@ public void sendData(String data) { } } + /** + * Sends a byte array of data to the connected bluetooth device. + * @param data the data to send. + */ + public void sendData(byte[] data) { + //check to see if the socket is connected first. + if(bluetoothSocket != null) { + if(bluetoothSocket.isConnected()){ + if(connectedThread != null) { + connectedThread.write(data); + } else { +// Log.d("BluetoothUtility", "Connected Thread is null"); + } + } else { +// Log.d("BluetoothUtility", "Socket is not connected."); + } + } else { +// Log.d("BluetoothUtility", "Socket is null"); + } + } + /** * Cancels the scanning process. */