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

Android基础——实现安卓蓝牙2.0模块的通信功能

2016-09-22 15:49 399 查看
实现安卓蓝牙2.0模块的通信功能
事先说明:安卓蓝牙2.0的开发和BLE4.0的开发完全是不一样的,不过很多设备都采用双模蓝牙,所以掌握2.0也是很有必要的安卓蓝牙需要手动申请定位权限,可参考我的博客点击打开链接
蓝牙连接过程:1、查询用户是否开启蓝牙。2、搜索附近的可用的蓝牙。3、进行蓝牙配对。4、进行蓝牙连接。5、获取输入流和输出流。6、发送消息。
蓝牙开发思路:蓝牙从连接到通信整个过程都是通过接收和发送广播进行的,下面是蓝牙进行特定操作时发出来的广播图,晒上我自己画的美图


蓝牙广播内容:ACTION_STATE_CHANGED 当你蓝牙开启或者关闭的时候发送
ACTION_FOUND  当你匹配到附近蓝牙设备时发送
ACTION_DISCOVERY_STARTED  当你开始搜索附近蓝牙设备时发送
ACTION_DISCOVERY_FINISHED  当你结束搜索附近蓝牙设备时发送
ACTION_BOND_STATE_CHANGED  当你蓝牙设备匹配状态发生变化时发送

实现需要的权限:由于安卓4.x以上的版本使用蓝牙,需要开启定位权限才能搜索到附近的蓝牙设备 <uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

这里使用俩手机,实现蓝牙之间的通信,下面是Demo的效果图



(一)服务端实现思路:1、拿到本地蓝牙设备。2、蓝牙之间的通讯需要一个唯一识别UUID来匹配正确的设备,使用UUID获取蓝牙的通讯Socket。3、开启获取数据的线程
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

BluetoothSocket BTSocket;
BluetoothAdapter BTAdapter;
Button bt_start;
TextView tv_msg;
StringBuilder sb;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_start = (Button) findViewById(R.id.bt_start);
tv_msg = (TextView) findViewById(R.id.tv_msg);
bt_start.setOnClickListener(this);
sb = new StringBuilder();

show("服务端:检查BT");
checkBT(this);
}

/**
* 检查蓝牙
*/
public void checkBT(Context context) {
BTAdapter = BluetoothAdapter.getDefaultAdapter();
if (BTAdapter != null) {
if (!BTAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
// 设置蓝牙可见性,最多300秒
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
context.startActivity(intent);
}
} else {
show("本地设备驱动异常!");
}
}

/**
* UI文本输出
*
* @param msg
*/
public void show(String msg) {
sb.append(msg + "\n");
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_msg.setText(sb.toString());
}
});
}

@Override
public void onClick(View v) {
//开启服务器
ServerThread startServerThread = new ServerThread();
startServerThread.start();
}

