前段时间写了蓝牙gatt协议的通讯,发现Android开发蓝牙,与硬件通讯使用gatt协议。如果个Android设备之间开发蓝牙通讯该怎么写。就在查了有关方面的资料,了解了Socket通讯,今天就写下Android设备之间的蓝牙Socket通讯。

首先你得有两部Android设备,一个作为服务器,一个作为客户端。我把服务器与客户端的代码都写在同一个工程中,只需要选择当前设备是作为服务器,还是客户端就OK.

首先看下主界面的代码,用于选择服务器或客户端的。

public class MainActivity extends AppCompatActivity {private Button mServerButton, mClientButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        mClientButton.setOnClickListener(v -> {Intent intent = new Intent(MainActivity.this, ClientActivity.class);
            startActivity(intent);
        });
        mServerButton.setOnClickListener(v -> {Intent intent = new Intent(MainActivity.this, ServerActivity.class);
            startActivity(intent);
        });
    }private void initView() {mServerButton = findViewById(R.id.btn_server);
        mClientButton = findViewById(R.id.btn_client);
    }
}

很明显主界面有两个按钮,用于选择服务器或客户端。

我们先看下服务器的创建。

public class ServerActivity extends AppCompatActivity {private ListView mReceiveListView, mSendListView;
    private Button mSendButton, mSearchButton;
    private EditText mSendEditText;
    private BluetoothServer bluetoothServer;
    /**
     * 用于存放接收到的数据
     */
    private List<String> stringList = new ArrayList<>();
    /**
     * 用于存放历史数据
     */
    private List<String> strings = new ArrayList<>();
    private TimerTask timerTask = new TimerTask() {@Override
        public void run() {stringList = bluetoothServer.getMeg();
            runOnUiThread(() -> {ArrayAdapter arrayAdapter = new ArrayAdapter(ServerActivity.this, R.layout.support_simple_spinner_dropdown_item, stringList);
                mReceiveListView.setAdapter(arrayAdapter);
            });
        }};

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);
        initView();
        mSearchButton.setVisibility(View.GONE);
        bluetoothServer = new BluetoothServer(ServerActivity.this);
        bluetoothServer.start();
        Timer timer = new Timer();
        timer.schedule(timerTask, 0, 1000);
        mSendButton.setOnClickListener(v -> {bluetoothServer.sendData(mSendEditText.getText().toString());
            strings.add(mSendEditText.getText().toString());
            ArrayAdapter arrayAdapter = new ArrayAdapter(ServerActivity.this, R.layout.support_simple_spinner_dropdown_item, strings);
            mSendListView.setAdapter(arrayAdapter);
        });

    }private void initView() {mReceiveListView = findViewById(R.id.receive_list);
        mSendListView = findViewById(R.id.send_list);
        mSendButton = findViewById(R.id.btn_send);
        mSearchButton = findViewById(R.id.btn_search);
        mSendEditText = findViewById(R.id.send_et);
    }
}

服务器界面的工作主要有两个:

一:创建服务器。

bluetoothServer.start();

服务器如何创建需要重点看看start()里面的写法,稍后在蓝牙服务类里面有详解.

二:不断的接收客户端发送过来的数据及向客户端发送数据

 private TimerTask timerTask = new TimerTask() {@Override
        public void run() {stringList = bluetoothServer.getMeg();
            runOnUiThread(() -> {ArrayAdapter arrayAdapter = new ArrayAdapter(ServerActivity.this, R.layout.support_simple_spinner_dropdown_item, stringList);
                mReceiveListView.setAdapter(arrayAdapter);
            });
        }};
Timer timer = new Timer();
        timer.schedule(timerTask, 0, 1000);

这个定时器就是用于接收客户端发过来的数据。

向客户端发送数据就很简单,在蓝牙服务类里面的sendData()方法里面。

蓝牙服务界面的写法就这样,接着看看蓝牙客户端的写法:

