summaryrefslogblamecommitdiffstats
path: root/app/src/main/java/com/xc3fff0e/xmanager/BluetoothController.java
blob: 31b850be06e504d4ce4dc40581416d02e8544571 (plain) (tree)

































































































































































































































































































































































                                                                                                                                                                                                              
package com.xc3fff0e.xmanager;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.UUID;

public class BluetoothController {
public static final String STATE_NONE       = "none";
public static final String STATE_LISTEN     = "listen";
public static final String STATE_CONNECTING = "connecting";
public static final String STATE_CONNECTED  = "connected";

private AcceptThread acceptThread;
private ConnectThread connectThread;
private ConnectedThread connectedThread;

private String state = STATE_NONE;

private static BluetoothController instance;

public static synchronized BluetoothController getInstance() {
if(instance == null) {
instance = new BluetoothController();
}

return instance;
}

public synchronized void start(BluetoothConnect bluetoothConnect, BluetoothConnect.BluetoothConnectionListener listener, String tag, UUID uuid, BluetoothAdapter bluetoothAdapter) {
if (connectThread != null) {
connectThread.cancel();
connectThread = null;
}

if (connectedThread != null) {
connectedThread.cancel();
connectedThread = null;
}

if (acceptThread != null) {
acceptThread.cancel();
acceptThread = null;
}

acceptThread = new AcceptThread(bluetoothConnect, listener, tag, uuid, bluetoothAdapter);
acceptThread.start();}

public synchronized void connect(BluetoothDevice device, BluetoothConnect bluetoothConnect, BluetoothConnect.BluetoothConnectionListener listener, String tag, UUID uuid, BluetoothAdapter bluetoothAdapter) {
if (state.equals(STATE_CONNECTING)) {
if (connectThread != null) {
connectThread.cancel();
connectThread = null;
}
}

if (connectedThread != null) {
connectedThread.cancel();
connectedThread = null;
}

connectThread = new ConnectThread(device, bluetoothConnect, listener, tag, uuid, bluetoothAdapter);
connectThread.start();
}

public synchronized void connected(BluetoothSocket socket, final BluetoothDevice device, BluetoothConnect bluetoothConnect, final BluetoothConnect.BluetoothConnectionListener listener, final String tag) {
if (connectThread != null) {
connectThread.cancel();
connectThread = null;
}

if (connectedThread != null) {
connectedThread.cancel();
connectedThread = null;
}

if (acceptThread != null) {
acceptThread.cancel();
acceptThread = null;
}

connectedThread = new ConnectedThread(socket, bluetoothConnect, listener, tag);
connectedThread.start();

bluetoothConnect.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
HashMap<String, Object> deviceMap = new HashMap<>();
deviceMap.put("name", device.getName());
deviceMap.put("address", device.getAddress());

listener.onConnected(tag, deviceMap);
}
});
}

public synchronized void stop(BluetoothConnect bluetoothConnect, final BluetoothConnect.BluetoothConnectionListener listener, final String tag) {
if (connectThread != null) {
connectThread.cancel();
connectThread = null;
}

if (connectedThread != null) {
connectedThread.cancel();
connectedThread = null;
}

if (acceptThread != null) {
acceptThread.cancel();
acceptThread = null;
}

state = STATE_NONE;

bluetoothConnect.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
listener.onConnectionStopped(tag);
}
});
}

public void write(byte[] out) {
ConnectedThread r;

synchronized (this) {
if (!state.equals(STATE_CONNECTED)) return;
r = connectedThread;
}

r.write(out);
}

public void connectionFailed(BluetoothConnect bluetoothConnect, final BluetoothConnect.BluetoothConnectionListener listener, final String tag, final String message) {
state = STATE_NONE;

bluetoothConnect.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
listener.onConnectionError(tag, state, message);
}
});
}

public void connectionLost(BluetoothConnect bluetoothConnect, final BluetoothConnect.BluetoothConnectionListener listener, final String tag) {
state = STATE_NONE;

bluetoothConnect.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
listener.onConnectionError(tag, state, "Bluetooth connection is disconnected");
}
});
}

