主要有BluetoothAdapter\BluetoothDevice\BluetoothServerSocket\BluetoothSocket等常用到的类。
一. BluetoothAdapter类
该类是蓝牙设备的接口,要想对设备的蓝牙进行操作,必须获得此类的对象,调用getDefaultAdapter()。此类可以完成的功能:
- 发现其他蓝牙 设备,调用startDiscovery()方法。
- 得到配对的蓝牙 设备,调用getBondedServices()。
- 创建监听socket,调用listenUsingRfcommWithServiceRecord(String,UUID)。
- ACTION_CONNECTION_STATE_CHANGED:用于将local Bluetooth Adapter的连接状态broadcast到remote device,当adapter试图第一次连接一个remote device或断开最后一个remote device连接时,此intent便会sent。
此Intent具有3个Extras:EXTRA_CONNECTION_STATE,表示设备当前连接状态。
EXTRA_PREVIOUS_CONNECTION,表示设备先前连接状态。
以上两个Extra的取值为STATE_CONNECTING、STATE_CONNECTED、STATE_DISCONNECTED、STATE_DISCONNECTING
还有一个Extra为EXTRA_DEVICE,表示remote device。
这里试了几个用法,但是都没有成功。首先,我定义了一个BroadcastReceiver,然后监听该事件:
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.
equals(action)) {
Toast.makeText(getApplicationContext(),
"ACTION_CONNECTION_STATE_CHANGED",
Toast.LENGTH_LONG).show();
}else if(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.
equals(action)) {
Toast.makeText(getApplicationContext(),
"local name has been changed",
Toast.LENGTH_LONG).show();
}
}
};
然后在onStart()方法中注册该BroadcastRecceiver:
/*****************************************************************************/
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
registerReceiver(mReceiver, intentFilter);
IntentFilter intentFilter1 = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
registerReceiver(mReceiver,intentFilter1);
/***********************************************************************/
但是,始终没有ACTION_CONNECTION_STATE_CHANGED事件触发,我也不知道怎么回事,有哪位大神懂得,麻烦告诉下。
5. ACTION_DISCOVERY_FINISHED\ACTION_DISCOVERY_STARTED\ACTION_LOCAL_NAME_CHANGED\ACTION_REQUEST_DISCOVERABLE\ACTION_REQUEST_ENBALE这些Broadcast Action或者Activity Action比较容易实现。这里就不多说了
6. ACTION_STATE_CHANGED:对于此Broadcast action,你可以在进行调用BluetoothAdapter的disable()或者enable()时,监听到。
7. ACTION_SCAN_MODE_CHANGED
还有一些方法,相对比较简单,这里不作介绍了。
二. BluetoothDevice类
代表一个Remote Divice可以通过方法来获得这个remote divice的name、address还有bond state。
- ACTION_ACL_CONNECTED:
- ACTION_ACL_DISCONNECTED:
这两个Broadcast action都会在建立或者断开一个连接时sent,所以可以用来进行检测设备的连接 动作。这只代表系统蓝牙设备试图进行连接,并不代表连接成功,也没有提供 连接方法,所以你检测到此事件后应该需要事先建立一个BluetoothServerSocket并进行连接accept(),所以此broadcast action的触发,和成功连接一个service并无直接关系,只是代表用户的操作,你仍然需要建立一个thread进行监听,并且先于此action的触发。因此,这两个broadcast action应该用为UI界面的更新,而不具有listen并建立连接的功能。其中ACTION_ACL_DISCONNECTED当一个remote设备断开连接时,就会sent。
public class Bluetooth extends AppCompatActivity {
private BluetoothAdapter mBluetoothAdapter;
public static final UUID MY_UUID_SECURE =
UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
public static final UUID MY_UUID_INSECURE =
UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter==null) {
Toast.makeText(this,"no bluetooth in your device",Toast.LENGTH_LONG).show();
finish();
return;
}
}
@Override
protected void onStart() {
IntentFilter intentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(bluetoothReceiver, intentFilter);
IntentFilter intentFilter1 = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
registerReceiver(bluetoothReceiver,intentFilter1);
super.onStart();
}
@Override
protected void onStop() {
super.onStop();
unregisterReceiver(bluetoothReceiver);
}
public void onOpenBluetoothBtnClicked(View view) {
if(!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
}
}
private Runnable listenConnection = new Runnable() {
BluetoothServerSocket bluetoothServerSocket;
@Override
public void run() {
try {
bluetoothServerSocket =
mBluetoothAdapter.listenUsingRfcommWithServiceRecord("tst",MY_UUID_SECURE);
} catch (IOException e) {
e.printStackTrace();
}
try {
BluetoothSocket bluetoothSocket = bluetoothServerSocket.accept();
Toast.makeText(getApplicationContext(),"connected successful",Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
} ;
private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
Toast.makeText(getApplicationContext(),"open bluetooth",Toast.LENGTH_LONG).show();
}else if(BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
Toast.makeText(getApplicationContext(),"a device connect to this one",Toast.LENGTH_LONG).show();
Thread thread = new Thread(listenConnection);
thread.start();
}
}
};
private Handler UiHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
}
3 . ACTION_ACL_DISCONNECT_REQUESTED:
顾名思义,这是一个remote device 要求断开连接时发送。这个action还不知道怎么进行触发。应该是主动要求断开擦次可以。
4. ACTION_BOND_STATE_CHANGED: 当一个remote device设备(unbonded)连接时,会触发该broadcast action;但是 在设计蓝牙设置处取消配对时,却没有触发该broadcast action,why?
5. ACTION_FOUND:当BluetoothAdapter 执行startDiscovery()时,每发现 一个设备就会触发该broadcast action
6. 其他constant有:ACTION_CLASS_CHANGED\ACTION_NAME_CHANGED\ACTION_UUID
另外该类还提供了一些获取remote device状态,属性的方法,主要有getAddress()、getBondState()、getName()、getUuids()。还有创建BluetoothSocket方法,用于连接remote divice主要有两个,createsecureRfcommSocketServiceRecord(UUID uuid)和
createRfcommSocketToServiceRecord(UUID uuid)。
三. BluetoothSocket类
设备之间进行通信,必须创建嵌套字。此类就是socket,来执行设备之间的通信。有两个方式得到BluetoothSocket,一种方式是host通过 创建BluetoothServerSocket然后进行accept()得到,一种方式是client,通过BluetoothDevice进行嵌套字创建。然后将创建好的BluetoothSocket调用connect()方法,从而建立连接。进而可以调用BluetoothSocket类的方法getInputStream()和getOutputStream()得到输入/输出流。注意connect()方法是阻塞方法。close()方法关闭socket,停止一切动作并释放资源。
四. BluetoothServerSocket
BluetoothSocket accept(int timeout);
BluetoothSocket accept();
void close();
注意:accept方法是thread safe的,执行后立刻关闭BluetoothServerSocket ,停止一切动作并释放资源。但是BluetoothServerSocket关闭后,又该对象创建的BluetootSocket也会立刻关闭。