public class ClientActivity extends AppCompatActivity {private ListView mReceiveListView, mSendListView;
    private Button mSendButton, mSearchButton;
    private EditText mSendEditText;
    /**
     *
     * 存放蓝牙设备列表
     */
    private List<BluetoothDevice> bluetoothDevices = new ArrayList<>();
    /**
     * 存放历史消息记录
     */
    private List<String> strings = new ArrayList<>();
    /**
     * 存放接收到的消息
     */
    private List<String> listMsg = new ArrayList<>();
    /**
     * 显示接收消息的定时器
     */
    private TimerTask timerTask = new TimerTask() {@Override
        public void run() {listMsg = mBluetoothClient.getMsg();
            runOnUiThread(() -> {ArrayAdapter arrayAdapter = new ArrayAdapter(ClientActivity.this, R.layout.support_simple_spinner_dropdown_item, listMsg);
                mReceiveListView.setAdapter(arrayAdapter);
            });
        }};
    /**
     * 蓝牙客户端
     */
    private BluetoothClient mBluetoothClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);
        mBluetoothClient = new BluetoothClient(ClientActivity.this);
        initView();
        listener();
        Timer timer = new Timer();
        timer.schedule(timerTask, 0, 1000);
    }private void initView() {mReceiveListView = findViewById(R.id.receive_list);
        mSendListView = findViewById(R.id.send_list);
        mSendButton = findViewById(R.id.btn_send);
        mSearchButton = findViewById(R.id.btn_search);
        mSendEditText = findViewById(R.id.send_et);
    }private void listener() {mSearchButton.setOnClickListener(v -> {mBluetoothClient.searchBluetooth();
        });
        mSendButton.setOnClickListener(v -> {mBluetoothClient.sendData(mSendEditText.getText().toString());
            strings.add(mSendEditText.getText().toString());
            ArrayAdapter arrayAdapter = new ArrayAdapter(ClientActivity.this, R.layout.support_simple_spinner_dropdown_item, strings);
            mSendListView.setAdapter(arrayAdapter);
        });
    }@Override
    protected void onResume() {super.onResume();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        registerReceiver(receiver, intentFilter);
    }@Override
    protected void onPause() {super.onPause();
        unregisterReceiver(receiver);
    }/**
     * 注册蓝牙搜索广播
     */
    private BroadcastReceiver receiver = new BroadcastReceiver() {@Override
        public void onReceive(Context context, Intent intent) {String action = intent.getAction();
            switch (action) {case BluetoothAdapter.ACTION_DISCOVERY_STARTED:mSearchButton.setText("正在搜索");
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:mSearchButton.setText("搜索");
                    AlertDialog.Builder builder = new AlertDialog.Builder(ClientActivity.this);
                    builder.setTitle("蓝牙搜索");
                    View view = View.inflate(ClientActivity.this, R.layout.activity_bluetoothdevice_listview, null);
                    builder.setView(view);
                    ListView mListView = view.findViewById(R.id.bluetooth_device);
                    BluetoothDeviceAdapter mBluetoothDeviceAdapter = new BluetoothDeviceAdapter(bluetoothDevices, ClientActivity.this);
                    mListView.setAdapter(mBluetoothDeviceAdapter);
                    builder.show();
                    mListView.setOnItemClickListener((parent, view1, position, id) -> {BluetoothDevice device = (BluetoothDevice) mBluetoothDeviceAdapter.getItem(position);
                        mBluetoothClient.connect(device);
                    });
                    break;
                case BluetoothDevice.ACTION_FOUND:BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    if (!bluetoothDevices.contains(device)) {bluetoothDevices.add(device);
                    }break;
                default:break;
            }}};
}

客户端的主要工作就是搜索蓝牙及连接蓝牙。在客户端也开了一个定时器,它的作用与服务器的定时器一样用于接收数据 ,接收服务器发送过来的数据 。

蓝牙的搜索及连接主要看看注册的广播。如有不懂得,可以去查下如何通过注册广播搜索蓝牙设备。

接着我们看看蓝牙服务类及蓝牙客户类的写法及作用。

一:蓝牙服务类。

这个类涉及到蓝牙服务器的创建及客户端与服务器的连接。先看下代码:

