Android开发之BlueTooth--最简单的Andorid传统蓝牙通讯Demo

又到了Android小白的开发之路上写笔记的时间了~~

开篇都不知道说什么好... ...前两个月写了WIFI,后来也想写一下蓝牙的,可惜公司产品不给力,出现了很多BUG,一直在修啊修,最近终于有点空闲时间了。那就来简单的尝试一下

关于蓝牙开发,优秀博客一大片,你能来看我这篇辣鸡文章真是不胜感激。基础知识/理论什么的我就不说了,我也是一边看着官方文档来的,想深入了解去看看官方文档也是极好的。

我们知道Andorid的蓝牙分为两种,一种是传统的一种是低功耗蓝牙(BLE),一步一步来,这里先写一下传统蓝牙~


功能实现

主要是实现两台手机能通过蓝牙相互发送消息。两手机可以任意一台充当服务端,一台充当客户端。过程尽量越简单,让大家看的更清楚!


代码-准备工作

1.首先我们需要一个蓝牙适配器,用于搜索设备/连接设备;一个UUID,用于创建服务端;一个广播接收器,用于监听搜索结果。

    public static final String BT_UUID = "00001101-0000-1000-8000-00805F9B34FB";//uuid

    private BluetoothAdapter mBluetoothAdapter;//蓝牙适配器
    private BlueToothStateReceiver mReceiver;//广播接收器
    private ConnectThread mConnectThread; //客户端线程
    private AcceptThread mAcceptThread; //服务端线程


2.然后先打开蓝牙

 private void openBT() {
        if (mBluetoothAdapter == null) {
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        }
        //1.设备不支持蓝牙,结束应用
        if (mBluetoothAdapter == null) {
            finish();
            return;
        }
        //2.判断蓝牙是否打开
        if (!mBluetoothAdapter.enable()) {
            //没打开请求打开
            Intent btEnable = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(btEnable, REQUEST_BT_ENABLE_CODE);
        }
    }

3.注册广播接收器

private void registerRec() {
        //3.注册蓝牙广播
        mReceiver = new BlueToothStateReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_FOUND);//搜多到蓝牙
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索结束
        registerReceiver(mReceiver, filter);
    }

4.开始搜索设备

if (mBluetoothAdapter != null) {
    mBluetoothAdapter.startDiscovery();
}

5.获取搜索结果

class BlueToothStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(MainActivity.this, "触发广播", Toast.LENGTH_SHORT).show();
            String action = intent.getAction();
            switch (action) {
                case BluetoothDevice.ACTION_FOUND:
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    Toast.makeText(MainActivity.this, "找到设备" + device.getName(), Toast.LENGTH_SHORT).show();
                    if (mRvAdapter != null) {
                        mRvAdapter.addDevice(device);
                    }
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                    mMessageAdapter.addMessage("搜索结束");
                    break;
            }
        }
    }


额~~还忘了一步,搜索完到指定设备后要记得关闭搜索

if (mBluetoothAdapter != null && mBluetoothAdapter.isDiscovering()) {  
                    mBluetoothAdapter.cancelDiscovery();  
                }  


----------------------------然后基础的就到这里了----------------------------------


接下来,是点击列表,然后连接对应的蓝牙。

开头说了,要实现两台手机任意充当客户端或者服务端,所以在程序中应该包含有服务端也要有客户端,因此我们需要两个线程,分别处理这两种情况。


