package com.lfk.justweengine.utils.blueTooth;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
import com.lfk.justweengine.R;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
/**
* Created by liufengkai on 16/1/20.
*/
public class BlueToothServer {
// Debugging
private static final String TAG = "BluetoothChat";
private static final boolean D = true;
// Message types sent from the BluetoothChatService Handler
public static final int MESSAGE_STATE_CHANGE = 1;
public static final int MESSAGE_READ = 2;
public static final int MESSAGE_WRITE = 3;
public static final int MESSAGE_DEVICE_NAME = 4;
public static final int MESSAGE_TOAST = 5;
// Key names received from the BluetoothChatService Handler
public static final String DEVICE_NAME = "device_name";
public static final String TOAST = "toast";
// Intent request codes
private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
private static final int REQUEST_ENABLE_BT = 3;
// Name of the connected device
private String mConnectedDeviceName = null;
// Array adapter for the conversation thread
private BluetoothChatService mChatService = null;
private BluetoothAdapter mBluetoothAdapter = null;
private Activity context;
private CharSequence mBlueToothState = null;
// msg handler
private BlueToothMsgHandler mHandler;
private ArrayList<String> mNewDeviceList;
private OnMessageBack onMessageBack = null;
public BlueToothServer(Activity context, OnMessageBack messageBack) {
this.context = context;
this.onMessageBack = messageBack;
this.mHandler = new BlueToothMsgHandler();
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if (mBluetoothAdapter == null) {
Toast.makeText(context, "Bluetooth is not available", Toast.LENGTH_LONG).show();
}
}
public void init() {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
// Otherwise, setup the chat session
} else {
if (mChatService == null) setupChat();
}
// Register for broadcasts when a device is discovered
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
context.registerReceiver(mReceiver, filter);
// Register for broadcasts when discovery has finished
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
context.registerReceiver(mReceiver, filter);
}
public void unBindService() {
if (mChatService != null) mChatService.stop();
if (mBluetoothAdapter != null) {
mBluetoothAdapter.cancelDiscovery();
}
// Unregister broadcast listeners
context.unregisterReceiver(mReceiver);
}
private void setupChat() {
Log.d(TAG, "setupChat()");
// Initialize the BluetoothChatService to perform bluetooth connections
mChatService = new BluetoothChatService(context, mHandler);
this.mNewDeviceList = new ArrayList<>();
}
/**
* handler for message
*/
@SuppressLint("HandlerLeak")
private class BlueToothMsgHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if (D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case BluetoothChatService.STATE_CONNECTED:
setStatus(context.getString(R.string.title_connected_to, mConnectedDeviceName));
break;
case BluetoothChatService.STATE_CONNECTING:
setStatus(R.string.title_connecting);
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
setStatus(R.string.title_not_connected);
break;
}
break;
case MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
onMessageBack.sendMessage(Arrays.toString(writeBuf));
break;
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
onMessageBack.getMessage(Arrays.toString(readBuf));
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
Toast.makeText(context, "Connected to "
+ mConnectedDeviceName, Toast.LENGTH_SHORT).show();
break;
case MESSAGE_TOAST:
Toast.makeText(context, msg.getData().getString(TOAST),
Toast.LENGTH_SHORT).show();
break;
}
}
}
/**
* set BlueTooth state
*
* @param s
*/
private void setStatus(CharSequence s) {
this.mBlueToothState = s;
}
private void setStatus(int res) {
this.mBlueToothState = context.getString(res);
}
/**
* enable for discover by others' phone
*/
public void ensureDiscoverable() {
if (D) Log.d(TAG, "ensure discoverable");
if (mBluetoothAdapter.getScanMode() !=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
context.startActivity(discoverableIntent);
}
}
/**
* send message
*
* @param message
*/
public void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
Toast.makeText(context, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService.write(send);
}
}
/**
* do discovery
*/
public void doDiscovery() {
if (D) Log.d(TAG, "doDiscovery()");
// If we're already discovering, stop it
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
// Request discover from BluetoothAdapter
mBluetoothAdapter.startDiscovery();
}
// The BroadcastReceiver that listens for discovered devices and
// changes the title when discovery is finished
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// If it's already paired, skip it, because it's been listed already
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
mNewDeviceList.add(device.getName() + "\n" + device.getAddress());
}
// When discovery is finished, change the Activity title
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
if (mNewDeviceList.size() == 0) {
mNewDeviceList.clear();
}
onMessageBack.getDevice(mNewDeviceList);
}
}
};
/**
* connect to a device
*
* @param address mac
* @param secure is secure?
*/
public void connectToDevice(String address, boolean secure) {
// Get the BluetoothDevice object
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device
mChatService.connect(device, secure);
}
public ArrayList<String> getPairedDevices() {
ArrayList<String> arrayList = new ArrayList<>();
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices, add each one to the ArrayAdapter
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
arrayList.add(device.getName() + "\n" + device.getAddress());
}
} else {
arrayList.clear();
}
return arrayList;
}
}