public class BluetoothServer {private Context context;
    /**
     * 创建服务器的名称
     */
    private String name = "FIUBluetoothServer";
    /**
     * 创建服务器所用的id
     */
    public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    /**
     * 创建线程池
     */
    private ExecutorService mExecutorService = Executors.newCachedThreadPool();

    /**
     * 蓝牙检测类
     */
    private BluetoothUtils mBluetoothUtils = new BluetoothUtils();
    /**
     * 蓝牙服务Socket
     */
    private BluetoothServerSocket mBluetoothServerSocket;
    /**
     * 蓝牙客户端Socket
     */
    private BluetoothSocket mBluetoothSocket;
    /**
     * 蓝牙服务器是否正在工作
     */
    private boolean isWorking;
    /**
     * 存放从客户端读取到的数据
     */
    private List<String> stringList = new ArrayList<>();

    public BluetoothServer(Context context) {this.context = context;
    }/**
     * 创建服务器,并连接客户端
     */
    public void start() {listener();
    }/**
     * 创建服务器监听
     */
    private void listener() {mExecutorService.execute(() -> {if (mBluetoothUtils.existBluetooth()) {if (mBluetoothUtils.openBluetooth()) {if (mBluetoothServerSocket == null) {try {mBluetoothServerSocket = BluetoothAdapter.getDefaultAdapter().listenUsingRfcommWithServiceRecord(name, MY_UUID);
                        } catch (IOException e) {e.printStackTrace();
                        }}isWorking = true;

                    try {mBluetoothSocket = mBluetoothServerSocket.accept();
                        handler.sendEmptyMessage(1);
                        readData();
                    } catch (IOException e) {e.printStackTrace();
                    }}} else {Toast.makeText(context, "该设备不支持蓝牙", Toast.LENGTH_LONG).show();
            }});
    }/**
     * 读取数据
     */
    private void readData() {mExecutorService.execute(() -> {try {InputStream inputStream = mBluetoothSocket.getInputStream();
                byte[] buffer = new byte[1024];
                while (isWorking) {int read = inputStream.read(buffer);
                    if (read != -1) {StringBuilder stringBuilder = new StringBuilder();
                        if (read < buffer.length) {String s = new String(buffer, 0, read);
                            stringBuilder.append(s);
                        }synchronized (stringList) {stringList.add("客户端发送"+stringBuilder.toString());
                        }}}mBluetoothSocket.close();
            } catch (IOException e) {e.printStackTrace();
            }});
    }public List<String> getMeg() {return stringList;
    }/**
     * 发送数据
     * @param msg
     */
    public void sendData(String msg) {try {byte[] b = msg.getBytes();
            mBluetoothSocket.getOutputStream().write(b);
            mBluetoothSocket.getOutputStream().flush();
        } catch (IOException e) {e.printStackTrace();
        }}private Handler handler = new Handler(msg -> {switch (msg.what) {case 1:Toast.makeText(context, "客户端已连接" +mBluetoothSocket.getRemoteDevice().getName(), Toast.LENGTH_LONG).show();
                break;
            default:break;
        }return false;
    });

在这个类里面创建的变量及方法我都有写注释。看注释应该能明白大致作用.

  public void start() {listener();
    }

start()方法在前面讲过,这个方法是创建蓝牙服务器的主要方法,在这个方法里面有一个listener()的方法。listener()方法是创建服务器的监听方法。在这个方法里面有一行代码:

  mBluetoothServerSocket = BluetoothAdapter.getDefaultAdapter().listenUsingRfcommWithServiceRecord(name, MY_UUID);

这行代码就是创建服务器的主要代码。就靠它创建服务器。name是创建的服务器名称,MY_UUID是创建服务器的唯一识别id。

我上面写的id是可以用的。

关羽readData()与sendData()两个方法里面的数据读取与写入都是依靠流操作完成的。有不懂的可以去学习下有关流的知识。在这个类里面服务器的创建及数据的读取、写入最为关键。这两大点学会就ok了。

蓝牙服务类看完了,我们再来看看蓝牙客户端的蓝牙类怎么写。

public class BluetoothClient {private Context context;
    private BluetoothUtils mBluetoothUtils = new BluetoothUtils();
    private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    /**
     * 客户端Socket
     */
    private BluetoothSocket mBluetoothSocket;
    /**
     * 连接服务器的uuid
     */
    public final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    /**
     * 数据输入输出流
     */
    private OutputStream outputStream;
    private InputStream inputStream;
    /**
     * 存放读取到的数据
     */
    private List<String> strings = new ArrayList<>();
    private StringBuilder stringBuilder = new StringBuilder();
    /**
     * 是否正在工作
     */
    private boolean isWorking;