6.首先服务端线程代码--里面有些没用到或者注释的代码还有一些通知UI更新的代码,大家可以忽略

 class AcceptThread extends Thread {
        private BluetoothServerSocket mServerSocket;
        private BluetoothSocket mSocket;
        private InputStream btIs;
        private OutputStream btOs;
        private PrintWriter writer;
        private boolean canAccept;
        private boolean canRecv;

        public AcceptThread() {
            canAccept = true;
            canRecv = true;
        }

        @Override
        public void run() {
            try {
                //获取套接字
                BluetoothServerSocket temp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("TEST", UUID.fromString(BT_UUID));
                mServerSocket = temp;
                //监听连接请求 -- 作为测试,只允许连接一个设备
                if (mServerSocket != null) {
                    // while (canAccept) {
                    mSocket = mServerSocket.accept();//阻塞等待客户端连接
                    sendHandlerMsg("有客户端连接");
                    // }
                }
                //获取输入输出流
                btIs = mSocket.getInputStream();
                btOs = mSocket.getOutputStream();
                //通讯-接收消息
                BufferedReader reader = new BufferedReader(new InputStreamReader(btIs, "UTF-8"));
                String content = null;
                while (canRecv) {
                    content = reader.readLine();
                    sendHandlerMsg("收到消息:" + content);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (mSocket != null) {
                        mSocket.close();
                    }
                    // btIs.close();//两个输出流都依赖socket,关闭socket即可
                    // btOs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    sendHandlerMsg("错误:" + e.getMessage());
                }
            }
        }

        private void sendHandlerMsg(String content) {
            Message msg = mHandler.obtainMessage();
            msg.what = 1001;
            msg.obj = content;
            mHandler.sendMessage(msg);
        }

        public void write(String msg) {
            if (btOs != null) {
                try {
                    if (writer == null) {
                        writer = new PrintWriter(new OutputStreamWriter(btOs, "UTF-8"), true);
                    }
                    writer.println(msg);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    writer.close();
                    sendHandlerMsg("错误:" + e.getMessage());
                }
            }
        }
    }

7.连接线程代码--用于点击某个设备后建立连接--同样里面有些没用到或者注释的代码用于以后拓展的,还有一些通知UI更新的代码,大家可以忽略

class ConnectThread extends Thread {
        private BluetoothDevice mDevice;
        private BluetoothSocket mSocket;
        private InputStream btIs;
        private OutputStream btOs;
        private boolean canRecv;
        private PrintWriter writer;

        public ConnectThread(BluetoothDevice device) {
            mDevice = device;//被点击设备
            canRecv = true;
        }

        @Override
        public void run() {
            if (mDevice != null) {
                try {
                    //获取套接字
                    BluetoothSocket temp = mDevice.createInsecureRfcommSocketToServiceRecord(UUID.fromString(BT_UUID));
                    //mDevice.createRfcommSocketToServiceRecord(UUID.fromString(BT_UUID));//sdk 2.3以下使用
                    mSocket = temp;
                    //发起连接请求
                    if (mSocket != null) {
                        mSocket.connect();
                    }
                    sendHandlerMsg("连接 " + mDevice.getName() + "成功!");
                    //获取输入输出流
                    btIs = mSocket.getInputStream();
                    btOs = mSocket.getOutputStream();

                    //通讯-接收消息
                    BufferedReader reader = new BufferedReader(new InputStreamReader(btIs, "UTF-8"));
                    String content = null;
                    while (canRecv) {
                        content = reader.readLine();
                        sendHandlerMsg("收到消息:" + content);
                    }


                } catch (IOException e) {
                    e.printStackTrace();
                    sendHandlerMsg("错误:" + e.getMessage());
                } finally {
                    try {
                        if (mSocket != null) {
                            mSocket.close();
                        }
                        //btIs.close();//两个输出流都依赖socket,关闭socket即可
                        //btOs.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        sendHandlerMsg("错误:" + e.getMessage());
                    }
                }
            }
        }

        private void sendHandlerMsg(String content) {
            Message msg = mHandler.obtainMessage();
            msg.what = 1001;
            msg.obj = content;
            mHandler.sendMessage(msg);
        }

        public void write(String msg) {
            if (btOs != null) {
                try {
                    if (writer == null) {
                        writer = new PrintWriter(new OutputStreamWriter(btOs, "UTF-8"), true);
                    }
                    writer.println(msg);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    writer.close();
                    sendHandlerMsg("错误:" + e.getMessage());
                }
            }
        }
    }

