Android 蓝牙开发

蓝牙开发 首先需要申请权限

    <!--经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,如果需要扫描设备或者操作蓝牙设置,则还需要BLUETOOTH_ADMIN权限-->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
此外 AndroidM之后,如果需要搜索附近蓝牙设备 还需要添加两个动态权限( 需要在代码中动态申请

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

接收 需要获取蓝牙系统管理

在使用蓝牙功能之前,我们需要判断设备是否支持蓝牙,如支持,则再判断 是否开启了蓝牙

bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
    /**
     * 判断是否支持蓝牙,并打开蓝牙
     * 获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。
     * 如果没打开,需要让用户打开蓝牙:
     */
    public void checkBleDevice(Context context) {
        if (getmBluetoothAdapter() != null) {
            if (!getmBluetoothAdapter().isEnabled()) {
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(enableBtIntent);
            }
        } else {
            Log.i("blueTooth", "该手机不支持蓝牙");
        }
    }

开启蓝牙后,需要扫描搜索附近蓝牙设备

//开始搜索
        getmBluetoothAdapter().startDiscovery();
当搜索到设备,会接收到相应的广播,当然  我们需要注册该广播
    /**
     * 注册蓝牙回调广播
     */
    private void blueToothRegister() {
        BltManager.getInstance().registerBltReceiver(this, new BltManager.OnRegisterBltReceiver() {

            /**搜索到新设备
             * @param device
             */
            @Override
            public void onBluetoothDevice(BluetoothDevice device) {
                if (bltList != null && !bltList.contains(device)) {
                    bltList.add(device);
                }
                if (myAdapter != null)
                    myAdapter.notifyDataSetChanged();
            }

            /**连接中
             * @param device
             */
            @Override
            public void onBltIng(BluetoothDevice device) {
                btl_bar.setVisibility(View.VISIBLE);
                blt_status_text.setText("连接" + device.getName() + "中……");
            }

            /**连接完成
             * @param device
             */
            @Override
            public void onBltEnd(BluetoothDevice device) {
                btl_bar.setVisibility(View.GONE);
                blt_status_text.setText("连接" + device.getName() + "完成");
            }

            /**取消链接
             * @param device
             */
            @Override
            public void onBltNone(BluetoothDevice device) {
                btl_bar.setVisibility(View.GONE);
                blt_status_text.setText("取消了连接" + device.getName());
            }
        });
    }

接下来就是建立蓝牙通信

这里需要用到 BluetoothServerSocket 

    /**
     * 从蓝牙适配器中创建一个蓝牙服务作为服务端,在获得蓝牙适配器后创建服务器端
     */
    private void createBltService() {
        try {
            if (BltManager.getInstance().getmBluetoothAdapter() != null && BltManager.getInstance().getmBluetoothAdapter().isEnabled()) {
                bluetoothServerSocket = BltManager.getInstance().getmBluetoothAdapter().listenUsingRfcommWithServiceRecord("com.bluetooth.demo", BltContant.SPP_UUID);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

创建好Socket之后,我们需要在服务端等待链接

    /**
     * 这个操作应该放在子线程中,因为存在线程阻塞的问题
     */
    public void run(Handler handler) {
        //服务器端的bltsocket需要传入uuid和一个独立存在的字符串,以便验证,通常使用包名的形式
        while (true) {
            try {
                //注意,当accept()返回BluetoothSocket时,socket已经连接了,因此不应该调用connect方法。
                //这里会线程阻塞,直到有蓝牙设备链接进来才会往下走
                socket = getBluetoothServerSocket().accept();
                if (socket != null) {
                    BltAppliaction.bluetoothSocket = socket;
                    //回调结果通知
                    Message message = new Message();
                    message.what = 3;
                    message.obj = socket.getRemoteDevice();
                    handler.sendMessage(message);
                    //如果你的蓝牙设备只是一对一的连接,则执行以下代码
                    getBluetoothServerSocket().close();
                    //如果你的蓝牙设备是一对多的,则应该调用break;跳出循环
                    break;
                }
            } catch (IOException e) {
                try {
                    getBluetoothServerSocket().close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
//                break;
            }
        }
    }

客户端则需要申请链接

    /**
     * 尝试连接一个设备,子线程中完成,因为会线程阻塞
     *
     * @param btDev 蓝牙设备对象
     * @param handler 结果回调事件
     * @return
     */
    private void connect(final BluetoothDevice btDev, final Handler handler) {
        try {
            //通过和服务器协商的uuid来进行连接
            mBluetoothSocket = btDev.createRfcommSocketToServiceRecord(BltContant.SPP_UUID);
            if (mBluetoothSocket != null)
                //全局只有一个bluetooth,所以我们可以将这个socket对象保存在appliaction中
                BltAppliaction.bluetoothSocket = mBluetoothSocket;
            //通过反射得到bltSocket对象,与uuid进行连接得到的结果一样,但这里不提倡用反射的方法
            //mBluetoothSocket = (BluetoothSocket) btDev.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(btDev, 1);
            Log.d("blueTooth", "开始连接...");
            //在建立之前调用
            if (getmBluetoothAdapter().isDiscovering())
                //停止搜索
                getmBluetoothAdapter().cancelDiscovery();
            //如果当前socket处于非连接状态则调用连接
            if (!getmBluetoothSocket().isConnected()) {
                //你应当确保在调用connect()时设备没有执行搜索设备的操作。
                // 如果搜索设备也在同时进行,那么将会显著地降低连接速率,并很大程度上会连接失败。

                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        if (getmBluetoothSocket() != null)
                            try {
                                getmBluetoothSocket().connect();

                                if (handler == null) return;
                                //结果回调
                                Message message = new Message();
                                message.what = 4;
                                message.obj = btDev;
                                handler.sendMessage(message);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                    }
                }).start();
            }
            Log.d("blueTooth", "已经链接");
        } catch (Exception e) {
            Log.e("blueTooth", "...链接失败");
            try {
                getmBluetoothSocket().close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
    }



当服务器链接成功  我们就可以基于Socket 进行数据相互传输了

传输文字:

    /**
     * 发送文本消息
     *
     * @param message
     */
    public static void sendMessage(String message) {
        if (BltAppliaction.bluetoothSocket == null || TextUtils.isEmpty(message)) return;
        try {
            message += "\n";
            OutputStream outputStream = BltAppliaction.bluetoothSocket.getOutputStream();
            outputStream.write(message.getBytes("utf-8"));
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
传输文件:

    /**
     * 发送文件
     */
    public static void sendMessageByFile(String filePath) {
        if (BltAppliaction.bluetoothSocket == null || TextUtils.isEmpty(filePath)) return;
        try {
            OutputStream outputStream = BltAppliaction.bluetoothSocket.getOutputStream();
            //要传输的文件路径
            File file = new File(filePath);
            //说明不存在该文件
            if (!file.exists()) return;
            //说明该文件是一个文件夹
            if (file.isDirectory()) return;
            //1、发送文件信息实体类
            outputStream.write("file".getBytes("utf-8"));
            //将文件写入流
            FileInputStream fis = new FileInputStream(file);
            //每次上传1M的内容
            byte[] b = new byte[1024];
            int length;
            int fileSize = 0;//实时监测上传进度
            while ((length = fis.read(b)) != -1) {
                fileSize += length;
                Log.i("socketChat", "文件上传进度:" + (fileSize / file.length() * 100) + "%");
                //2、把文件写入socket输出流
                outputStream.write(b, 0, length);
            }
            //关闭文件流
            fis.close();
            //该方法无效
            //outputStream.write("\n".getBytes());
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

接收消息

    public static void receiveMessage(Handler handler) {
        if (BltAppliaction.bluetoothSocket == null || handler == null) return;
        try {
            InputStream inputStream = BltAppliaction.bluetoothSocket.getInputStream();
            // 从客户端获取信息
            BufferedReader bff = new BufferedReader(new InputStreamReader(inputStream));
            String json;

            while (true) {
                while ((json = bff.readLine()) != null) {
                    Message message = new Message();
                    message.obj = json;
                    message.what = 1;
                    handler.sendMessage(message);
                    //说明接下来会接收到一个文件流
                    if ("file".equals(json)) {
                        FileOutputStream fos = new FileOutputStream(Environment.getExternalStorageDirectory() + "/test.gif");
                        int length;
                        int fileSzie = 0;
                        byte[] b = new byte[1024];
                        // 2、把socket输入流写到文件输出流中去
                        while ((length = inputStream.read(b)) != -1) {
                            fos.write(b, 0, length);
                            fileSzie += length;
                            System.out.println("当前大小:" + fileSzie);
                            //这里通过先前传递过来的文件大小作为参照,因为该文件流不能自主停止,所以通过判断文件大小来跳出循环
                        }
                        fos.close();
                        message.obj = "文件:保存成功";
                        message.what = 2;
                        handler.sendMessage(message);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值