    private ExecutorService mExecutorService;

    public BluetoothClient(Context context) {this.context = context;
        mExecutorService = Executors.newCachedThreadPool();
    }public void searchBluetooth() {if (mBluetoothUtils.existBluetooth()) {if (mBluetoothUtils.openBluetooth()) {if (mBluetoothAdapter.isDiscovering()) {mBluetoothAdapter.cancelDiscovery();
                }mBluetoothAdapter.startDiscovery();
            }} else {Toast.makeText(context, "蓝牙不被支持使用", Toast.LENGTH_LONG).show();
        }}public void connect(BluetoothDevice bluetoothDevice) {mExecutorService.execute(() -> {try {mBluetoothSocket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(uuid);
                mBluetoothSocket.connect();
                isWorking = true;
                outputStream = mBluetoothSocket.getOutputStream();
                inputStream = mBluetoothSocket.getInputStream();
                readData();
            } catch (IOException e) {e.printStackTrace();
            }});

    }public void sendData(String msg) {mExecutorService.execute(() -> {if (mBluetoothSocket != null) {if (outputStream != null) {byte[] bytes = msg.getBytes();
                    try {outputStream.write(bytes);
                        outputStream.flush();
                    } catch (IOException e) {e.printStackTrace();
                    }}}});
    }/**
     * strings
     *
     * @return
     */
    public List<String> getMsg() {synchronized (strings) {return strings;
        }}public void readData() {mExecutorService.execute(() -> {byte[] buffer = new byte[1024 * 2];
            while (isWorking) {try {int read = inputStream.read(buffer);
                    if (read != -1) {stringBuilder.delete(0, stringBuilder.length());
                        if (read < buffer.length) {String s = new String(buffer, 0, read);
                            stringBuilder.append(s);
                        }synchronized (strings) {strings.add("服务器发送" + stringBuilder.toString());
                        }}} catch (IOException e) {e.printStackTrace();
                }}try {mBluetoothSocket.close();
            } catch (IOException e) {e.printStackTrace();
            }});
    }
}

在前面说过蓝牙客户端主要负责蓝牙的搜索及连接。看上面代码是不是很容易就能发现搜索部分及连接部分。就在searchBluetooth()与connnect()这连个方法里面。这两个方法搞清楚了,其他的是不是和蓝牙服务类基本一样。

蓝牙Socket通讯相关推荐

  1. Android蓝牙串口通讯【转】

    本文转载自:http://blog.sina.com.cn/s/blog_631e3f2601012ixi.html Android蓝牙串口通讯 闲着无聊玩起了Android蓝牙模块与单片机蓝牙模块的 ...

  2. android蓝牙串口通讯

    2019独角兽企业重金招聘Python工程师标准>>> 最近做的项目用到了蓝牙串口通讯功能.毕竟是接触到底层的一些东西,让吾等局限于java编程思想的小菜遇到了一些意想不到的问题. ...

  3. 蓝牙双向通讯【可自定义协议】SDK