8.然后这个两个线程的开启时机我是这么来设置的:服务端是开启蓝牙后立马启动,连接线程是点击了某个设备发起连接请求时启动。

                openBT();
                mMessageAdapter.addMessage("打开蓝牙");
                if (mAcceptThread == null && mBluetoothAdapter != null) {
                    mAcceptThread = new AcceptThread();
                    mAcceptThread.start();
                    mMessageAdapter.addMessage("启动服务线程");
                }
mRvAdapter.setOnItemClickListener(new RvAdapter.OnItemClickListener() {
            @Override
            public void onClick(BluetoothDevice device) {
                mConnectThread = new ConnectThread(device);
                mConnectThread.start();
            }
        });

9.连接上别人或者别人连接我们之后就可以进行通讯了。要发送消息,直接调用对应线程的write()方法即可。大致流程就这样。还是挺简单的。接下来给大家看一下全部的代码:

看全部代码前给大家先看运行效果图,我怕大家没耐心看到后面。操作:两个设备都点击打开蓝牙,然后搜索,找出设备点击停止。最后设备1点击结果中的设备2,互发消息。 ps:设备1 Android 4.0     设备2(OnePlus3T) Android 7.1

设备1截图:

Android开发之BlueTooth--最简单的Andorid传统蓝牙通讯Demo_第1张图片

设备2截图:

Android开发之BlueTooth--最简单的Andorid传统蓝牙通讯Demo_第2张图片

-放全部代码:

首先是我的布局:消息列表显示的是各种消息,什么有客户端连接,收到什么消息,发送什么消息等。截图如下:

Android开发之BlueTooth--最简单的Andorid传统蓝牙通讯Demo_第3张图片




    

        

然后是Activity代码,这里代码可能有点多而且乱,大家按照上面的步骤来看就清楚多了。本来大部分都是交给服务来做的,谷歌文档官方就是这么干的。我这里为了直观看到所有代码,就没用服务。大家将就看看

package cn.small_qi.bluetoothtest;

