由于前段时间,需要蓝牙操作一些东西。但是没有写过蓝牙连接与蓝牙操作等一系列的东西。
然后就去网上找找大家写的。到现在。已经结束了这个蓝牙的开发。
安卓端蓝牙操作。主要需要如下类
BluetoothAdapter 通过名字,可以了解到这是一个蓝牙适配器的类。可以获取到蓝牙的状态。开关,。扫描等一系列的常规操作
BluetoothSocket 这个呢,是一个蓝牙的socket。不做过多的介绍。和普通socket一样
BluetoothDevice 这个类是获取远程设备的类。
有了上面3个类。蓝牙的基本操作就可以实现了。
当然。,蓝牙的操作需要广播来支持、。下面是具体的代码。
蓝牙相关广播
Action值 说明
ACTION_STATE_CHANGED 蓝牙状态值发生改变
ACTION_SCAN_MODE_CHANGED 蓝牙扫描状态(SCAN_MODE)发生改变
ACTION_DISCOVERY_STARTED 蓝牙扫描过程开始
ACTION_DISCOVERY_FINISHED 蓝牙扫描过程结束
ACTION_LOCAL_NAME_CHANGED 蓝牙设备Name发生改变
ACTION_REQUEST_DISCOVERABLE 请求用户选择是否使该蓝牙能被扫描
PS:如果蓝牙没有开启,用户点击确定后,会首先开启蓝牙,继而设置蓝牙能被扫描。
ACTION_REQUEST_ENABLE 请求用户选择是否打开蓝牙
ACTION_FOUND (该常量字段位于BluetoothDevice类中)
说明:蓝牙扫描时,扫描到任一远程蓝牙设备时,会发送此广播。
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {//开始扫描蓝牙时候的广播
mDeviceList.clear();
mAdapter.notifyDataSetChanged();
}
if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //这个广播是扫描结束,蓝牙发送的广播
if (progressDialog!=null){
progressDialog.cancel();
progressDialog=null;
}
showToast("搜素完成");
}
if (BluetoothDevice.ACTION_FOUND.equals(action)) { //当扫描到蓝牙设备时,会发送这个广播
mDeviceList.add((BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
mAdapter.notifyDataSetChanged();
}
if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) { //蓝牙扫描状态(SCAN_MODE)发生改变
if (intent.getIntExtra("android.bluetooth.adapter.extra.SCAN_MODE", 0) == 23) {
}
}
if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) { //绑定时候的广播
BluetoothDevice remoteDevice = (BluetoothDevice) intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE");
if (remoteDevice == null) {
showToast("no device");
return;
}
int status = intent.getIntExtra("android.bluetooth.device.extra.BOND_STATE", 0);
if (status == 12) {
showToast("配对完成 " + remoteDevice.getName());
blueToothUtils.searchDevices();
showToast("刷新列表中 ");
} else if (status == 11) {
showToast("正在配对 " + remoteDevice.getName());
} else if (status == 10) {
showToast("配对失败 " + remoteDevice.getName());
}
}
}
};
//设置要监听的广播。
void initView(){
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
mContext.registerReceiver(mReceiver, filter);
}
上面的设置完成以后
编写一个蓝牙工具类进行使用。方便以后的开发。
在一开始。网上找了一些蓝牙的操作工具类。但是多多少少都有写瑕疵。
大多数都是2个手机通信。无法和蓝牙单片机模块通信。
具体的蓝牙操作类如下,这个工具类都是我在网上的大多数工具类中攒在一起的。里面有些方法也没用。我也就不删了。在接收数据的时候。如果是单片机发过来的话,数据会接收不完全。这里,将原来类方法更改了一下。、大家在接收数据时,尽量选择一个用不到的数字或者字母等,来当做结束位。进行判断、工具类里面的注释基本都有。
在网上找资料时,发现2个工具类,一个如下,看着比较简单,大家容易懂,还有一个。都是英文,后面翻译了一下,也放在文章最后吧。其实思路都一样。喜欢那个,用那个
工具类如下:
public class BlueToothUtils {
private static final String TAG = "BlueToothUtils";
private Context mContext;
public static BlueToothUtils sInstance;
private BluetoothAdapter mBA;
private SharedPreferences sp;
// UUID.randomUUID()随机获取UUID
private final UUID MY_UUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
// 连接对象的名称
private final String NAME = "Chaoba";
// 这里本身即是服务端也是客户端,需要如下类
private BluetoothSocket mSocket;
private BluetoothDevice mOldDevice;
private BluetoothDevice mCurDevice;
// 输出流_客户端需要往服务端输出
private OutputStream os;
private InputStream inputStream;
//线程类的实例
private AcceptThread ac;
private Handler mhandler;
private Handler handler2;
private BlueToothUtils.Readtask readtask;
public static synchronized BlueToothUtils getInstance() {
if (sInstance == null) {
sInstance = new BlueToothUtils();
}
return sInstance;
}
public BlueToothUtils() {
mBA = BluetoothAdapter.getDefaultAdapter();
ac = new AcceptThread();
}
public void setContext(Context context) {
this.mContext = context;
}
public void setHandler(Handler handler){
this.mhandler=handler;
}
public void setHandler2(Handler handler2){
this.handler2=handler2;
}
public BluetoothAdapter getBA() {
return mBA;
}
public AcceptThread getAc() {
return ac;
}
public BluetoothDevice getCurDevice() {
return mCurDevice;
}
/**
* 判断是否打开蓝牙
*
* @return
*/
public boolean isEnabled() {
if (mBA.isEnabled()) {
return true;
}
return false;
}
/**
* 搜索设备
*/
public void searchDevices() {
// 判断是否在搜索,如果在搜索,就取消搜索
if (mBA.isDiscovering()) {
mBA.cancelDiscovery();
}
// 开始搜索
mBA.startDiscovery();
Log.e(TAG, "正在搜索...");
}
/**
* 获取已经配对的设备
*
* @return
*/
public List<BluetoothDevice> getBondedDevices() {
List<BluetoothDevice> devices = new ArrayList<>();
Set<BluetoothDevice> pairedDevices = mBA.getBondedDevices();
// 判断是否有配对过的设备
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
devices.add(device);
Log.e(TAG, "BondedDevice:" + device.getName());
}
}
return devices;
}
/**
* 与设备配对
*
* @param device
*/
public void createBond(BluetoothDevice device) {
try {
Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
createBondMethod.invoke(device);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 与设备解除配对
*
* @param device
*/
public void removeBond(BluetoothDevice device) {
try {
Method removeBondMethod = device.getClass().getMethod("removeBond");
removeBondMethod.invoke(device);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @param device
* @param str 设置PIN码
* @return
*/
public boolean setPin(BluetoothDevice device, String str) {
try {
Method removeBondMethod = device.getClass().getDeclaredMethod("setPin",
new Class[]{byte[].class});
Boolean returnValue = (Boolean) removeBondMethod.invoke(device,
new Object[]{str.getBytes()});
Log.e("returnValue", "" + returnValue);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
/**
* 取消用户输入
*/
public boolean cancelPairingUserInput(BluetoothDevice device) {
Boolean returnValue = false;
try {
Method createBondMethod = device.getClass().getMethod("cancelPairingUserInput");
returnValue = (Boolean) createBondMethod.invoke(device);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// cancelBondProcess()
return returnValue.booleanValue();
}
/**
* 取消配对
*/
public boolean cancelBondProcess(BluetoothDevice device) {
Boolean returnValue = null;
try {
Method createBondMethod = device.getClass().getMethod("cancelBondProcess");
returnValue = (Boolean) createBondMethod.invoke(device);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return returnValue.booleanValue();
}
/**
* @param strAddr
* @param strPsw
* @return
*/
public boolean pair(String strAddr, String strPsw) {
boolean result = false;
mBA.cancelDiscovery();
if (!mBA.isEnabled()) {
mBA.enable();
}
if (!BluetoothAdapter.checkBluetoothAddress(strAddr)) { // 检查蓝牙地址是否有效
Log.d("mylog", "devAdd un effient!");
}
BluetoothDevice device = mBA.getRemoteDevice(strAddr);
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
Log.d("mylog", "NOT BOND_BONDED");
try {
setPin(device, strPsw); // 手机和蓝牙采集器配对
createBond(device);
result = true;
} catch (Exception e) {
Log.d("mylog", "setPiN failed!");
e.printStackTrace();
} //
} else {
Log.d("mylog", "HAS BOND_BONDED");
try {
createBond(device);
setPin(device, strPsw); // 手机和蓝牙采集器配对
createBond(device);
result = true;
} catch (Exception e) {
Log.d("mylog", "setPiN failed!");
e.printStackTrace();
}
}
return result;
}
/**
* 获取device.getClass()这个类中的所有Method
*
* @param clsShow
*/
public void printAllInform(Class clsShow) {
try {
// 取得所有方法
Method[] hideMethod = clsShow.getMethods();
int i = 0;
for (; i < hideMethod.length; i++) {
Log.e("method name", hideMethod[i].getName() + ";and the i is:" + i);
}
// 取得所有常量
Field[] allFields = clsShow.getFields();
for (i = 0; i < allFields.length; i++) {
Log.e("Field name", allFields[i].getName());
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 打开蓝牙
*/
public void openBlueTooth() {
if (!mBA.isEnabled()) {
// 弹出对话框提示用户是后打开
/*Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);*/
// 不做提示,强行打开
mBA.enable();
showToast("打开蓝牙");
} else {
showToast("蓝牙已打开");
}
}
/**
* 关闭蓝牙
*/
public void closeBlueTooth() {
mBA.disable();
showToast("关闭蓝牙");
}
/**
* 弹出Toast窗口
*
* @param message
*/
private void showToast(String message) {
if (mContext != null) {
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
} else {
Log.e(TAG, "message:" + message);
}
}
/**
* 主动连接蓝牙
*
* @param device
*/
public void connectDevice(BluetoothDevice device) {
// 判断是否在搜索,如果在搜索,就取消搜索
if (mBA.isDiscovering()) {
mBA.cancelDiscovery();
}
try {
// 获得远程设备
if (mCurDevice == null || mCurDevice != mOldDevice) {
mCurDevice = mBA.getRemoteDevice(device.getAddress());
mOldDevice = mCurDevice;
Log.e(TAG, "device:" + mCurDevice);
// sp.edit().putString("device","device:"+mCurDevice).commit();
mSocket = mCurDevice.createRfcommSocketToServiceRecord(MY_UUID);
// 连接
// mSocket.connect();
// boolean connected = mSocket.isConnected();
// if (connected){
//
// // 获得输出流
// os = mSocket.getOutputStream();
// inputStream=mSocket.getInputStream();
// while (true){
// readDataFromServer();
// }
// }
new Thread(new Runnable() {
@Override
public void run() {
try {
mSocket.connect();
os = mSocket.getOutputStream();
mhandler.sendEmptyMessage(10);
readtask = new BlueToothUtils.Readtask(); //连接成功后开启读取数据的线程
readtask.start();
mContext.getSharedPreferences("demo",Context.MODE_PRIVATE).edit().putString("device","已连接").commit();
} catch (IOException e) {
mhandler.sendEmptyMessage(11);
e.printStackTrace();
}
}
}).start();
}
// 如果成功获得输出流
} catch (IOException e) {
e.printStackTrace();
mhandler.sendEmptyMessage(11);
}
}
public static final int CONNECT_FAILED=1;
public static final int CONNECT_SUCCESS=5;
public static final int READ_FAILED=2;
public static final int WRITE_FAILED=3;
public static final int DATA=4;
private boolean isConnect=false;
/**
*开辟连接线程任务
*/
public void connectTow(final BluetoothDevice device){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
BluetoothSocket tmp = null;
Method method;
try {
method = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
tmp = (BluetoothSocket) method.invoke(device, 1);
} catch (Exception e) {
// setState(CONNECT_FAILED);
Log.e("TAG", e.toString());
}
mSocket = tmp;
try {
mSocket.connect();
isConnect = true;
// setState(CONNECT_SUCCESS);
readtask = new BlueToothUtils.Readtask(); //连接成功后开启读取数据的线程
readtask.start();
} catch (Exception e) {
Log.e("TAG", e.toString());
}
}
});
new Thread(thread).start();
}
/**
*开辟线程读任务
*/
public class Readtask extends Thread{
@Override
public void run(){
// byte[] buffer = new byte[9999];
// int bytes;
// InputStream inputStream ; //建立输入流读取数据
// while (true) {
// try {
// inputStream = mSocket.getInputStream();
// if ((bytes = inputStream.read(buffer)) > 0) {
// byte[] buf_data= new byte[bytes];
// for (int i = 0; i < bytes; i++) {
// buf_data[i] = buffer[i];
// }
// String s = new String(buf_data);
//
// setState(1,s);
//
// }
// } catch (IOException e) {
//
// Log.e("TAG", e.toString());
// break;
// }
// }
byte[] tt = new byte[100];
try {
int ch;
inputStream = mSocket.getInputStream();
int i;
while (true) {
synchronized (this) {
i=0;
while ((ch=inputStream.read())!='#'){
if (ch!=-1){
tt[i]=(byte)ch;
i++;
}
}
if (tt.length > 0) {
String s = new String(tt, "GBK");
System.out.println(s);
setState(1,s);
}else {
System.out.println(111);
}
}
}
} catch (IOException e) {
e.printStackTrace();
Message message=new Message();
message.obj="连接已断开,请重新连接";
handler.sendMessage(message);
}
if (mSocket != null) {
try {
mSocket.close();
} catch (IOException e) {
Log.e("TAG", e.toString());
}
}
}
public void cancel() {
try {
mSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
/**
*开辟线程写任务
*/
public class WriteTask extends Thread{
private String srt;
public WriteTask(String str){
this.srt=str;
}
@Override
public void run(){
OutputStream outputStream=null;
byte[] st=srt.getBytes();
try{
outputStream=mSocket.getOutputStream();
outputStream.write(st);
}catch (Exception e){
e.printStackTrace();
}
}
}
private void setState(int mes,String str){
Message message=new Message();
message.what=mes;
message.obj=str;
handler2.sendMessage(message);
}
/**
* 传输数据
*
* @param message
*/
public void write(String message) {
try {
if (os != null) {
os.write(message.getBytes("GBK"));
}
Log.e(TAG, "write:" + message);
handler2.sendEmptyMessage(3);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Stop all threads
*/
public synchronized void stops() {
if (readtask != null) {readtask.cancel(); readtask = null;}
Message message=new Message();
message.obj="关闭所有线程";
handler.sendMessage(message);
}
public void initSP(){
sp=mContext.getSharedPreferences("demo",Context.MODE_PRIVATE);
}
// 服务端,需要监听客户端的线程类
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
showToast(String.valueOf(msg.obj));
Log.e(TAG, "服务端:" + msg.obj);
super.handleMessage(msg);
}
};
// 线程服务类
public class AcceptThread extends Thread {
private BluetoothServerSocket serverSocket;
private BluetoothSocket socket;
// 输入 输出流
private OutputStream os;
private InputStream is;
public AcceptThread() {
try {
serverSocket = mBA.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
// 截获客户端的蓝牙消息
try {
socket = serverSocket.accept(); // 如果阻塞了,就会一直停留在这里
is = socket.getInputStream();
os = socket.getOutputStream();
while (true) {
synchronized (this) {
byte[] tt = new byte[is.available()];
if (tt.length > 0) {
is.read(tt, 0, tt.length);
Message msg = new Message();
msg.obj = new String(tt, "GBK");
Log.e(TAG, "客户端:" + msg.obj);
handler.sendMessage(msg);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
第二个工具类
/**
*建立和管理与其他设备的BT连接。
*它有一个线程来侦听传入的连接,一个线程
*用于与设备连接,以及用于执行数据的线程
*连接时的传输。
*/
public class BTService {
// 表示当前连接状态的常量
public static final int STATE_NONE = 0; // 我们什么也不做
public static final int STATE_LISTEN = 1; // 现在监听传入的连接
public static final int STATE_CONNECTING = 2; // 现在启动输出连接
public static final int STATE_CONNECTED = 3; // 现在连接到远程设备
private static final String TAG = "BTConnection";
// 创建服务器套接字时SDP记录的名称
private static final String MY_NAME = "BTConnection";
//引用:[来自Android SDK文档]
//如果您正在连接蓝牙串行板,则尝试使用众所周知的
//SPP UUID 000 000 110~00 0 0 0 0 0 0 0 0 0 0 0 5 5 F9B34 FB。
// 但是,如果您正在连接Android对等体,那么请生成您自己的
//
///独特的UUID。
private static final UUID MY_UUID =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// 成员字段
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mAcceptThread;
private ConnectThread mConnThread;
private ConnectedThread mConnectedThread;
private int mState;
private final Context mContext;
public static BTService sInstance;
/**
* Constructor. Prepares a new BT session.
*
* @param handler A Handler to send message back to the UI Activity.
* 构造函数。准备新的BT会话。 * * @param handler一个Handler,用于将消息发送回UI Activity。
*/
public BTService(Context context, Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
mContext = context;
}
/**
* 判断是否打开蓝牙
*
* @return
*/
public boolean isEnabled() {
if (mAdapter.isEnabled()) {
return true;
}
return false;
}
/**
* 搜索设备
*/
public void searchDevices() {
// 判断是否在搜索,如果在搜索,就取消搜索
if (mAdapter.isDiscovering()) {
mAdapter.cancelDiscovery();
}
// 开始搜索
mAdapter.startDiscovery();
Log.e(TAG, "正在搜索...");
}
/**
* 获取已经配对的设备
*
* @return
*/
public List<BluetoothDevice> getBondedDevices() {
List<BluetoothDevice> devices = new ArrayList<>();
Set<BluetoothDevice> pairedDevices = mAdapter.getBondedDevices();
// 判断是否有配对过的设备
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
devices.add(device);
Log.e(TAG, "BondedDevice:" + device.getName());
}
}
return devices;
}
/**
* 与设备配对
*
* @param device
*/
public void createBond(BluetoothDevice device) {
try {
Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
createBondMethod.invoke(device);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 与设备解除配对
*
* @param device
*/
public void removeBond(BluetoothDevice device) {
try {
Method removeBondMethod = device.getClass().getMethod("removeBond");
removeBondMethod.invoke(device);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @param device
* @param str 设置PIN码
* @return
*/
public boolean setPin(BluetoothDevice device, String str) {
try {
Method removeBondMethod = device.getClass().getDeclaredMethod("setPin",
new Class[]{byte[].class});
Boolean returnValue = (Boolean) removeBondMethod.invoke(device,
new Object[]{str.getBytes()});
Log.e("returnValue", "" + returnValue);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
/**
* 取消用户输入
*/
public boolean cancelPairingUserInput(BluetoothDevice device) {
Boolean returnValue = false;
try {
Method createBondMethod = device.getClass().getMethod("cancelPairingUserInput");
returnValue = (Boolean) createBondMethod.invoke(device);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// cancelBondProcess()
return returnValue.booleanValue();
}
/**
* 取消配对
*/
public boolean cancelBondProcess(BluetoothDevice device) {
Boolean returnValue = null;
try {
Method createBondMethod = device.getClass().getMethod("cancelBondProcess");
returnValue = (Boolean) createBondMethod.invoke(device);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return returnValue.booleanValue();
}
/**
* @param strAddr
* @param strPsw
* @return
*/
public boolean pair(String strAddr, String strPsw) {
boolean result = false;
mAdapter.cancelDiscovery();
if (!mAdapter.isEnabled()) {
mAdapter.enable();
}
if (!BluetoothAdapter.checkBluetoothAddress(strAddr)) { // 检查蓝牙地址是否有效
Log.d("mylog", "devAdd un effient!");
}
BluetoothDevice device = mAdapter.getRemoteDevice(strAddr);
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
Log.d("mylog", "NOT BOND_BONDED");
try {
setPin(device, strPsw); // 手机和蓝牙采集器配对
createBond(device);
result = true;
} catch (Exception e) {
Log.d("mylog", "setPiN failed!");
e.printStackTrace();
} //
} else {
Log.d("mylog", "HAS BOND_BONDED");
try {
createBond(device);
setPin(device, strPsw); // 手机和蓝牙采集器配对
createBond(device);
result = true;
} catch (Exception e) {
Log.d("mylog", "setPiN failed!");
e.printStackTrace();
}
}
return result;
}
/**
* 获取device.getClass()这个类中的所有Method
*
* @param clsShow
*/
public void printAllInform(Class clsShow) {
try {
// 取得所有方法
Method[] hideMethod = clsShow.getMethods();
int i = 0;
for (; i < hideMethod.length; i++) {
Log.e("method name", hideMethod[i].getName() + ";and the i is:" + i);
}
// 取得所有常量
Field[] allFields = clsShow.getFields();
for (i = 0; i < allFields.length; i++) {
Log.e("Field name", allFields[i].getName());
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 打开蓝牙
*/
public void openBlueTooth() {
if (!mAdapter.isEnabled()) {
// 弹出对话框提示用户是后打开
/*Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);*/
// 不做提示,强行打开
mAdapter.enable();
showToast("打开蓝牙");
} else {
showToast("蓝牙已打开");
}
}
/**
* 关闭蓝牙
*/
public void closeBlueTooth() {
mAdapter.disable();
showToast("关闭蓝牙");
}
/**
* 弹出Toast窗口
*
* @param message
*/
private void showToast(String message) {
if (mContext != null) {
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
} else {
Log.e(TAG, "message:" + message);
}
}
public static synchronized BTService getInstance(Context context, Handler handler) {
if (sInstance == null) {
sInstance = new BTService(context,handler);
}
return sInstance;
}
public BluetoothAdapter getBA() {
return mAdapter;
}
/**
* Return the current connection state.
*
* @return mState current connection state
* 返回当前连接状态。 * * @return mState当前连接状态
*/
public synchronized int getState() {
return mState;
}
/**
* Set the current state of BT connection.
*
* @param state An integer defining the current connection state
*
* *设置BT连接的当前状态。 * * @param state定义当前连接状态的整数
*/
private synchronized void setState(int state) {
Log.d(TAG, "setState() " + mState + "-> " + state);
mState = state;
// Give the new state to the Handler so the UI Activity can update
//将新状态提供给处理程序,以便UI活动可以更新
mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
/**
* Start the BT service. Specifically start AcceptThread to begin a
* session in listening (server) mode. Called by the Activity onResume()
* *启动BT服务。具体来说,启动AcceptThread以在侦听(服务器)模式下开始*会话。由Activity onResume()调用
*/
public synchronized void start() {
Log.d(TAG, "start");
// Cancel any thread attempting to make a connection
//取消任何尝试建立连接的线程
if (mConnThread != null) {
mConnThread.cancel();
mConnThread = null;
}
// Cancel any thread currently running a connection
//取消当前正在运行连接的任何线程
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
setState(STATE_LISTEN);
// Start the thread to listen on a BluetoothServerSocket
//启动线程以侦听BluetoothServerSocket
if (mAcceptThread == null) {
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
}
/**
* Start the ConnThread to initiate a connection to a remote device.
*启动ConnThread以启动与远程设备的连接。
* @param device The BluetoothDevice to connect
*/
public synchronized void connect(BluetoothDevice device) {
Log.d(TAG, "Connect to: " + device);
// Cancel any thread attempting to make a connection
//取消任何尝试建立连接的线程
if (mState == STATE_CONNECTING) {
if (mConnThread != null) {
mConnThread.cancel();
mConnThread = null;
}
}
// Cancel any thread currently running a connection
//取消当前正在运行连接的任何线程
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to connect with the given device
//启动线程以连接给定设备
mConnThread = new ConnectThread(device);
mConnThread.start();
setState(STATE_CONNECTING);
}
/**
* 启动ConnectedThread以开始管理蓝牙连接。
*
* @param socket 连接所在的BluetoothSocket
* @param device 已连接的BluetoothDevice
*/
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
Log.d(TAG, "Connected");
// 取消完成连接的线程
if (mConnThread != null) {
mConnThread.cancel();
mConnThread = null;
}
//取消当前正在运行连接的任何线程
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
//取消接受线程,因为我们只想连接到一个设备
if (mAcceptThread != null) {
mAcceptThread.cancel();
mAcceptThread = null;
}
//启动线程来管理连接并执行传输
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
// 将已连接设备的名称发送回UI活动
Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(Constants.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
/**
* 停止所有线程。
*/
public synchronized void stop() {
Log.d(TAG, "stop");
if (mConnThread != null) {
mConnThread.cancel();
mConnThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mAcceptThread != null) {
mAcceptThread.cancel();
mAcceptThread = null;
}
setState(STATE_NONE);
}
/**
* 以不同步的方式写入ConnectedThread。
*
* @param content 要写入的字节
* @see
*/
public void write(String content) {
//创建临时对象
ConnectedThread r;
//同步ConnectedThread的副本
synchronized (this) {
if (mState != STATE_CONNECTED) {
Log.d(TAG, "State: " + getState());
return;
}
r = mConnectedThread;
}
//执行写入不同步
r.write(content);
}
/**
* 指示连接尝试失败并通知UI活动。
*/
private void connectionError(String errMsg) {
Log.e(TAG, "Connection Error:" + errMsg);
// 将失败消息发送回活动
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST, errMsg);
msg.setData(bundle);
mHandler.sendMessage(msg);
// 启动服务以重新启动侦听模式
BTService.this.start();
}
/**
*此线程在侦听传入连接时运行。它表现得很好
*像服务器端客户端。它会一直运行,直到接受连接
*(或直到取消)。
*/
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
//使用稍后分配给mmServerSocket的临时对象
//因为mmServerSocket是最终的
BluetoothServerSocket tmp = null;
try {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(MY_NAME, MY_UUID);
} catch (IOException e) {
Log.e(TAG, "套接字听不通", e);
}
mmServerSocket = tmp;
}
public void run() {
Log.d(TAG, "套接字开始");
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
//这是一个阻止调用,只会返回
//成功连接或异常
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "套接字accept()失败", e);
break;
}
//如果接受了连接
if (socket != null) {
synchronized (BTService.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
//情况正常启动连接的线程。
connected(socket, socket.getRemoteDevice());
break;
case STATE_NONE:
case STATE_CONNECTED:
//未准备好或已连接。终止新套接字。
try {
socket.close();
} catch (IOException e) {
Log.e(TAG, "无法关闭不需要的套接字", e);
}
break;
}
}
}
}
}
public void cancel() {
Log.d(TAG, "套接字取消");
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "服务器的套接字close()失败", e);
}
}
}
/***此线程在尝试进行传出连接时运行
*带有设备。它直接通过;连接
*成功或失败。
*/
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
//获取与之连接的BluetoothSocket
//给出了BluetoothDevice
try {
// device.fetchUuidsWithSdp();
// ParcelUuid[] uuids = device.getUuids();
// for (ParcelUuid u : uuids) {
// Log.d(TAG, u.getUuid().toString());
// }
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.e(TAG, "Socket create() failed", e);
}
mmSocket = tmp;
}
public void run() {
try {
mmSocket.connect();
} catch (IOException e) {
e.printStackTrace();
try {
mmSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
connectionError("连接失败");
return;
}
//重置ConnectThread,因为我们已经完成了
synchronized (BTService.this) {
mConnThread = null;
}
//启动连接的线程
connected(mmSocket, mmDevice);
}
public void cancel() {
Log.d(TAG, "Socket cancel");
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Socket close() of server failed", e);
}
}
}
/**
*此线程在与远程设备连接期间运行。
*它处理所有传入和传出传输。
*/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "create ConnectedThread");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
//获取BluetoothSocket输入和输出流
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.d(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[512];
byte[] ret = null;
//连接时继续收听inputStream
while (true) {
try {
//从InputStream中读取
int bytes = mmInStream.read(buffer);
Log.e(TAG, "length: " + bytes);
for (int i = 0; i < bytes; i++) {
if ((buffer[i] & 0xFF) == 255) {
ret = Arrays.copyOfRange(buffer, 0, i + 1);
break;
}
}
Log.e(TAG, "data: " + ret);
//将获取的字节发送到UI活动
mHandler.obtainMessage(Constants.MESSAGE_READ, -1, -1, ret).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionError("连接失败");
//启动服务以重新启动侦听模式
BTService.this.start();
break;
}
}
}
/**
* 写入已连接的OutStream。
*
* @param content The bytes to write
*/
public void write(String content) {
try {
mmOutStream.write(content.getBytes());
// 将发送的消息共享回UI活动
mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, content).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "E写入期间的xception", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "connect()的连接套接字失败", e);
}
}
}