    一.简介: 此文档主要是介绍蓝牙双向通讯sdk的调用方法以及蓝牙双向传输的核心功能逻辑,用户可以根据需要自定义协议进行蓝牙双向通讯 二.SDK接入步骤: 1: 增加sdk库依赖: a)libs文件夹下 ...

  4. 蓝牙聊天App设计3:Android Studio制作蓝牙聊天通讯软件(完结,蓝牙连接聊天,结合生活情景进行蓝牙通信的通俗讲解,以及代码功能实现,内容详细,讲解通俗易懂)

    前言:蓝牙聊天App设计全部有三篇文章(一.UI界面设计,二.蓝牙搜索配对连接实现,三.蓝牙连接聊天),这篇文章是:三.蓝牙连接聊天. 课程1:Android Studio小白安装教程,以及第一个An ...

  5. Java与C++Socket通讯注意

    2019独角兽企业重金招聘Python工程师标准>>> c++与java进行socket通信时注意事项 因为java发送的都是网络字节序(big-endium),而c++是主机字节序 ...

  6. [置顶] 【C#】 Socket通讯客户端程序

    这段时间一直在优化Socket通讯这块,经常和Socket打交道,现在分享给大家一个小的案例, 代码如下: byte[] m_dataBuffer = new byte [10];         I ...

  7. java与 C++ 之间进行 SOCKET 通讯要点简要解析

    Endian定义: 在计算机系统体系结构中用来描述在多字节数中各个字节的存储顺序. big-endian也称高位在前.大端在前.是 计算机体系结构中一种描述多字节存储顺序的术语,在这种机制中最重要字节 ...

  8. as3 java 交互_求大佬用 Java 实现这段 AS3 的 socket 通讯功能

    最近在分析一个直播网站,初步分析后发现是在 swf 中用 socket 通讯返回的 flv 地址. 其中 Actionscript socket 通讯的关键代码如下: this._socket = n ...

  9. 基于TCP的Socket通讯

    基于 TCP 的 Socket 通讯 最近要实现两个机器之间基于 TCP 的 socket 通讯(个人使用 Python 实现),尝试了官方的 demo 代码后总是被拒绝连接,仔细研究了一下并成功建立 ...

  10. Socket网络通讯开发总结之:Java 与 C进行Socket通讯

    先交待一下业务应用背景: 服务端:移动交费系统:基于C语言的Unix系统 客户端:增值服务系统:基于Java的软件系统 通迅协议:采用TCP/IP协议,使用TCP以异步方式接入 数据传输:基于Sock ...

最新文章

  1. 使用OpenCV 实现matlab的padarray(A, padsize, ‘symmetric’)函数简单实现
  2. java算法2_二分查找法
  3. 再论SAP云平台上CloudFoundry编程环境的connectivity
  4. Teams架构剖析(2019年版本)
  5. 推荐系统遇上深度学习(七)--NFM模型理论和实践
  6. ESXi开启SSH的方法总结
  7. python(十一)接口开发、写日志、发邮件、python来发请求、手动添加环境变量...
  8. 台湾ICPlus IP178G/GH/GI 8接口FE以太网交换机芯片详细介绍
  9. SAP检验批次批量取消程序示例(备份)
  10. mysql前台工具下载_phpmyadmin工具下载
  11. Kafka安装详细教程
  12. java实现简易计算器,实现加减乘除,括号,算式查错,
  13. Theano2.1.12-基础知识之使用GPU
  14. mt6765和骁龙665哪个好_联发科MT6750和骁龙450哪个好 高通骁龙450与联发科MT6750区别对比评测...
  15. 《用户体验设计:100堂入门课》20190920
  16. Cream Finance 重入漏洞事件分析
  17. Data (Privacy) Regulation 数据隐私法规整理
  18. android平板下架,小米平板电脑下架 号称最好用的安卓平板成绝唱
  19. oracle scott用户来历,Oracle应用之Scott用户简介
  20. 南大通用GBase8s 常用SQL语句(284)

热门文章

  1. Ruby on Rails 教程
  2. Java、数据库等面试题大全
  3. 通知的各种实用写法技巧
  4. php rrd getcreator,Cacti ERROR: opening '*.rrd': No such file or directory 解决方法
  5. 词法分析与词性标注学习之笔记(二)----词性标注
  6. ppt制作心得【转发】
  7. win10系统更新后打开chrome浏览器几秒后自动闪退
  8. 火狐浏览器批量保存网页图片
  9. 高通Thermal debug
  10. 包学会之浅入浅出Vue.js:开学篇(转)