import android.Manifest;
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.Build;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.UUID;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    public static final int REQUEST_BT_ENABLE_CODE = 200;
    public static final String BT_UUID = "00001101-0000-1000-8000-00805F9B34FB";//uuid

    private BluetoothAdapter mBluetoothAdapter;//蓝牙适配器
    private BlueToothStateReceiver mReceiver;//广播接收器
    private ConnectThread mConnectThread; //客户端线程
    private AcceptThread mAcceptThread; //服务端线程

    private RecyclerView mRecyclerView;
    private RvAdapter mRvAdapter;

    private RecyclerView mMessageView;
    private static MsgAdapter mMessageAdapter;

    private EditText inputEt;

    private static Handler mHandler = new Handler() {
        @Override
        public void dispatchMessage(Message msg) {
            mMessageAdapter.addMessage((String) msg.obj);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //这是我是为了6.0以上的设备能搜索到结果,动态申请了位置权限。但是没有处理结果,因为我测试肯定点同意~- -
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 1001);
        }
        initUI();
        registerRec();
    }

    private void initUI() {
        findViewById(R.id.open).setOnClickListener(this);
        findViewById(R.id.close).setOnClickListener(this);
        findViewById(R.id.start).setOnClickListener(this);
        findViewById(R.id.stop).setOnClickListener(this);
        findViewById(R.id.send).setOnClickListener(this);

        inputEt = (EditText) findViewById(R.id.input);

        mRecyclerView = (RecyclerView) findViewById(R.id.devices);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRvAdapter = new RvAdapter(this);
        mRecyclerView.setAdapter(mRvAdapter);
        mRvAdapter.setOnItemClickListener(new RvAdapter.OnItemClickListener() {
            @Override
            public void onClick(BluetoothDevice device) {
                mConnectThread = new ConnectThread(device);
                mConnectThread.start();
            }
        });

        mMessageView = (RecyclerView) findViewById(R.id.msglist);
        mMessageView.setLayoutManager(new LinearLayoutManager(this));
        mMessageAdapter = new MsgAdapter(this);
        mMessageView.setAdapter(mMessageAdapter);
    }


    private void openBT() {
        if (mBluetoothAdapter == null) {
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        }
        //1.设备不支持蓝牙,结束应用
        if (mBluetoothAdapter == null) {
            finish();
            return;
        }
        //2.判断蓝牙是否打开
        if (!mBluetoothAdapter.enable()) {
            //没打开请求打开
            Intent btEnable = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(btEnable, REQUEST_BT_ENABLE_CODE);
        }
    }

    private void registerRec() {
        //3.注册蓝牙广播
        mReceiver = new BlueToothStateReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_FOUND);//搜多到蓝牙
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索结束
        registerReceiver(mReceiver, filter);
    }

    @Override
    protected void onDestroy() {
        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
        }
        super.onDestroy();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_BT_ENABLE_CODE) {
            if (resultCode == RESULT_OK) {
                //用户允许打开蓝牙
                mMessageAdapter.addMessage("用户同意打开蓝牙");
            } else if (resultCode == RESULT_CANCELED) {
                //用户取消打开蓝牙
                mMessageAdapter.addMessage("用户拒绝打开蓝牙");
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.open:
                openBT();
                mMessageAdapter.addMessage("打开蓝牙");
                if (mAcceptThread == null && mBluetoothAdapter != null) {
                    mAcceptThread = new AcceptThread();
                    mAcceptThread.start();
                    mMessageAdapter.addMessage("启动服务线程");
                }
                break;
            case R.id.close:
                mBluetoothAdapter.disable();
                break;
            case R.id.start:
                if (mBluetoothAdapter != null) {
                    mRvAdapter.clearDevices();//开始搜索前清空上一次的列表
                    mBluetoothAdapter.startDiscovery();
                    mMessageAdapter.addMessage("开始搜索蓝牙");
                } else {
                    openBT();
                    if (mBluetoothAdapter != null) {
                        mRvAdapter.clearDevices();//开始搜索前清空上一次的列表
                        mBluetoothAdapter.startDiscovery();
                        mMessageAdapter.addMessage("开始搜索蓝牙");
                    }
                }
                break;
            case R.id.stop:
                if (mBluetoothAdapter != null && mBluetoothAdapter.isDiscovering()) {
                    mBluetoothAdapter.cancelDiscovery();
                }
                break;
            case R.id.send:
                /**
                 * 如何区分我是使用服务端的socket还是使用客户端的socket发送消息
                 *  1. 在单一环境下,手机一般作为客户端,外围设备是服务器。所以手机完全可以不用创建服务器,不存在这个问题。
                 *  2. 假如是两台手机用来聊天,可分别充当服务器和客户端,那就是发起连接方(即点击设备列表连接)作为客户端。
                 *  3. 假如我链接了别人,另一个人又连接了我,那我怎么区分?那你写两个界面啊~你要回复其他客户端发来的消息就用服务器的socket
                 *  否则就用客户端的。我这里偷懒了,一但我主动连接别人,相当于我就关闭服务端了,不给别人连我了。
                 *  4. 那那些蓝牙对战游戏都怎么区分的?你发现蓝牙对战需要一个人先创建房间没?那个人就是服务端,其他都是客户端,没这个问题。
                 */
                String msg = inputEt.getText().toString();
                if (TextUtils.isEmpty(msg)) {
                    Toast.makeText(this, "消息为空", Toast.LENGTH_SHORT).show();
                    return;
                }
                if (mConnectThread != null) {//证明我主动去链接别人了
                    mConnectThread.write(msg);
                } else if (mAcceptThread != null) {
                    mAcceptThread.write(msg);
                }
                mMessageAdapter.addMessage("发送消息:" + msg);
                break;
        }
    }

    class BlueToothStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(MainActivity.this, "触发广播", Toast.LENGTH_SHORT).show();
            String action = intent.getAction();
            switch (action) {
                case BluetoothDevice.ACTION_FOUND:
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    Toast.makeText(MainActivity.this, "找到设备" + device.getName(), Toast.LENGTH_SHORT).show();
                    if (mRvAdapter != null) {
                        mRvAdapter.addDevice(device);
                    }
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                    mMessageAdapter.addMessage("搜索结束");
                    break;
            }
        }
    }


    class ConnectThread extends Thread {
        private BluetoothDevice mDevice;
        private BluetoothSocket mSocket;
        private InputStream btIs;
        private OutputStream btOs;
        private boolean canRecv;
        private PrintWriter writer;

        public ConnectThread(BluetoothDevice device) {
            mDevice = device;
            canRecv = true;
        }

        @Override
        public void run() {
            if (mDevice != null) {
                try {
                    //获取套接字
                    BluetoothSocket temp = mDevice.createInsecureRfcommSocketToServiceRecord(UUID.fromString(BT_UUID));
                    //mDevice.createRfcommSocketToServiceRecord(UUID.fromString(BT_UUID));//sdk 2.3以下使用
                    mSocket = temp;
                    //发起连接请求
                    if (mSocket != null) {
                        mSocket.connect();
                    }
                    sendHandlerMsg("连接 " + mDevice.getName() + "成功!");
                    //获取输入输出流
                    btIs = mSocket.getInputStream();
                    btOs = mSocket.getOutputStream();

                    //通讯-接收消息
                    BufferedReader reader = new BufferedReader(new InputStreamReader(btIs, "UTF-8"));
                    String content = null;
                    while (canRecv) {
                        content = reader.readLine();
                        sendHandlerMsg("收到消息:" + content);
                    }


                } catch (IOException e) {
                    e.printStackTrace();
                    sendHandlerMsg("错误:" + e.getMessage());
                } finally {
                    try {
                        if (mSocket != null) {
                            mSocket.close();
                        }
                        //btIs.close();//两个输出流都依赖socket,关闭socket即可
                        //btOs.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        sendHandlerMsg("错误:" + e.getMessage());
                    }
                }
            }
        }

        private void sendHandlerMsg(String content) {
            Message msg = mHandler.obtainMessage();
            msg.what = 1001;
            msg.obj = content;
            mHandler.sendMessage(msg);
        }

        public void write(String msg) {
            if (btOs != null) {
                try {
                    if (writer == null) {
                        writer = new PrintWriter(new OutputStreamWriter(btOs, "UTF-8"), true);
                    }
                    writer.println(msg);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    writer.close();
                    sendHandlerMsg("错误:" + e.getMessage());
                }
            }
        }
    }

    class AcceptThread extends Thread {
        private BluetoothServerSocket mServerSocket;
        private BluetoothSocket mSocket;
        private InputStream btIs;
        private OutputStream btOs;
        private PrintWriter writer;
        private boolean canAccept;
        private boolean canRecv;

        public AcceptThread() {
            canAccept = true;
            canRecv = true;
        }

        @Override
        public void run() {
            try {
                //获取套接字
                BluetoothServerSocket temp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("TEST", UUID.fromString(BT_UUID));
                mServerSocket = temp;
                //监听连接请求 -- 作为测试,只允许连接一个设备
                if (mServerSocket != null) {
                    // while (canAccept) {
                    mSocket = mServerSocket.accept();
                    sendHandlerMsg("有客户端连接");
                    // }
                }
                //获取输入输出流
                btIs = mSocket.getInputStream();
                btOs = mSocket.getOutputStream();
                //通讯-接收消息
                BufferedReader reader = new BufferedReader(new InputStreamReader(btIs, "UTF-8"));
                String content = null;
                while (canRecv) {
                    content = reader.readLine();
                    sendHandlerMsg("收到消息:" + content);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (mSocket != null) {
                        mSocket.close();
                    }
                    // btIs.close();//两个输出流都依赖socket,关闭socket即可
                    // btOs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    sendHandlerMsg("错误:" + e.getMessage());
                }
            }
        }

        private void sendHandlerMsg(String content) {
            Message msg = mHandler.obtainMessage();
            msg.what = 1001;
            msg.obj = content;
            mHandler.sendMessage(msg);
        }

        public void write(String msg) {
            if (btOs != null) {
                try {
                    if (writer == null) {
                        writer = new PrintWriter(new OutputStreamWriter(btOs, "UTF-8"), true);
                    }
                    writer.println(msg);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    writer.close();
                    sendHandlerMsg("错误:" + e.getMessage());
                }
            }
        }
    }


}


