美文网首页我爱编程
Android蓝牙系列——客户端与服务端通信过程以及实现数据通信

Android蓝牙系列——客户端与服务端通信过程以及实现数据通信

作者: justCode_ | 来源:发表于2017-07-01 11:04 被阅读0次

    一.蓝牙数据传输

    蓝牙数据传输其实跟我们的 Socket(套接字)有点类似,如果有不懂的,可以百度一下概念,我们只要知道是这么回事就可以了,在网络中使用Socket和ServerSocket控制客户端和服务端来数据读写。而蓝牙通讯也是由客户端和服务端来完成的,蓝牙客户端Socket是BluetoothSocket,蓝牙服务端Socket是BluetoothServerSocket,这两个类都在Android.bluetooth包下,而且无论是BluetoothSocket还是BluetoothServerSocket,我们都需要一个UUID(标识符),这个UUID在上篇也是有提到,而且他的格式也是固定的:

    UUID:XXXXXXXX(8)-XXXX(4)-XXXX(4)-XXXX(4)-XXXXXXXXXXXX(12)

    第一段是8位,中间三段式4位,最后一段是12位,UUID相当于Socket的端口,而蓝牙地址则相当于Socket的IP

    1.activity_main.xml

    <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" >

    <Button

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:onClick="btnSearch"

    android:text="搜索蓝牙设备" />

    <ListView

    android:id="@+id/lvDevices"

    android:layout_width="match_parent"

    android:layout_height="0dp"

    android:layout_weight="1" />

    </LinearLayout>

    2.实现步骤

    1.声明

    我们需要的东西

    // 本地蓝牙适配器    

    private BluetoothAdapter mBluetoothAdapter;    

    // 列表   

     private ListView lvDevices;    

    // 存储搜索到的蓝牙    

    private ListbluetoothDevices = new ArrayList();   

     // listview的adapter   

     private ArrayAdapterarrayAdapter;

    // UUID.randomUUID()随机获取UUID

    private final UUID MY_UUID = UUID

    .fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3");

    // 连接对象的名称

    private final String NAME = "LGL";

    // 这里本身即是服务端也是客户端,需要如下类

    private BluetoothSocket clientSocket;

    private BluetoothDevice device;

    // 输出流_客户端需要往服务端输出

    private OutputStream os;

    2.初始化

    // 获取本地蓝牙适配器                

    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();       

     // 判断手机是否支持蓝牙                

    if (mBluetoothAdapter == null) {            

    Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();            

    finish();        

    }        

    // 判断是否打开蓝牙               

     if (!mBluetoothAdapter.isEnabled()) {           

     // 弹出对话框提示用户是后打开            

    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);           

     startActivityForResult(intent, 1);           

     // 不做提示,强行打开            

    // mBluetoothAdapter.enable();       

     }       

     // 初始化listview       

     lvDevices = (ListView) findViewById(R.id.lvDevices);        

    lvDevices.setOnItemClickListener(this);       

     // 获取已经配对的设备        

    SetpairedDevices = mBluetoothAdapter.getBondedDevices();        

    // 判断是否有配对过的设备       

     if (pairedDevices.size() > 0) {           

     for (BluetoothDevice device : pairedDevices) {               

     // 遍历到列表中               

     bluetoothDevices.add(device.getName() + ":"  + device.getAddress() + "\n");           

     }       

     }        

    // adapter        

    arrayAdapter = new ArrayAdapter(this,

    android.R.layout.simple_list_item_1, android.R.id.text1,

    bluetoothDevices);

    lvDevices.setAdapter(arrayAdapter);

    /**

    * 异步搜索蓝牙设备——广播接收

    */

    // 找到设备的广播

    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);

    // 注册广播

    registerReceiver(receiver, filter);

    // 搜索完成的广播

    filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

    // 注册广播

    registerReceiver(receiver, filter);

    }

    3.点击搜索

    public void btnSearch(View v) {

    // 设置进度条

    setProgressBarIndeterminateVisibility(true);

    setTitle("正在搜索...");

    // 判断是否在搜索,如果在搜索,就取消搜索

    if (mBluetoothAdapter.isDiscovering()) {

    mBluetoothAdapter.cancelDiscovery();

    }

    // 开始搜索

    mBluetoothAdapter.startDiscovery();

    }

    4.搜索设备

    private final BroadcastReceiver receiver = new BroadcastReceiver() {

    @Override

    public void onReceive(Context context, Intent intent) {

    // 收到的广播类型

    String action = intent.getAction();

    // 发现设备的广播

    if (BluetoothDevice.ACTION_FOUND.equals(action)) {

    // 从intent中获取设备

    BluetoothDevice device = intent

    .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

    // 判断是否配对过

    if (device.getBondState() != BluetoothDevice.BOND_BONDED) {

    // 添加到列表

    bluetoothDevices.add(device.getName() + ":"

    + device.getAddress() + "\n");

    arrayAdapter.notifyDataSetChanged();

    }

    // 搜索完成

    } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED

    .equals(action)) {

    // 关闭进度条

    setProgressBarIndeterminateVisibility(true);

    setTitle("搜索完成!");

    }

    }

    };

    5.客户端实现已经发送数据流

    // 客户端

    @Override

    public void onItemClick(AdapterView parent, View view, int position,

    long id) {

    // 先获得蓝牙的地址和设备名

    String s = arrayAdapter.getItem(position);

    // 单独解析地址

    String address = s.substring(s.indexOf(":") + 1).trim();

    // 主动连接蓝牙

    try {

    // 判断是否在搜索,如果在搜索,就取消搜索

    if (mBluetoothAdapter.isDiscovering()) {

    mBluetoothAdapter.cancelDiscovery();

    }

    try {

    // 判断是否可以获得

    if (device == null) {

    // 获得远程设备

    device = mBluetoothAdapter.getRemoteDevice(address);

    }

    // 开始连接

    if (clientSocket == null) {

    clientSocket = device

    .createRfcommSocketToServiceRecord(MY_UUID);

    // 连接

    clientSocket.connect();

    // 获得输出流

    os = clientSocket.getOutputStream();

    }

    } catch (Exception e) {

    // TODO: handle exception

    }

    // 如果成功获得输出流

    if (os != null) {

    os.write("Hello Bluetooth!".getBytes("utf-8"));

    }

    } catch (Exception e) {

    // TODO: handle exception

    }

    }

    6.Handler服务

    // 服务端,需要监听客户端的线程类

    private Handler handler = new Handler() {

    public void handleMessage(android.os.Message msg) {

    Toast.makeText(MainActivity.this, String.valueOf(msg.obj),

    Toast.LENGTH_SHORT).show();

    super.handleMessage(msg);

    }

    };

    7.服务端读取数据流

    // 线程服务类

    private class AcceptThread extends Thread {

    private BluetoothServerSocket serverSocket;

    private BluetoothSocket socket;

    // 输入 输出流

    private OutputStream os;

    private InputStream is;

    public AcceptThread() {

    try {

    serverSocket = mBluetoothAdapter

    .listenUsingRfcommWithServiceRecord(NAME, MY_UUID);

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    @Override

    public void run() {

    // 截获客户端的蓝牙消息

    try {

    socket = serverSocket.accept(); // 如果阻塞了,就会一直停留在这里

    is = socket.getInputStream();

    os = socket.getOutputStream();

    // 不断接收请求,如果客户端没有发送的话还是会阻塞

    while (true) {

    // 每次只发送128个字节

    byte[] buffer = new byte[128];

    // 读取

    int count = is.read();

    // 如果读取到了,我们就发送刚才的那个Toast

    Message msg = new Message();

    msg.obj = new String(buffer, 0, count, "utf-8");

    handler.sendMessage(msg);

    }

    } catch (Exception e) {

    // TODO: handle exception

    }

    }

    }

    8.开启服务

    首先要声明

    //启动服务

    ac =newAcceptThread();

    ac.start();

    MainActivity完整代码

    package com.lgl.bluetoothget;

    import java.io.IOException;

    import java.io.InputStream;

    import java.io.OutputStream;

    import java.util.ArrayList;

    import java.util.List;

    import java.util.Set;

    import java.util.UUID;

    import android.app.Activity;

    import android.bluetooth.BluetoothAdapter;

    import android.bluetooth.BluetoothDevice

    ;import android.bluetooth.BluetoothServerSocket;

    import android.bluetooth.BluetoothSocket;

    import android.content.BroadcastReceiver;

    import android.content.Context;

    import android.content.Intent;

    import android.content.IntentFilter;

    import android.os.Bundle;

    import android.os.Handler;

    import android.os.Message;

    import android.util.Log;

    import android.view.View;

    import android.view.View.OnClickListener;

    import android.widget.AdapterView;

    import android.widget.AdapterView.OnItemClickListener;

    import android.widget.ArrayAdapter;

    import android.widget.Button;

    import android.widget.ListView;

    import android.widget.TextView;

    import android.widget.Toast;

    public class MainActivity extends Activity implements OnItemClickListener {    

    // 本地蓝牙适配器    

    private BluetoothAdapter mBluetoothAdapter;   

     // 列表   

     private ListView lvDevices;    

    // 存储搜索到的蓝牙    

    private ListbluetoothDevices = new ArrayList();   

     // listview的adapter   

     private ArrayAdapterarrayAdapter;   

     // UUID.randomUUID()随机获取UUID    

    private final UUID MY_UUID = UUID.fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3");   

     // 连接对象的名称    

    private final String NAME = "LGL";   

     // 这里本身即是服务端也是客户端,需要如下类    

    private BluetoothSocket clientSocket;    

    private BluetoothDevice device;   

     // 输出流_客户端需要往服务端输出    

    private OutputStream os;   

     //线程类的实例    

    private AcceptThread ac;    

    @Override  

      protected void onCreate(Bundle savedInstanceState) {        

    super.onCreate(savedInstanceState);        

    setContentView(R.layout.activity_main);        

    initView();    

    }    

    private void initView() { 

           // 获取本地蓝牙适配器        

    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();        

    // 判断手机是否支持蓝牙       

    if (mBluetoothAdapter == null) {            

    Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();            

    finish();        

    }        

    // 判断是否打开蓝牙        

    if (!mBluetoothAdapter.isEnabled()) {            

    // 弹出对话框提示用户是后打开           

     Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);            

    startActivityForResult(intent, 1);           

     // 不做提示,强行打开           

     // mBluetoothAdapter.enable();      

      }       

     // 初始化listview       

     lvDevices = (ListView) findViewById(R.id.lvDevices);       

     lvDevices.setOnItemClickListener(this);       

     // 获取已经配对的设备        

    SetpairedDevices = mBluetoothAdapter.getBondedDevices();       

     // 判断是否有配对过的设备       

     if (pairedDevices.size() > 0) {           

     for (BluetoothDevice device : pairedDevices) {               

     // 遍历到列表中                

    bluetoothDevices.add(device.getName() + ":" + device.getAddress() + "\n");           

     }       

     }        

    // adapter       

    arrayAdapter = new ArrayAdapter(this,

    android.R.layout.simple_list_item_1, android.R.id.text1,

    bluetoothDevices);

    lvDevices.setAdapter(arrayAdapter);

    //启动服务

    ac = new AcceptThread();

    ac.start();

    /**

    * 异步搜索蓝牙设备——广播接收

    */

    // 找到设备的广播

    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);

    // 注册广播

    registerReceiver(receiver, filter);

    // 搜索完成的广播

    filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

    // 注册广播

    registerReceiver(receiver, filter);

    }

    public void btnSearch(View v) {

    // 设置进度条

    setProgressBarIndeterminateVisibility(true);

    setTitle("正在搜索...");

    // 判断是否在搜索,如果在搜索,就取消搜索

    if (mBluetoothAdapter.isDiscovering()) {

    mBluetoothAdapter.cancelDiscovery();

    }

    // 开始搜索

    mBluetoothAdapter.startDiscovery();

    }

    // 广播接收器

    private final BroadcastReceiver receiver = new BroadcastReceiver() {

    @Override

    public void onReceive(Context context, Intent intent) {

    // 收到的广播类型

    String action = intent.getAction();

    // 发现设备的广播

    if (BluetoothDevice.ACTION_FOUND.equals(action)) {

    // 从intent中获取设备

    BluetoothDevice device = intent

    .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

    // 判断是否配对过

    if (device.getBondState() != BluetoothDevice.BOND_BONDED) {

    // 添加到列表

    bluetoothDevices.add(device.getName() + ":"

    + device.getAddress() + "\n");

    arrayAdapter.notifyDataSetChanged();

    }

    // 搜索完成

    } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED

    .equals(action)) {

    // 关闭进度条

    setProgressBarIndeterminateVisibility(true);

    setTitle("搜索完成!");

    }

    }

    };

    // 客户端

    @Override

    public void onItemClick(AdapterView parent, View view, int position,

    long id) {

    // 先获得蓝牙的地址和设备名

    String s = arrayAdapter.getItem(position);

    // 单独解析地址

    String address = s.substring(s.indexOf(":") + 1).trim();

    // 主动连接蓝牙

    try {

    // 判断是否在搜索,如果在搜索,就取消搜索

    if (mBluetoothAdapter.isDiscovering()) {

    mBluetoothAdapter.cancelDiscovery();

    }

    try {

    // 判断是否可以获得

    if (device == null) {

    // 获得远程设备

    device = mBluetoothAdapter.getRemoteDevice(address);

    }

    // 开始连接

    if (clientSocket == null) {

    clientSocket = device

    .createRfcommSocketToServiceRecord(MY_UUID);

    // 连接

    clientSocket.connect();

    // 获得输出流

    os = clientSocket.getOutputStream();

    }

    } catch (Exception e) {

    // TODO: handle exception

    }

    // 如果成功获得输出流

    if (os != null) {

    os.write("Hello Bluetooth!".getBytes("utf-8"));

    }

    } catch (Exception e) {

    // TODO: handle exception

    }

    }

    // 服务端,需要监听客户端的线程类

    private Handler handler = new Handler() {

    public void handleMessage(android.os.Message msg) {

    Toast.makeText(MainActivity.this, String.valueOf(msg.obj),

    Toast.LENGTH_SHORT).show();

    super.handleMessage(msg);

    }

    };

    // 线程服务类

    private class AcceptThread extends Thread {

    private BluetoothServerSocket serverSocket;

    private BluetoothSocket socket;

    // 输入 输出流

    private OutputStream os;

    private InputStream is;

    public AcceptThread() {

    try {

    serverSocket = mBluetoothAdapter

    .listenUsingRfcommWithServiceRecord(NAME, MY_UUID);

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    @Override

    public void run() {

    // 截获客户端的蓝牙消息

    try {

    socket = serverSocket.accept(); // 如果阻塞了,就会一直停留在这里

    is = socket.getInputStream();

    os = socket.getOutputStream();

    // 不断接收请求,如果客户端没有发送的话还是会阻塞

    while (true) {

    // 每次只发送128个字节

    byte[] buffer = new byte[128];

    // 读取

    int count = is.read();

    // 如果读取到了,我们就发送刚才的那个Toast

    Message msg = new Message();

    msg.obj = new String(buffer, 0, count, "utf-8");

    handler.sendMessage(msg);

    }

    } catch (Exception e) {

    // TODO: handle exception

    }

    }

    }

    }

    相关文章

      网友评论

        本文标题:Android蓝牙系列——客户端与服务端通信过程以及实现数据通信

        本文链接:https://www.haomeiwen.com/subject/nrmwcxtx.html