public String getState() {
return state;
}

private class AcceptThread extends Thread {
private BluetoothServerSocket serverSocket;

private BluetoothConnect bluetoothConnect;
private BluetoothConnect.BluetoothConnectionListener listener;
private String tag;

public AcceptThread(BluetoothConnect bluetoothConnect, BluetoothConnect.BluetoothConnectionListener listener, String tag, UUID uuid, BluetoothAdapter bluetoothAdapter) {
this.bluetoothConnect = bluetoothConnect;
this.listener = listener;
this.tag = tag;

try {
serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(tag, uuid);
} catch (Exception e) {
e.printStackTrace();
}

state = STATE_LISTEN;
}

@Override
public void run() {
BluetoothSocket bluetoothSocket;

while (!state.equals(STATE_CONNECTED)) {
try {
bluetoothSocket = serverSocket.accept();
} catch (Exception e) {
e.printStackTrace();
break;
}

if (bluetoothSocket != null) {
synchronized (BluetoothController.this) {
switch (state) {
case STATE_LISTEN:
case STATE_CONNECTING:
connected(bluetoothSocket, bluetoothSocket.getRemoteDevice(), bluetoothConnect, listener, tag);
break;
case STATE_NONE:
case STATE_CONNECTED:
try {
bluetoothSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}
}
}

public void cancel() {
try {
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

private class ConnectThread extends Thread {
private BluetoothDevice device;
private BluetoothSocket socket;

private BluetoothConnect bluetoothConnect;
private BluetoothConnect.BluetoothConnectionListener listener;
private String tag;
private BluetoothAdapter bluetoothAdapter;

public ConnectThread(BluetoothDevice device, BluetoothConnect bluetoothConnect, BluetoothConnect.BluetoothConnectionListener listener, String tag, UUID uuid, BluetoothAdapter bluetoothAdapter) {
this.device = device;
this.bluetoothConnect = bluetoothConnect;
this.listener = listener;
this.tag = tag;
this.bluetoothAdapter = bluetoothAdapter;

try {
socket = device.createRfcommSocketToServiceRecord(uuid);
} catch (Exception e) {
e.printStackTrace();
}

state = STATE_CONNECTING;
}

@Override
public void run() {
bluetoothAdapter.cancelDiscovery();

try {
socket.connect();
} catch (Exception e) {
try {
socket.close();
} catch (Exception e2) {
e2.printStackTrace();
}
connectionFailed(bluetoothConnect, listener, tag, e.getMessage());
return;
}

synchronized (BluetoothController.this) {
connectThread = null;
}

connected(socket, device, bluetoothConnect, listener, tag);
}

public void cancel() {
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

private class ConnectedThread extends Thread {
private BluetoothSocket socket;
private InputStream inputStream;
private OutputStream outputStream;

private BluetoothConnect bluetoothConnect;
private BluetoothConnect.BluetoothConnectionListener listener;
private String tag;

public ConnectedThread(BluetoothSocket socket, BluetoothConnect bluetoothConnect, BluetoothConnect.BluetoothConnectionListener listener, String tag) {
this.bluetoothConnect = bluetoothConnect;
this.listener = listener;
this.tag = tag;

this.socket = socket;

try {
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
} catch (Exception e) {
e.printStackTrace();
}

state = STATE_CONNECTED;
}

public void run() {
while (state.equals(STATE_CONNECTED)) {
try {
final byte[] buffer = new byte[1024];
final int bytes = inputStream.read(buffer);

bluetoothConnect.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
listener.onDataReceived(tag, buffer, bytes);
}
});
} catch (Exception e) {
e.printStackTrace();
connectionLost(bluetoothConnect, listener, tag);
break;
}
}
}

public void write(final byte[] buffer) {
try {
outputStream.write(buffer);

bluetoothConnect.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
listener.onDataSent(tag, buffer);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}

public void cancel() {
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}