/**
* 开启服务器
*/
private class ServerThread extends Thread {
public void run() {
try {
BluetoothServerSocket mserverSocket = BTAdapter.listenUsingRfcommWithServiceRecord("btspp",
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
show("服务端:等待连接");

BTSocket = mserverSocket.accept();
show("服务端:连接成功");

readThread mreadThread = new readThread();
mreadThread.start();
show("服务端:启动接受数据");
} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* 读取数据
*/
private class readThread extends Thread {
public void run() {
byte[] buffer = new byte[1024];
int bytes;
InputStream mmInStream = null;
try {
mmInStream = BTSocket.getInputStream();
show("服务端:获得输入流");
} catch (IOException e1) {
e1.printStackTrace();
}
while (true) {
try {
if ((bytes = mmInStream.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);
show("服务端:读取数据了~~" + s);
}
} catch (IOException e) {
try {
mmInStream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
break;
}
}
}
}
}
(二)客户端
实现思路:1、检查是否开启蓝牙。2、注册一系列蓝牙的广播。3、由于蓝牙每经过一个阶段都会发送一个广播,根据广播来实现对应的方法。4、蓝牙配对->蓝牙连接->发送消息(UUID必须相同)其实客户端的操作就是上面那张思路图,根据里面的步骤进行就可以完成
① 检查蓝牙 /**
* 检查蓝牙
*/
public void checkBT(Context context) {
BTAdapter = BluetoothAdapter.getDefaultAdapter();
if (BTAdapter != null) {
if (!BTAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
// 设置蓝牙可见性,最多300秒
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
context.startActivity(intent);
}
} else {
show("本地设备驱动异常!");
}
}

② 注册广播 /**
* 注册广播
*/
public void registerBTReceiver() {
// 设置广播信息过滤
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
// 注册广播接收器,接收并处理搜索结果
registerReceiver(BTReceive, intentFilter);
}

③ 搜索附近设备BTAdapter.startDiscovery();

④ 获取搜索到设备的通知 /**
* 广播接收者
*/
private BroadcastReceiver BTReceive = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//打印Action,调试使用
show(action);
//找到设备通知 ACTION_FOUND,设备已配对通知 ACTION_BOND_STATE_CHANGED
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
show("客户端:找到的BT名:" + device.getName());
// 如果查找到的设备符合,添加到UI上
addBT();
} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
// 获取蓝牙设备的连接状态
int connectState = device.getBondState();
// 已配对
if (connectState == BluetoothDevice.BOND_BONDED) {
try {
show("客户端:开始连接:");
clientThread clientConnectThread = new clientThread();
clientConnectThread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};

/**
* 添加找到的BT
*/
private void addBT() {
Button bt = new Button(MainActivity.this);
bt.setTag(device.getName());
bt.setText(device.getName());
ly_device.addView(bt);
//处理选中BT设备,进行绑定
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bondBT((String) v.getTag());
}
});
}

/**
* 绑定蓝牙
*
* @param deviceName
*/
private void bondBT(String deviceName) {
if (device.getName().equalsIgnoreCase(deviceName)) {
show("客户端:配对蓝牙开始");
// 搜索蓝牙设备的过程占用资源比较多,一旦找到需要连接的设备后需要及时关闭搜索
BTAdapter.cancelDiscovery();
// 获取蓝牙设备的连接状态
int connectState = device.getBondState();

switch (connectState) {
// 未配对
case BluetoothDevice.BOND_NONE:
show("客户端:开始配对");
try {
Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
createBondMethod.invoke(device);
} catch (Exception e) {
e.printStackTrace();
}
break;
// 已配对
case BluetoothDevice.BOND_BONDED:
try {
show("客户端:开始连接:");
clientThread clientConnectThread = new clientThread();
clientConnectThread.start();
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}

⑤ 进行连接 /**
* 开启客户端
*/
private class clientThread extends Thread {
public void run() {
try {
//创建一个Socket连接:只需要服务器在注册时的UUID号
BTSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
//连接
show("客户端:开始连接...");
BTSocket.connect();
show("客户端:连接成功");
//启动接受数据
show("客户端:启动接受数据");
readThread mreadThread = new readThread();
mreadThread.start();
} catch (IOException e) {
show("客户端:连接服务端异常!断开连接重新试一试");
e.printStackTrace();
}
}
}

⑥ 读取数据 /**
* 读取数据
*/
private class readThread extends Thread {
public void run() {
byte[] buffer = new byte[1024];
int bytes;
InputStream is = null;
try {
is = BTSocket.getInputStream();
show("客户端:获得输入流");
} catch (IOException e1) {
e1.printStackTrace();
}
while (true) {
try {
if ((bytes = is.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);
show("客户端:读取数据了" + s);
}
} catch (IOException e) {
try {
is.close();
} catch (IOException e1) {
e1.printStackTrace();
}
break;
}
}
}
}

⑦ 发送数据 /**
* 发送数据
*/
public void sendMessage() {
if (BTSocket == null) {
Toast.makeText(this, "没有连接", Toast.LENGTH_SHORT).show();
return;
}
try {
OutputStream os = BTSocket.getOutputStream();
os.write("我爱你dahsid132456@#%¥*".getBytes());
os.flush();
show("客户端:发送信息成功");
} catch (IOException e) {
e.printStackTrace();
}
}

蓝牙2.0比较简单,大家可以通过源码进行理解
源码下载:工具是Android Studio2.1 (建议使用Import Project导入)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