首先介绍基本类及方法
一,BlueboothAdapter这个就是表示本机,里面几个常用的方法如下。
1,getDefaultAdapter 这个是静态的方法,通过它可以获取BlueboothAdapter对象
2,enable() 这个方法会弹出一个对话框(包含“确定”,“取消”按钮)提示用户打开蓝牙,用户选择确定则这个方法会返回true,取消返回false.
3,getNmae() 返回本机蓝牙的名称
4,getRemoteDevice(String address)根据给定一个地址参数获取远程蓝牙。
5,getAddress 获取本机的地址
6,startDiscovery() 扫描周围蓝牙,若找到蓝牙会发送 BluetoothDevice.
ACTION_FOUND广播
7 cancelDiscovery() 取消扫描
8,isEnabled() 判断蓝牙是否打开若打开则返回true,没有打开返回false
9,getBondedDevices() 返回绑定的蓝牙,
10,listenUsingRfcommWithServiceReord(String name,UUID uuid) 其中name通常是你的包名,也可以是任意字符串,UUID你可以通过浏览器在线获取
返回的是一个BlueboothServerSocket对象
BlueboothAdapter中常用的方法就是这么多,接下来是BlueboothDevice
二,BlueboothDevice 这个表示远程的设备,常用方法如下
1,getName 获取远程蓝牙的名字
2,getAddress获取远程蓝牙的地址
3,getBondState()获取远程蓝牙的绑定状态,Bond_none 为绑定,bond_bonding正在绑定,bond_bonded已经绑定
3,createBond() 调用这个方法可以进行绑定蓝牙,这个方法要求的最低版本是19,当然你还可以通过反射进行绑定如下
Method method=(Method)BluetoothDevice.class.getMethod("createBond");
method.invoke(device);//device为你想要绑定的远程蓝牙
4,createRfcommSocketToServiceRecord(UUID uuid)//根据uuid获取BlueboothSocket对象,其中uuid一定要跟listenUsingRfcommWithServiceReord中给定的uuid一致
这里再说明一定蓝牙客户端与服务端进行通信时用BlueboothSocket获取输入流,输出流来进行通信的。
下面是代码包含蓝牙的搜索及绑定
public class MainActivity
extends AppCompatActivity
implements View.OnClickListener, AdapterView.OnItemClickListener {
private Button
search;
private Button
client;
private ListView
listBluebooth;
private BluetoothAdapter
bAdapter;
private BluetoothDevice
bDevice;
private ListAdapter
listAdapter;
private List<String>
deviceNames =
new ArrayList<>();
private List<String>
deviceAddress =
new ArrayList<>();
private BluetoothDevice
device;
private IsSuccess
isSuccess;
private String
isServer =
"on";
//判断是否为服务端
private Handler
handler =
new Handler() {
@Override
public void handleMessage(Message msg) {
search.setText(
"搜索完成");
client.setText(
"搜索完成");
}
};
private boolean sureBlueboothIsOpen=
true;
//默认蓝牙是打开状态
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.
activity_main);
init();
}
private void init() {
client = (Button) findViewById(R.id.
client);
client.setOnClickListener(
this);
search = (Button) findViewById(R.id.
search);
search.setOnClickListener(
this);
listBluebooth = (ListView) findViewById(R.id.
list_bluebooth);
IntentFilter filter =
new IntentFilter();
filter.addAction(BluetoothDevice.
ACTION_FOUND);
filter.addAction(BluetoothAdapter.
ACTION_DISCOVERY_FINISHED);
registerReceiver(
receiver, filter);
bAdapter = BluetoothAdapter.
getDefaultAdapter();
}
//得到已绑定的设备
private void addBoundDevice(BluetoothAdapter bAdapter) {
Set<BluetoothDevice> set = bAdapter.getBondedDevices();
Log.
d(
"test",
"set:" + set.size());
for (BluetoothDevice device : set) {
deviceNames.add(device.getName());
deviceAddress.add(device.getAddress());
}
listAdapter =
new ListAdapter(MainActivity.
this, R.layout.
bluebooth_item,
deviceNames);
/*listAdapter.notifyDataSetChanged();*/
listBluebooth.setAdapter(
listAdapter);
listBluebooth.setOnItemClickListener(
this);
}
//搜索到发现蓝牙广播
BroadcastReceiver
receiver =
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.
d(
"test",
"action:" + intent.getAction());
if (intent.getAction().equals(BluetoothDevice.
ACTION_FOUND)) {
bDevice = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.
EXTRA_DEVICE);
if (
bDevice.getBondState() == BluetoothDevice.
BOND_NONE) {
Log.
d(
"test",
"none");
deviceNames.add(
bDevice.getName());
deviceAddress.add(
bDevice.getAddress());
}
listAdapter.notifyDataSetChanged();
listBluebooth.setAdapter(
listAdapter);
}
else if (intent.getAction().equals(BluetoothAdapter.
ACTION_DISCOVERY_FINISHED)) {
handler.sendEmptyMessage(
1);
}
}
};
@Override
protected void onActivityResult(
int requestCode,
int resultCode, Intent data) {
if (resultCode ==
RESULT_OK) {
Log.
d(
"test",
"result ok");
}
else {
Log.
d(
"test", resultCode +
" result");
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//服务端只需打开蓝牙,不需扫描,只要等待客户端接入即可
case R.id.
search:
if (!
bAdapter.isEnabled()) {
sureBlueboothIsOpen=
bAdapter.enable();
}
if (
sureBlueboothIsOpen) {
isServer =
"yes";
Intent intent1 =
new Intent(MainActivity.
this, ChatActivity.
class);
intent1.putExtra(
"is_server",
isServer);
startActivity(intent1);
client.setEnabled(
false);
}
else {
Toast.
makeText(getApplicationContext(),
"蓝牙没有开启",Toast.
LENGTH_SHORT).show();
return;
}
break;
case R.id.
client:
addBoundDevice(
bAdapter);
//用户按下取消按钮返回false,确定返回true
if (!
bAdapter.isEnabled()) {
sureBlueboothIsOpen=
bAdapter.enable();
}
if (
sureBlueboothIsOpen) {
isServer =
"no";
bAdapter.startDiscovery();
client.setText(
"搜索蓝牙中");
isSuccess =
new IsSuccess();
isSuccess.start();
search.setEnabled(
false);
}
else {
Toast.
makeText(getApplicationContext(),
"蓝牙没有开启",Toast.
LENGTH_SHORT).show();
return;
}
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(
receiver);
if (
isSuccess !=
null)
isSuccess.interrupt();
}
//deviceNmaes list子项的点击事件配对蓝牙
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position,
long id) {
//你要想绑定的蓝牙
device =
bAdapter.getRemoteDevice(
deviceAddress.get(position));
try {
Method method = (Method) BluetoothDevice.
class.getMethod(
"createBond");
Log.
d(
"test", (
boolean) method.invoke(
device) +
":" +
device.getBondState());
/*Log.d("test", device.createBond() + ":" + device.getBondState());*/
}
catch (Exception e) {
e.printStackTrace();
}
/* address = deviceAddress.get(position);
Intent intent1 = new Intent(MainActivity.this, ChatActivity.class);
intent1.putExtra("device", address);
intent1.putExtra("is_server", isServer);
startActivity(intent1);*/
}
//根据bDevice绑定状态判断用户是否按下匹配按钮
//这个线程会一直执行下去直到用户绑定蓝牙成功
class IsSuccess
extends Thread {
private int i =
0;
@Override
public void run() {
while (
true) {
i++;
/*Log.d("test", "device state:" + bDevice.getBondState());*/
if (
device !=
null) {
break;
}
/* if (bDevice.getBondState() == 12 ) {
break;
}*/
try {
sleep(
1000);
}
catch (Exception e) {
e.printStackTrace();
}
}
runOnUiThread(
new Runnable() {
@Override
public void run() {
if (
device.getBondState() ==
12) {
Intent intent1 =
new Intent(MainActivity.
this, ChatActivity.
class);
intent1.putExtra(
"device",
device.getAddress());
intent1.putExtra(
"is_server",
isServer);
startActivity(intent1);
}
}
});
}
}
}
接着是客户端与服务端通信的代码
public class ChatActivity
extends Activity
implements View.OnClickListener {
private ListView
chat;
private EditText
content;
private static String
UUID_CODE=
"42385BC1-F486-5196-1956-9CBEF428212B";
private Button
send;
private BluetoothSocket
socket;
private BluetoothServerSocket
serverSocket;
private BluetoothAdapter
bAdapter;
private BluetoothDevice
device;
private ReadThread
readThread;
//读线程
private String
isServer;
private List<String>
messageLists =
new ArrayList<>();
private ArrayAdapter
arrayAdapter;
private Handler
handler =
new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.
what ==
3) {
Log.
d(
"test",
"message ==3");
readThread =
new ReadThread(
socket);
readThread.start();
messageLists.add(
"已连接到服务端:" +
socket.getRemoteDevice().getName());
}
arrayAdapter =
new ArrayAdapter(ChatActivity.
this, android.R.layout.
simple_list_item_1,
messageLists);
switch (msg.
what) {
case 1:
break;
case 2:
String content = (String) msg.
obj;
Log.
d(
"test",
"handler:" + content);
messageLists.add(content);
break;
}
Log.
d(
"test",
messageLists.size() +
"");
arrayAdapter.notifyDataSetChanged();
chat.setAdapter(
arrayAdapter);
chat.setSelection(
messageLists.size()-
1);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.
char_layout);
init();
}
@Override
protected void onStart() {
super.onStart();
String isServer = getIntent().getStringExtra(
"is_server");
if (isServer.equals(
"yes")) {
Log.
d(
"test",
"server");
this.
isServer =
"server";
ServerThread serverThread =
new ServerThread(
bAdapter);
serverThread.start();
}
else if (isServer.equals(
"no")) {
Log.
d(
"test",
"client");
this.
isServer =
"client";
ClientThread clientThread =
new ClientThread(
device);
clientThread.start();
}
}
private void init() {
chat = (ListView) findViewById(R.id.
chat);
content = (EditText) findViewById(R.id.
content);
send = (Button) findViewById(R.id.
send);
send.setOnClickListener(
this);
bAdapter = BluetoothAdapter.
getDefaultAdapter();
String address = getIntent().getStringExtra(
"device");
if (!TextUtils.
isEmpty(address)) {
Log.
d(
"test",
"chat adress:" + address);
device =
bAdapter.getRemoteDevice(address);
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.
send:
Log.
d(
"test",
"onclick");
if (!TextUtils.
isEmpty(
content.getText())) {
/*sendMessage();*/
Log.
d(
"test",
"sendmessage");
sendMessage(
content.getEditableText().toString());
//若读线程为空则再次创建读线程
if (
readThread ==
null) {
readThread =
new ReadThread(
socket);
readThread.start();
Log.
d(
"test",
"readThread==nulll");
}
else {
Log.
d(
"test",
"readThread!=null");
}
}
break;
}
}
//发送信息
//客户端
private class ClientThread
extends Thread {
private BluetoothDevice
device;
public ClientThread(BluetoothDevice device) {
this.
device = device;
}
@Override
public void run() {
try {
Log.
d(
"test",
"client");
bAdapter.cancelDiscovery();
socket =
device.createRfcommSocketToServiceRecord(UUID.
fromString(
UUID_CODE));
Log.
d(
"test",
device.getUuids().toString());
socket.connect();
//通过BlueboothSocket的getRemoteDevice()来确认连接的远程蓝牙是否是自己想要连接的
Log.
d(
"test",
"client connet success:"+
socket.getClass().toString() +
socket.getRemoteDevice().getName() +
":" +
socket.getRemoteDevice().getAddress());
/*if (socket != null) {
readThread = new ReadThread(socket);
readThread.start();
}*/
Log.
d(
"test",
"start client read");
//这里创建的readThread为空
/*readThread = new ReadThread(socket);
readThread.start();*/
Message message=
new Message();
message.
what=
3;
handler.sendMessage(message);
}
catch (Exception e) {
e.printStackTrace();
runOnUiThread(
new Runnable() {
@Override
public void run() {
if (
socket !=
null) {
}
});}
}
}
//服务端
private class ServerThread
extends Thread {
private BluetoothAdapter
adapter;
public ServerThread(BluetoothAdapter adapter) {
this.
adapter = adapter;
}
@Override
public void run() {
try {
Log.
d(
"test",
"serverThread");
/*bAdapter.cancelDiscovery();*/
serverSocket =
adapter.listenUsingInsecureRfcommWithServiceRecord(
"bluetoothdemo", UUID.
fromString(
UUID_CODE));
socket =
serverSocket.accept();
Log.
d(
"test",
"server connect success");
}
catch (Exception e) {
}
runOnUiThread(
new Runnable() {
@Override
public void run() {
Log.
d(
"test",
"start server read");
if (
socket !=
null) {
//
readThread =
new ReadThread(
socket);
readThread.start();
messageLists.add(
"客户端:" +
socket.getRemoteDevice().getName() +
"已连接");
Message message=
new Message();
message.
what=
1;
handler.sendMessage(message);
/* sendMessage("client:"+socket.getRemoteDevice().getName()+"已经连接");*///自己会读取自己这边放入的字符
/* socket.close();*/
}
}
});
}
}
//从输入流中读取,因为read(byte [])这个方法会阻塞,所以要放到子线程中
private class ReadThread
extends Thread {
private BluetoothSocket
socket;
private InputStream
stream;
public ReadThread(BluetoothSocket socket) {
this.
socket = socket;
}
@Override
public void run() {
super.run();
while (
true) {
try {
stream =
socket.getInputStream();
/*if (stream != null)
*//*Log.d("test", "stram not null");*//*
else
Log.d("test", "stram null");*/
byte[] buff =
new byte[
1024];
stream.read(buff);
String content=
new String(buff);
//判断是是服务端还是客户端
if (
isServer.equals(
"server")) {
content=
"客户端:"+content;
}
else {
content=
"服务端:"+content;
}
Message message =
new Message();
message.
obj = content;
message.
what =
2;
handler.sendMessage(message);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
//发送信息
private void sendMessage(String content) {
if (
socket !=
null) {
Log.
d(
"test",
"socket class:" +
socket.getRemoteDevice().getName() +
":" +
socket.getRemoteDevice().getAddress());
Log.
d(
"test",
"socket class:" +
socket.toString());
try {
Log.
d(
"test",
"sock not null");
OutputStream outputStream =
socket.getOutputStream();
;
if (outputStream !=
null) {
Log.
d(
"test",
"output not null");
}
else {
Log.
d(
"test",
"output null");
}
outputStream.write(content.getBytes());
messageLists.add(content);
/* InputStream stream = socket.getInputStream();
byte[] buff = new byte[1024];
stream.read(buff);
String s = new String(buff);
Log.d("test", "read:" + s);*/
Log.
d(
"test",
"tttt");
Message message1 =
new Message();
message1.
what =
1;
handler.sendMessage(message1);
}
catch (Exception e) {
e.printStackTrace();
}
}
else {
Log.
d(
"test",
"socket null");
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (
readThread !=
null) {
readThread.interrupt();
}
}
}
这里有几个坑想说一下,当你从输入流中读取信息的时候一定要保证读线程是不为空的,不然一定读取不到信息,所以我在按下发送按钮的时候再重新检查下读线程是否为空
要是为空则重新创建一个读线程