前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BlueTooth聊天软件(支持表情和语音)

BlueTooth聊天软件(支持表情和语音)

作者头像
提莫队长
发布2019-02-21 11:05:44
1.8K0
发布2019-02-21 11:05:44
举报
文章被收录于专栏:刘晓杰刘晓杰

首先声明,这是从官方给出的demo修改而来的。

第一:官方demo的注解

1.三个用到的Thread的意义: (1)AcceptThread 服务器端,起监听作用。(accept函数) (2)ConnectThread This thread runs while attempting to make an outgoing connection with a device.(正在试图连接) (3)ConnectedThread This thread runs during a connection with a remote device. It handles all incoming and outgoing transmissions.(已经连接,准备进行数据交换)

2.流程 BluetoothChat加载的同时启动BluetoothChatService。 (1)点击右上角的“瞄准镜”图标,调用ensureDiscoverable,使自己可被周围的蓝牙检测到 (2)点击右上角的“搜索”图标,进入DeviceListActivity。它其实是一个对话框,显示了已经配对的蓝牙和一个button。点击button调用doDiscovery搜索周围的蓝牙设备,同时使自己不可见。 点击蓝牙列表中的任意一项,响应OnItemClickListener,将需要的信息通过intent回传给BluetoothChat。同时,DeviceListActivity注册一个BroadcastReceiver检测是否四周有新打开的BluetoothDevice (3)BluetoothChat响应onActivityResult,调用connectDevice。获取传过来的intent数据,马上再调用BluetoothChatService的connect方法。 在这个方法里面取消正在试图连接或者已经连接的线程。然后重启一个试图连接的线程(ConnectThread),并设置状态位,在BluetoothChat的mHandler处获得响应 4.ConnectThread里面mmSocket.connect();表示已连接。如果失败,调用connectionFailed然后return。如果成功,调用connected(mmSocket, mmDevice, mSocketType)。 connectionFailed函数把“失败”的消息传给handler交给BluetoothChat来显示,然后调用BluetoothChatService.this.start()取消正在试图连接或者已经连接的线程,然后重启一个AcceptThread线程继续监听(accept)。 connected(mmSocket, mmDevice, mSocketType)取消所有线程,开启ConnectedThread进行数据传输,同时通过handler向BluetoothChat发送“连接成功”消息。 5.ConnectedThread里面就是io和数据传输。传输过程中可能会有蓝牙掉线。调用connectionLost,重启BluetoothChatService

第二:新增功能

(1)通过点击edittext之外的部分使软键盘隐藏 setupUI(findViewById(R.id.root));//定义main.xml里面最大的LinearLayout的id=root 函数功能:遍历所有控件,包括子控件,只要点击的view不是Edittext就隐藏软键盘

(2)表情传输 initFaceView(); 利用反射机制实现“根据文件名加载图片“ 再将图片信息以二进制数据的形式传给另一端,另一端得到数据后用正则表达式来判断消息内是否有表情 SpannableString spannableString = ExpressionUtil.getExpressionString(context, str, zhengze);

(3)语音传输 数据传输部分,官方给的方法对于语音不适合。

代码语言:javascript
复制
byte[] buffer = new byte[1024];
bytes = mmInStream.read(buffer);

官方给的1024缓存对于字符而言够了,但是对于语音不够。 蓝牙传输速度有限,一个几秒的语音就要分好几次,所以要全部读完再来判断 所以要修改ConnectedThread中的run方法。同时记住,获取完所有数据以后不能结束run方法。因为还有数据的传输

代码语言:javascript
复制
        public void run() {
            Log.i(TAG, "BEGIN mConnectedThread");
            byte[] buffer = new byte[1024];
            int bytes = 0;
            String source = "";

            // 获得所有数据
            // 官方给的方法对于语音不适合。蓝牙传输速度有限,一个几秒的语音就要分好几次
            // 所以要全部读完再来判断
            while (true) {
                try {
                    bytes = mmInStream.read(buffer);
                    String temp = new String(buffer, 0, bytes);
                    source += temp;
                    Log.i("bytes", bytes + "");
                    // 这个989是通过后台log查看到的,具体为啥是这个值我不知道
                    if (bytes < 989) {
                        // voice
                        if (source.contains("Recorder")) {
                            // 构造Recorder
                            int end = source.lastIndexOf("]");
                            int start = source.indexOf("[") + 1;
                            String[] sub = source.substring(start, end).split(
                                    ", ");
                            int tempInteger = sub[0].indexOf("=") + 1;
                            String content = sub[0].substring(tempInteger,
                                    sub[0].length());
                            float audioLength = Float.parseFloat(sub[1]
                                    .split("=")[1]);
                            String filePath = sub[2].split("=")[1];

                            Recorder recorder = new Recorder(content,
                                    audioLength, filePath,
                                    BluetoothChat.VOICE_READ);
                            mHandler.obtainMessage(BluetoothChat.VOICE_READ,
                                    bytes, -1, recorder).sendToTarget();
                        } else {
                            // message
                            mHandler.obtainMessage(BluetoothChat.MESSAGE_READ,
                                    bytes, -1, buffer).sendToTarget();
                        }
                        source = "";
                    }
                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                    connectionLost();
                    // Start the service over to restart listening mode
                    BluetoothChatService.this.start();
                    return;
                }
            }
        }

注意,上面的代码有bug。语音传输以后声音不对,因为没有对语音进行编码解码。只是用了二进制数据。string类型通过二进制编码解码还可以还原,语音不行 附上源码:http://download.csdn.net/detail/lxj1137800599/9514013

最后再加个Thread用于传输voice也不行

代码语言:javascript
复制
    private class TransformThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        private String filePath;

        public TransformThread(BluetoothSocket socket, String filePath) {
            mmSocket = socket;
            this.filePath = filePath;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "temp sockets not created", e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        @Override
        public void run() {
            try {
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                int len = -1;
                byte[] buff = new byte[1024];
                while ((len = mmInStream.read(buff)) != -1) {
                    outputStream.write(buff, 0, len);
                }
                File file = new File(Environment.getExternalStorageDirectory()
                        + filePath);
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(outputStream.toByteArray());
                fos.close();
                mmSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void write(byte[] buffer) {
            try {
                mmOutStream.write(buffer);
            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
        }
    }
}

后台查看是乱码,我猜的原因可能是 ConnectedThread和TransformThread都有如下代码

代码语言:javascript
复制
socket.getInputStream()

获得的是同一个stream对象所以传输的时候搞混了。但是又不能用FileInputStream,毕竟这是一个蓝牙应用。所有的努力宣告破产

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年05月09日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一:官方demo的注解
  • 第二:新增功能
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档