然后是两个RecycleView的适配器

消息列表:

package cn.small_qi.bluetoothtest;

import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by small_qi on 2017/9/13.
 */

public class MsgAdapter extends RecyclerView.Adapter{
    private Context mContext;
    private List msgList;


    public MsgAdapter(Context mContext) {
        this.mContext = mContext;
        msgList = new ArrayList<>();
    }

    @Override
    public MsgAdapter.MsgHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MsgAdapter.MsgHolder(LayoutInflater.from(mContext).inflate(R.layout.item,parent,false));
    }

    @Override
    public void onBindViewHolder(MsgAdapter.MsgHolder holder, final int position) {
       holder.nameTv.setText(msgList.get(position));
    }

    @Override
    public int getItemCount() {
        return msgList.size();
    }

    public void addMessage(String msg) {
        msgList.add(msg);
        notifyItemInserted(msgList.size()-1);
    }

    public void clearMsgList(){
        msgList.clear();
        notifyDataSetChanged();
    }

    public interface OnItemClickListener{
        void onClick(BluetoothDevice device);
    }

    class MsgHolder extends RecyclerView.ViewHolder{
        private TextView nameTv;
        public MsgHolder(View itemView) {
            super(itemView);
            nameTv = itemView.findViewById(R.id.name);
        }
    }
}

