您的位置:首页 > 移动开发 > Android开发

android 通过蓝牙和设备通信 收发数据

2015-05-21 17:19 465 查看
这边由于我不知道我们公司的设备代码怎么设计的,所以不太清楚通用性如何,不过一般而言应该差不多吧。

首先我自定义了一个蓝牙连接管理的类,初始化的参数为Activity的context(这里我写的很随意,理论上这个类写在Service中更好):

public class BTManager {
private Context context = null;
private BluetoothAdapter adapter = null;
private BroadcastReceiver receiver = null;
private BTService bts = null;

// 初始化
public BTManager(Context context) {
this.context = context;
initAdapter();
initRecevier();
}
}
首先判断手机支不支持蓝牙功能,如果支持则开启蓝牙

// 看是否支持蓝牙
private void initAdapter() {
adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null) {
Toast.makeText(context, "该设备不支持蓝牙!", Toast.LENGTH_SHORT).show();
return;
}
enabledBT();
}

// 开启蓝牙
private void enabledBT() {
if (!adapter.isEnabled()) {
Intent mIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivity(mIntent);
}
}
然后初始化广播,这个广播是要给Acitivty注册的,用来通知界面蓝牙连接的状态:

// 初始化广播
private void initRecevier() {
if(receiver == null){
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String actionName = intent.getAction();
if (actionName.equals("android.bluetooth.device.action.FOUND")) {
// 获取找到设备的对象
BluetoothDevice device = (BluetoothDevice) intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

// 如果找到的设备和想要搜索的设备名一致,就发送找到广播
if (device.getName() != null
&& device.getName().equalsIgnoreCase(
Params.deviceName)) {
Intent it = new Intent(
"com.fisee.bluetooth.findFinished");
it.putExtra("state", true);
context.sendBroadcast(it);
cancelDiscover();

bts = new BTService(device);
}
} else if (actionName
.equals("android.bluetooth.adapter.action.DISCOVERY_FINISHED")) {
// 搜索结束
Intent it = new Intent("com.fisee.bluetooth.findFinished");
it.putExtra("state", false);
context.sendBroadcast(it);

cancelDiscover();
}
}
};
}
}
android.bluetooth.device.action.FOUND为找到设备后收到的广播,但是周围开启的蓝牙设备都有可能被搜索到,所以要将搜索到的设备名和我们要搜索的设备名进行比较,如果一致则停止搜寻设备,进行连接。

android.bluetooth.adapter.action.DISCOVERY_FINISHED为搜索结束后收到的广播,一般蓝牙搜索的过程会持续12s,12s后没有找到要匹配的设备则收到此广播。

下面是开始搜寻设备的方法和停止搜寻设备的方法:

// 开始搜寻设备
public void discover(String name) {
if (adapter == null) {
return;
}
Params.deviceName = name;
if (adapter.isDiscovering()) {
Toast.makeText(context, "正在搜索请等待...", Toast.LENGTH_SHORT).show();
} else {
// 注册广播
IntentFilter filter = new IntentFilter();
filter.addAction("android.bluetooth.device.action.FOUND");
filter.addAction("android.bluetooth.adapter.action.DISCOVERY_FINISHED");
context.registerReceiver(receiver, filter);

adapter.startDiscovery();
}
}

// 停止搜索设备
private void cancelDiscover() {
// 如果还在搜寻设备,则停止
if (adapter.isDiscovering()) {
adapter.cancelDiscovery();
}
// 注销广播
context.unregisterReceiver(receiver);
}
在搜寻开始时注册广播,如果搜寻结束,要记住注销广播。

然后我写了一个内部类,专门用来处理蓝牙收发数据:

public class BTService {
private BluetoothDevice target = null;// socket连接的对象
private Thread thread = null;// 接收数据线程
private BluetoothSocket socket = null;// bt socket对象
private boolean running = false;// socket是否正在运行

public BTService(BluetoothDevice device) {
running = false;
closeSocket();
target = device;
if (thread == null) {
thread = new Thread() {
public void run() {
try {
Log.e("CREAT BT SOCKET", "creating bt socket");
/**
* 蓝牙socket连接的建立
*/
Method m = target.getClass().getMethod(
"createRfcommSocket",
new Class[] { Integer.TYPE });
socket = ((BluetoothSocket) m.invoke(target,
new Object[] { Integer.valueOf(1) }));
socket.connect();
} catch (IOException e) {
closeSocket();
Log.e("IOException", "creat bt socket exception");
} catch (SecurityException e) {
closeSocket();
Log.e("SecurityException",
"close bt socket exception");
} catch (NoSuchMethodException e) {
closeSocket();
Log.e("Exception", "close bt socket exception");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

if (socket == null)
return;
running = true;
OnConnect();

byte[] buf = new byte[1024];
Log.e("creating success", "create bt socket success");
while (running) {
try {
InputStream isr = socket.getInputStream();
int sz = isr.read(buf);
isr = null;
if (sz <= 0) {
// Log.e("BluetoothSockTask",
// " read error size:" +
// sz);
} else {
// Log.e("BluetoothSockTask",
// " receive data success size:" + sz);
OnRecv(buf, sz);
}
} catch (Exception e) {
// Log.e("Exception","receive bt socket data exception");
if (running)
closeSocket();
}
}
}
};
}
thread.start();
}

// 关闭socket
private void closeSocket() {
running = false;
if (this.socket == null) {
return;
}
try {
socket.close();
System.out.println("closing bt socket");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clear_bond();
socket = null;
}

public void clear_bond() {
BluetoothAdapter m_adapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice m_btdevice = null;
Method removeBondMethod = null;
int i = 0;
Set<BluetoothDevice> m_dev_set = m_adapter.getBondedDevices();
for (Iterator<BluetoothDevice> it = m_dev_set.iterator(); it
.hasNext();) {
Log.e("", "clear bond++++++++++++++ " + i);
m_btdevice = it.next();
i++;
try {
removeBondMethod = m_btdevice.getClass().getMethod(
"removeBond");// 移除沾和
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
@SuppressWarnings("unused")
Boolean returnValue = (Boolean) removeBondMethod
.invoke(m_btdevice);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

//socket创建成功
public void OnConnect(){
Intent intent = new Intent(
"com.fisee.bluetooth.bluetoothConnected");
context.sendBroadcast(intent);
}

//接收到数据
public void OnRecv(byte[] buf,int size){
byte[] data = new byte[size];
for (int i = 0; i < size; i++) {
data[i] = buf[i];
}

//处理数据
System.out.println(data.length);
}

/**
* 蓝牙socket发送出的数据
*
* @param data
* @param size
* @return
*/
public int sendData(byte[] data, int size) {
if ((!this.running) || (data == null) || (this.socket == null))
return -1;
try {
OutputStream out = this.socket.getOutputStream();
if (data.length <= size) {

out.write(data);
size = data.length;
} else {
out.write(data, 0, size);
}
out.flush();
} catch (IOException e) {
e.printStackTrace();
return 0;
}
return size;
}
}
running相当于是个标志位,用来判断socket的状态,同时也控制着接收蓝牙数据的线程。sendData(byte[] data, int size) 方法是用来发送蓝牙包的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: