在AndroidSDK sample中给出了一个蓝牙聊天的示例代码,本文只是略作修改变成一个简单的服务器和客户端模式的应用,以适应在游戏开发中一对一关联的数据传输。
由于游戏中的蓝牙设置在新线程中发生,所以采用Handler的方式将蓝牙的状态以及读取信息传输给显示Activity。
1 开启蓝牙,包括xml中的配置:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
//获取蓝牙适配器
BluetoothAdapter btAdapter = BlueToothService.getInstance().getBtAdapter();
//开启蓝牙
if (!btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, ConstantsUtil.ENABLE_BLUETOOTH);
}
2 在当前Activity中获取蓝牙开启结果,并根据具体情况对蓝牙进行处理
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case ConstantsUtil.ENABLE_BLUETOOTH:
if (resultCode == Activity.RESULT_OK) {
bluetoothProcess(PSystem.isServer);
} else {
finish();
}
}
}
public void bluetoothProcess(boolean isServer) {
BlueToothService.getInstance().setsHandler(mHandler);
if (isServer) {
//如果是蓝牙服务器,则需要开启发现服务,并启动蓝牙服务器
if(btAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(
BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 180);
startActivity(discoverableIntent);
}
BlueToothService.getInstance().start();
} else {
//如果是蓝牙客户端则扫描周围可用的蓝牙设备
blueToothNames = new ArrayList<String>();
blutToothDevices = new ArrayList<BluetoothDevice>();
//添加过滤器,并注册广播,用于监听蓝牙发现信息
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
//开始扫描
doDiscovery();
}
}
public void doDiscovery() {
if (btAdapter.isDiscovering()) {
btAdapter.cancelDiscovery();
}
btAdapter.startDiscovery();
}
3 蓝牙广播接收器
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(device.getName() != null && !device.getName().trim().equals("")) {
blueToothNames.add(device.getName());
blutToothDevices.add(device);
}
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)) {
btAdapter.cancelDiscovery();
TestActivity.this.unregisterReceiver(this);
}
}
};
4 以上是蓝牙基本配置和发现。现在进行蓝牙监听和连接:
蓝牙服务器监听代码:
public void start() {
BluetoothServerSocket serverSocket = null;
try {
serverSocket = btAdapter.listenUsingRfcommWithServiceRecord("JumpForMeApp", MY_UUID_SECURE);
changeState(ConstantsUtil.BT_STATE_LISTEN);
btSocket = serverSocket.accept();
} catch (IOException e) {
} finally {
try {
serverSocket.close();
} catch (IOException e) {
}
}
if(btSocket != null) {
changeState(ConstantsUtil.BT_STATE_CONNECTED);
}
}
客户端连接代码:
public void connect(BluetoothDevice device) {
try {
btAdapter.cancelDiscovery();
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
changeState(ConstantsUtil.BT_STATE_CONNECTING);
btSocket.connect();
} catch (IOException e) {
}
changeState(ConstantsUtil.BT_STATE_CONNECTED);
}
5 利用蓝牙进行消息传递,建立新的线程来处理读写操作(见BluetoothChat Sample中的ConnectedThread):
class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
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() {
byte[] buffer = new byte[1024];
int bytes;
while (true) {
try {
bytes = mmInStream.read(buffer);
if(transHandler != null) {
//通知数据传输处理器
transHandler.sendMessage(transHandler.obtainMessage(ConstantsUtil.BT_READ, bytes, -1, buffer));
}
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
break;
}
}
}
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}