设备列表(有个点击回调):

package cn.small_qi.bluetoothtest;

import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by small_qi on 2017/9/13.
 */

public class RvAdapter extends RecyclerView.Adapter{
    private Context mContext;
    private List mDevices;
    private OnItemClickListener onItemClickListener;

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public RvAdapter(Context mContext) {
        this.mContext = mContext;
        mDevices = new ArrayList<>();
    }

    @Override
    public RvHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new RvHolder(LayoutInflater.from(mContext).inflate(R.layout.item,parent,false));
    }

    @Override
    public void onBindViewHolder(RvHolder holder, final int position) {
        holder.nameTv.setText(mDevices.get(position).getName()+":"+mDevices.get(position).getAddress());
        //点击事件 点击配对
        if (onItemClickListener!=null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    onItemClickListener.onClick(mDevices.get(position));
                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return mDevices.size();
    }

    public void addDevice(BluetoothDevice device) {
        mDevices.add(device);
        notifyItemInserted(mDevices.size()-1);
    }

    public void clearDevices(){
        mDevices.clear();
        notifyDataSetChanged();
    }

    public interface OnItemClickListener{
        void onClick(BluetoothDevice device);
    }

    class RvHolder extends RecyclerView.ViewHolder{
        private TextView nameTv;
        public RvHolder(View itemView) {
            super(itemView);
            nameTv = itemView.findViewById(R.id.name);
        }
    }
}

列表Item的布局,两个用的同一个布局



    



全部代码就这些了。主要展示的是蓝牙的基本使用流程,要达到标准的使用,还需要做大量优化和修改~这就要根据业务需求来了。就像我这里,用手机实时获取同步并记录万用表的测量数据,如果不用BLE,其实就是万用表充当服务端,我一旦连接,就给我发送约定好的数据格式,我在客户端进行解析就可以了。这样的功能这个例子就可以完全模拟出来了~~


非常感谢您能看到最后~这Demo实现了,两个设备相互聊天。其实获取到socekt后,就不关蓝牙什么事了,主要是考察对socket通讯的使用了。例子中只实现了1V1聊天,至于一对多还有文件传输,可以看看我之前的Socket通讯的博客哦~博客中的WIFI通讯相关中也有类似的功能,大家有兴趣可以看看,虽然不是什么深度优秀文章。

demo就是demo各种处理都不完善,而且我只是个小白白,有问题在所难免,大家见谅。有问题评论中指出~谢谢 have a nice day


你可能感兴趣的:(Android开发之BlueTooth--最简单的Andorid传统蓝牙通讯Demo)