Android 蓝牙 一对一聊天APP 心得

学习了,三天的Android 蓝牙开发,开始是一头雾水,看着别人讲的Google官方的demo感觉很容易,所有自己也尝试写一个很简单的聊天demo.可是想的很简单,自己做起来也花了,将近一天的时间才搞定这个基本的流程设计.下面是几点心得后面再贴代码
1>写一个简单的demo也好,记得一定需要有总体的流程,才开始抠代码
2>既然是demo毕竟就是新的知识,代码中间的log点一定\不能少,这是你快速调试的利器
3>还是thinking in java 里面的那句话,思考什么是可变的,什么是不可变的,然后分开,这样来实现代码的封装,感觉很不错了.只是现在感觉还是很难想明白
4>开始思考以面向对象的流程处理问题,需要怎么弄,也是封装代码的一种思想

蓝牙聊天的基本功能:
1.实现一对一蓝牙连接
2.实现一对一聊天

很简单的功能,思路看着也很清晰,可是深入去写,才知道,水还是深度的,java不熟的话.
此处基本的如何打开蓝牙不在复述,请自行百度.
思路:
1>初始化,打开手机的蓝牙,开始蓝牙服务器线程,等待连接
2>配对,获取某台手机的蓝牙address地址.
3>开启连接线程连接手机蓝牙
4>连接成功后,开启,蓝牙聊天的线程,进行聊天的通讯.

上面四步是主要思路,其中存在着几个细节的地方,就是在开发中某些逻辑问题,线程间的安全问题,也是需要好好处理的. 让我感受比较深的地方是,一对一聊天,相当于,首相每台机器都可能作为服务器在进行通讯,所以一开始开启了两个服务监听,一旦有一个接入进来,这里需要弄清楚哪个是接入对象,哪个是被接入对象, 没有作为服务端的,可以把服务端线程关闭掉.
下面贴点代码

    /**
     * 客户端启动连接线程
     * 通过蓝牙的mac地址获取连接
     * @author Administrator
     *
     */
    private class ConnectThread extends Thread {

        private BluetoothDevice mDevice;
        private BluetoothSocket btSocket = null;

        public ConnectThread(String address) {
            // TODO Auto-generated constructor stub
            mDevice = mBluetoothAdapter.getRemoteDevice(address);
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            connect(mDevice);
        }

        private void connect(BluetoothDevice btDev) {

            Method creMethod;
            try {
                creMethod = BluetoothDevice.class.getMethod("createBond");
                creMethod.invoke(btDev);

            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                btSocket = btDev.createRfcommSocketToServiceRecord(MYUUID);
                System.out.println("========" + "start connect");
                Log.d("BlueToothTestActivity", "开始连接...");
                btSocket.connect();
                mClientSocket = btSocket;
                isConnected=true;
                mHandler.sendEmptyMessage(SUCCESS_SERVICE_BEGIN_TALKING);

                // 作为客户端 关闭 服务端 等待的链接
                if (acceptThread != null) {
                    acceptThread.close();
                }
                startTalk();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                System.out.println("???????????????? close socket");
                close();
                System.out.println(e.toString());
                e.printStackTrace();
            }

        }

        private void close() {
            if (btSocket != null) {
                try {
                    btSocket.close();
                    mHandler.sendEmptyMessage(FAILED_SERVICE_SOCRCKET);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        }

    }

    /**
     * 服务端的设计
     * 每个蓝牙的客户端先要开启服务端等待接入
     * @author Administrator
     *
     */
    private class AcceptThread extends Thread {
        private final BluetoothServerSocket mmServerSocket;

        public AcceptThread() {
            // Use a temporary object that is later assigned to mmServerSocket,
            // because mmServerSocket is final
            BluetoothServerSocket tmp = null;
            try {
                // MY_UUID is the app's UUID string, also used by the client
                // code
                tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("Fisrt", MYUUID);
            } catch (IOException e) {
                mHandler.sendEmptyMessage(FAILED_SERVICE_SOCRCKET);

            }
            mmServerSocket = tmp;
        }

        public void run() {
            BluetoothSocket socket = null;
            // Keep listening until exception occurs or a socket is returned
            while (isRun) {
                try {
                    socket = mmServerSocket.accept();
                    mHandler.sendEmptyMessage(SUCCESS_SERVICE_SOCRCKET);

                    Log.e("TAG", "========== server start ====");

                } catch (IOException e) {
                    mHandler.sendEmptyMessage(FAILED_SERVICE_SOCRCKET);
                    close();
                }



                // If a connection was accepted
                if (socket != null) {
                    // 服务端连接成功,启动聊天线程,通过 同一个 socket  防止多线程赋值出现空值的问题
                    isConnected=true;
                    mClientSocket = socket;
                    mTalkThread = new TalkThread();
                    mTalkThread.start();

                    // Do work to manage the connection (in a separate thread)
                    // 多线程操作小心不安全性
                    synchronized (BlueConnectService.this) {
                        //close();
                    }
                }

            }
        }

        public void close() {
            isRun = false;
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }
/*
    *设计连接成功后的聊天线程 1.建立流,打通连接 2.发送和接收数据 3.显示数据
     *  需要注意的是聊天的时候,需要同一个socket建立连接才能获取对应的输入输出流
     */

    private class TalkThread extends Thread {

        private final BluetoothSocket talkSocket;
        private final InputStream mIs;
        private final OutputStream mOs;
        private boolean isRunning = true;

        public TalkThread() {
            // TODO Auto-generated constructor stub
            talkSocket = mClientSocket;
            if (talkSocket == null) {
                System.out.println("================= talkThread erro ");
                // return;
            }

            InputStream is = null;
            OutputStream os = null;
            try {
                is = talkSocket.getInputStream();
                os = talkSocket.getOutputStream();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                try {
                    System.out.println("???????????????? close socket");
                    talkSocket.close();
                    CloseUtil.closeStream(is, os);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }

            mIs = is;
            mOs = os;

        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();
            byte[] buffer = new byte[1024];
            int len;
            while (isRunning) {
                try {
                    len = mIs.read(buffer);
                    mHandler.obtainMessage(READ_MESSAGE, len, -1, buffer).sendToTarget();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    try {
                        isRunning = false;
                        isConnected=false;
                        System.out.println("???????????????? close socket");
                        talkSocket.close();
                        // 需要重启服务器
                        // 启动服务器

                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                    CloseUtil.closeStream(mIs, mOs);

                }
            }

        }

        public void write(byte[] bytes) {
            try {
                mOs.write(bytes);
                mHandler.obtainMessage(WRITE_MESSAGE, bytes.length, -1, bytes).sendToTarget();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值