今天我们来实现一下客户端和服务端通过蓝牙传数据
效果图如下:
这个布局太简单了,我就不给出了,直接上逻辑.
MainActivity:
public class MainActivity extends Activity implements View.OnClickListener {
private Button btn1;
private Button btn2;
private Button btn3;
private Button btn4;
private Button btn5;
private Button btn6;
private Button btn7;
private BluetoothAdapter mBlueToothAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
setListener();
}
private void setListener() {
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
btn3.setOnClickListener(this);
btn4.setOnClickListener(this);
btn5.setOnClickListener(this);
btn6.setOnClickListener(this);
btn7.setOnClickListener(this);
}
private void initView() {
btn1 = ((Button) findViewById(R.id.btn1));
btn2 = ((Button) findViewById(R.id.btn2));
btn3 = ((Button) findViewById(R.id.btn3));
btn4 = ((Button) findViewById(R.id.btn4));
btn5 = ((Button) findViewById(R.id.btn5));
btn6 = ((Button) findViewById(R.id.btn6));
btn7 = ((Button) findViewById(R.id.btn7));
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn1://打开蓝牙
onOpen();
break;
case R.id.btn2://关闭蓝牙
onClose();
break;
case R.id.btn3://允许搜索
onAbleFound();
break;
case R.id.btn4://开始搜索
onFound();
break;
case R.id.btn5://客户端
Intent intent=new Intent(this,ClientSocketActivity.class);
startActivity(intent);
break;
case R.id.btn6://服务器端
Intent intent1=new Intent(this,ServerSocketActivity.class);
startActivity(intent1);
break;
case R.id.btn7://OBEX服务器端
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==300){
//蓝牙已开启
Toast.makeText(MainActivity.this,"蓝牙已打开",Toast.LENGTH_SHORT).show();
}
}
/*
* 打开蓝牙
* */
public void onOpen(){
mBlueToothAdapter= BluetoothAdapter.getDefaultAdapter();
if (mBlueToothAdapter==null){
Toast.makeText(MainActivity.this,"手机不支持蓝牙",Toast.LENGTH_SHORT).show();
return;
}
if (!mBlueToothAdapter.isEnabled()){//蓝牙未开启 则开启蓝牙
Intent enableIntent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,300);
}
}
/*
* 关闭蓝牙
* */
public void onClose(){
if (mBlueToothAdapter.enable())
mBlueToothAdapter.disable();
Toast.makeText(MainActivity.this,"蓝牙已关闭",Toast.LENGTH_SHORT).show();
}
/*
* 允许被搜索到 时长300
* */
public void onAbleFound(){
if (mBlueToothAdapter!=null&&mBlueToothAdapter.isEnabled()){
if (mBlueToothAdapter.getScanMode()==BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){
Intent discoverableIntent=new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
//使本机在300秒内可被搜索
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);
startActivity(discoverableIntent);
Toast.makeText(MainActivity.this,"蓝牙已允许被检测",Toast.LENGTH_SHORT).show();
}
}
}
public void onFound(){
Intent intent=new Intent(MainActivity.this,BlueListActivity.class);
startActivity(intent);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onRestart() {
super.onRestart();
}
}
客户端逻辑:
/*
* 客户端
*
* */
public class ClientSocketActivity extends AppCompatActivity implements View.OnClickListener {
private BluetoothAdapter mBluetoothAdapter;
private static final int REQUEST_BLUELIST=200;
BluetoothDevice device;
private Button btn;
BluetoothSocket socket=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
initView();
setListener();
Log.i("onCreate----","onCreate");
// 获取到蓝牙默认的适配器
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!mBluetoothAdapter.isEnabled()){
finish();
return;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode!=REQUEST_BLUELIST){
return;
}
if (resultCode!=RESULT_OK){
return;
}
device=data.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
new Thread(new Runnable() {
@Override
public void run() {
//开始连接
connect();
}
}).start();
}
private void connect() {
try {
socket=device.createRfcommSocketToServiceRecord(UUID.fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3"));
if (socket!=null){
socket.connect();
OutputStream outputStream=socket.getOutputStream();
if (outputStream != null) {
// 需要发送的信息
String text ="向服务端"+device.getName()+"发送的信息";
// 以utf-8的格式发送出去
outputStream.write(text.getBytes("UTF-8"));
// Toast.makeText(ClientSocketActivity.this,"消息已发出,等待服务端接收",Toast.LENGTH_SHORT).show();
}
}
} catch (IOException e) {
e.printStackTrace();
// Toast.makeText(ClientSocketActivity.this,"socket未连接",Toast.LENGTH_SHORT).show();
}finally {
}
}
private void setListener() {
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//跳转到搜索蓝牙列表 选择一个要连接的服务器 回到客户端 开始连接
Intent intent=new Intent(ClientSocketActivity.this,BlueListActivity.class);
startActivityForResult(intent,REQUEST_BLUELIST);
}
});
}
private void initView() {
// 获取到ListView组件
btn=(Button)findViewById(R.id.btn);
}
@Override
public void onClick(View v) {
}
@Override
protected void onDestroy() {
super.onDestroy();
if (socket!=null){
socket=null;
}
}
}
activity_client布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.lzq.bluetoothmanager.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="客户端"
/>
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="搜索蓝牙设备"
/>
</LinearLayout>
服务端逻辑:
/*
* 服务端
*
* */
public class ServerSocketActivity extends Activity implements View.OnClickListener {
private BluetoothAdapter mBluetoothAdapter;
private Thread serverWorker=new Thread(){
@Override
public void run() {
listen();
}
};
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 通过msg传递过来的信息,吐司一下收到的信息
Toast.makeText(ServerSocketActivity.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
}
};
private BluetoothServerSocket serverSocket;
private BluetoothSocket clientSocket;
private ListView lv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_server);
initView();
setListener();
// 获取到蓝牙默认的适配器
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!mBluetoothAdapter.isEnabled()){
finish();
return;
}
//开启服务器
serverWorker.start();
}
/*
* 监听是否有客户端连接
* */
private void listen() {
try {
serverSocket=mBluetoothAdapter.listenUsingRfcommWithServiceRecord("服务端",UUID.fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3"));
/*
* 客户连线列表
* */
final List<String> lines=new ArrayList<>();
handler.post(new Runnable() {
@Override
public void run() {
lines.add("Rfcomm server started...");
ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(ServerSocketActivity.this,android.R.layout.simple_list_item_1,lines);
lv.setAdapter(arrayAdapter);
}
});
clientSocket=serverSocket.accept();
//处理请求内容
if (clientSocket!=null){
Log.i("clientSocket---","已经连接上客户端");
// Toast.makeText(ServerSocketActivity.this,"已经连接上客户端",Toast.LENGTH_SHORT).show();
InputStream inputStream = clientSocket.getInputStream();
// 无线循环来接收数据
while (true) {
// 创建一个128字节的缓冲
byte[] buffer = new byte[128];
// 每次读取128字节,并保存其读取的角标
int count = inputStream.read(buffer);
// 创建Message类,向handler发送数据
Message msg = new Message();
// 发送一个String的数据,让他向上转型为obj类型
msg.obj = new String(buffer, 0, count, "utf-8");
// 发送数据
handler.sendMessage(msg);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void setListener() {
}
private void shutDownServer() {
new Thread(new Runnable() {
@Override
public void run() {
serverWorker.interrupt();
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
serverSocket=null;
}
}
}).start();
}
private void initView() {
lv = (ListView) findViewById(R.id.lv);
}
@Override
public void onClick(View v) {
}
@Override
protected void onDestroy() {
super.onDestroy();
shutDownServer();
}
}
activity_server布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.lzq.bluetoothmanager.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="服务端"
/>
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</LinearLayout>
BlueListActivity
/*
* 搜索蓝牙列表
*
* */
public class BlueListActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {
private ListView lvDevices;
private ArrayAdapter<String> arrayAdapter;
//蓝牙设备信息集合包括 name address
private List<String> bluetoothDevicesStr = new ArrayList<String>();
//蓝牙设备对象集合
private List<BluetoothDevice> bluetoothDevices = new ArrayList<BluetoothDevice>();
private BluetoothAdapter mBluetoothAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blue_list);
initView();
setListener();
// 为listview设置字符换数组适配器
arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, android.R.id.text1,bluetoothDevicesStr);
// 为listView绑定适配器
lvDevices.setAdapter(arrayAdapter);
// 为listView设置item点击事件侦听
lvDevices.setOnItemClickListener(this);
// 获取到蓝牙默认的适配器
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter==null){
Toast.makeText(BlueListActivity.this,"手机不支持蓝牙",Toast.LENGTH_SHORT).show();
return;
}
if (!mBluetoothAdapter.isEnabled()){//蓝牙未开启 则开启蓝牙
Intent enableIntent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,200);
}
// 获取曾经匹配的蓝牙设备 用Set集合保持已匹配的蓝牙设备
Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
if (devices.size() > 0) {
for (BluetoothDevice bluetoothDevice : devices) {
// 保存到arrayList集合中
bluetoothDevicesStr.add("曾经匹配过的蓝牙--"+bluetoothDevice.getName() + ":"
+ bluetoothDevice.getAddress() + "\n");
bluetoothDevices.add(bluetoothDevice);
}
}
// 因为蓝牙搜索到设备和完成搜索都是通过广播来告诉其他应用的
// 这里注册找到设备和完成搜索广播
IntentFilter filter=new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); //设备已经连接广播
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //设备断开连接广播
registerReceiver(receiver, filter);
//开始搜索
Search();
}
private void setListener() {
}
private void initView() {
// 获取到ListView组件
lvDevices = (ListView) findViewById(R.id.lv);
}
public void Search() {
setTitle("正在扫描...");
// 点击搜索周边设备,如果正在搜索,则暂停搜索
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
mBluetoothAdapter.startDiscovery();
}
// 注册广播接收者
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context arg0, Intent intent) {
// 获取到广播的action
String action = intent.getAction();
// 判断广播是搜索到设备还是搜索完成
if (action.equals(BluetoothDevice.ACTION_FOUND)) {
// 找到设备后获取其设备
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 判断这个设备是否是之前已经绑定过了,如果是则不需要添加,在程序初始化的时候已经添加了
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
// 设备没有绑定过,则将其保持到arrayList集合中
bluetoothDevicesStr.add(device.getName() + ":"
+ device.getAddress() + "\n");
// 更新字符串数组适配器,将内容显示在listView中
arrayAdapter.notifyDataSetChanged();
bluetoothDevices.add(device);
}
} else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
setTitle("搜索完成");
}
}
};
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn1://打开蓝牙
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
if (bluetoothDevicesStr!=null){
bluetoothDevicesStr=null;
}
if (bluetoothDevices!=null){
bluetoothDevices=null;
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mBluetoothAdapter.cancelDiscovery();
Intent intent=new Intent();
intent.putExtra(BluetoothDevice.EXTRA_DEVICE,bluetoothDevices.get(position));
setResult(RESULT_OK,intent);
finish();
}
}
注意:测试时要在两个手机同时安装app,且一个打开服务器,作为服务端,另一个打开客户端,模拟向服务端发送数据。