为新手准备的安卓连接经典蓝牙模块教程

绪论:

        本人业余爱好者一个,无android基础,在开发android蓝牙的时候遇到了很多问题,其中最难受的还是基础不够好而看不懂别人在写什么。所以针对新手,我想写一个新手也完完全全能看懂的教程(连android studio都没用过的人除外)。

        在完成文章之后我发现有点长,希望读者能耐心看完。如果有大神看到发现不好的地方欢迎指出,但请别喷,毕竟我只是个新手+业余的。

 

需要了解的蓝牙概念:

        首先,我们需要搞清楚经典蓝牙低功耗蓝牙两个的区别,这两者在android代码上的编写是不一样的。本文针对经典蓝牙。

        其次,手机蓝牙<----->手机蓝牙,手机蓝牙<----->蓝牙模块    两种连接方式也是不同的,前者需要两个手机同时安装开发的APP,APP里面的代码指定了唯一的UUID用于通信,而后者只能在手机APP里面通过反射的方式获取外设蓝牙的UUID,然后连接通信。

 

开发流程:

第一步:设置蓝牙权限

    <!-- 蓝牙权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <!-- Android 5.0以上蓝牙还需要位置权限 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

以上代码放在AndroidManifest.xml的<application上面 

 

第二步:打开蓝牙

首先定义一个全局变量:

        private BluetoothAdapter mBluetoothAdapter;

以上放在onCreate上面。

 

其次打开蓝牙:

        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

        mBluetoothAdapter = bluetoothManager.getAdapter();

        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {

        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

        startActivityForResult(enableBtIntent, 1);

        }

以上代码放在onCreate里面

 

第三步:搜索蓝牙设备

先等待蓝牙完全打开再开始搜索

        while(!mBluetoothAdapter.isEnabled());

        mBluetoothAdapter.startDiscovery();

以上代码放在打开蓝牙的代码之后

 

经典蓝牙的设备获取是通过广播获取的,所以我们要先定义一个广播:

        private class BluetoothReceiver extends BroadcastReceiver

        {

             @Override

             public void onReceive(Context context, Intent intent) {

                    String action = intent.getAction();

                    if (BluetoothDevice.ACTION_FOUND.equals(action)) {

                           BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                                                               bluetoothDeviceArrayList.add(device);

                           Device_Name.add(device.getName()+" "+device.getAddress());

                    }

                    //ShowDevice(); //此函数只是在ListView中显示搜索到的蓝牙设备,读者可以自己写到到想要显示的地方

            }

      }

以上代码放在OnCreate下面即可

 

广播代码中的blueDeviceArrayList与Device_Name是分别用来存放外部蓝牙设备对象与外部蓝牙设备名和地址的,所以需要定义全局变量

        ArrayList<BluetoothDevice>bluetoothDeviceArrayList=new ArrayList<>();

        ArrayList<String>Device_Name=new ArrayList<>();

以上代码放在OnCreate上面即可

 

定义了广播之后要创建广播的对象

        BluetoothReceiver receiver;

以上代码放在OnCreate上面即可

 

创建广播变量后要绑定

        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);

        receiver = new BluetoothReceiver();

        registerReceiver(receiver, filter);

以上代码放在OnCreate里面即可

 

在APP关闭之后要解除绑定,这个函数应该是应用关闭之后自动调用,不需要管

        @Override

        protected void onDestroy()

        {

                unregisterReceiver(receiver);

                super.onDestroy();

        }

以上代码放在onCreate下面即可  

 

第四步:连接蓝牙

先定义一个全局变量

        BluetoothSocket btSocket;

以上代码放在onCreate上面

 

然后是连接蓝牙的代码

        mBluetoothAdapter.cancelDiscovery();

        BluetoothDevice device = bluetoothDeviceArrayList.get(position);

        try {

                Method clientMethod = device.getClass() .getMethod("createRfcommSocket", new Class[]{int.class});

                btSocket = (BluetoothSocket) clientMethod.invoke(device, 1);

                connect(btSocket);//连接设备

        } catch (Exception e) {e.printStackTrace();}

以上代码我放于ListView的OnItemClick监听器中,所以第二行的device我是通过监听器函数中自带的参数去列表中获取,读者需要自行修改此行,关于connect函数是自己写的一个函数,我在接下来贴出代码

 

        public void connect(final BluetoothSocket btSocket) {

                try {

                        if (btSocket.isConnected()) { return; }

                        btSocket.connect();//连接

                        if (btSocket.isConnected()) {

                                new Readtask().start();

                        } else { btSocket.close(); }

                } catch (Exception e) { e.printStackTrace(); }

        }

以上代码放在onCreate下面,关于new Readtask().start();是执行读取的线程,在接下来会讲到

完成上述步骤蓝牙应该是连接成功了,为了能够清楚知道是否连接成功,读者可以自行在connect函数中加点上面显示以清楚现在蓝牙状态

 

第五步:发送数据

发送数据要开启一个发送数据的线程

        public class WriteTask extends Thread{ //写数据线程

                private String srt; public WriteTask(String str){

                         this.srt=str;

                }

                @Override

                public void run(){

                        OutputStream outputStream=null;

                        byte[] st=srt.getBytes();

                        try{

                                outputStream=btSocket.getOutputStream();

                                outputStream.write(st);

                        }catch (Exception e){e.printStackTrace();}

                }

        }

以上代码放在onCreate下面

 

写好线程需要开始这个线程

        new WriteTask("aaaa").start();

以上我是放在按钮的点击事件里面,读者可以自行选择,“aaaa”只是我正在测试时用的数据,读者可以自行修改

 

第六步:接收数据

接收数据需要一个接收线程

        public class Readtask extends Thread{//读数据线程
                @Override

                public void run(){

                        byte[] buffer = new byte[1024];

                        int bytes; InputStream inputStream ; //建立输入流读取数据

                        while (true) {

                                try {

                                        inputStream = btSocket.getInputStream();

                                        if ((bytes = inputStream.read(buffer)) > 0) {

                                                 byte[] buf_data= new byte[bytes];

                                                 for (int i = 0; i < bytes; i++) {

                                                         buf_data[i] = buffer[i];

                                                 }

                                                 String s = new String(buf_data);

                                                 Message msg = handler.obtainMessage();

                                                 msg.what = 1;

                                                 msg.obj = s;

                                                 handler.sendMessage(msg);

                                        }

                               } catch (Exception e) { Log.e("TAG", e.toString());break;}

                       }

                      if (btSocket != null) {

                              try {

                                    btSocket.close();

                              } catch (Exception e) {Log.e("TAG", e.toString());}

                     }

             }

     }

此代码放在onCreate下面,关于新接触的handler我接下来会讲

 

设定好线程之后我们需要启动线程,关于线程的启动,在connect函数中已经写好

        new Readtask().start();

以上代码放在connect函数中,请往上翻看

 

关于handler,是一个对象

        Handler handler=new Handler() {

                @Override

                public void handleMessage(Message msg){

                        super.handleMessage(msg);

                        if(msg.what == 1){

                                String s=msg.obj.toString();

                               // txv.setText(s);

                        }

                }

         };

以上代码放在onCreate下面,s为接收到的字符串,读者可以自行操作它

Handler类的作用大概是一种机制,使自定义线程与主线程之间的通信,具体读者如果感兴趣可以自行百度。一开始我是在进程中直接对读取的字符串进行操作,但后来出现不明问题,我想可能是读取线程一直在循环而时序可能出现冲突,所以一定要用Handler这种方法。

 

以上描述可以实现经典蓝牙模块的通信,但我在使用的时候出现手机端接收到蓝牙模块数据丢失一字节的问题,由于要趁热打铁,所以我先写了这篇文章,如果后续有朋友遇到相同的问题又解决了,欢迎告知解决方法,谢谢!

关于上述丢数据的问题,我觉得可能是我发一串数据过去的时候手机分成多个数据段去接收了,而我显示只是显示最新接收的数据,导致看起来像丢包,所以最保险的方法是一个一个字节发送。

步骤: 1. 两个蓝牙模块必须一个作为主机,另一个作为从机才能建立连接(上电后,从机一直处于接受状态,等待被连接。而主机则主动发出信号,寻找目标从机,前提是该目标从机的mac地址事先被写入到主机的flash芯片中储存) 2. 蓝牙模块上电前一直按住key按键不放,上电后松开,此时LED灯处于慢闪状态(每秒闪1次),提示已经进入AT指令响应状态,可以进行接收AT指令控制 3. PC端打开安可信串口助手(带AT指令),打开相应的串口,发送AT+ROLE?\n查询该模块的主从角色,如果为0,则为从机,如果为1则为主机。本例中,此模块(图中左边的HC-05模块)设为主机,则发送AT+ROLE=1\n,设为主机,成功返回OK 4. 发送AT+ADDR?\n查询此模块的mac地址,本例中为98d3:33:80ebdf,记下来稍后为从机的地址绑定用。同样的方法将另一个模块(图中右边的HC-05模块)设置为从机(AT+ROLE=0\n),并且查询到mac地址为98d3:36:aac2 5. 向主机串口中发送AT+BIND=98d3,36,aac2\n绑定从机的mac地址,成功则返回OK。发送AT+CMODE=0\n将主机设为指定蓝牙地址连接模式(即只允许主机向绑定好mac地址的蓝牙从机设备发起连接) 6. 同样地,向从机串口发送AT+BIND=983d,33,80ebdf\n绑定主机的mac地址,成功则返回OK。发送AT+CMODE=0\n将从机也设为指定蓝牙地址连接模式(即只允许从机接受绑定好mac地址的蓝牙主机设备发起的连接) 7. 至此,主从机均设置完毕。主从两模块松开key键重新上电,LED都快闪(每秒闪2次),表明均处于等待配对状态,随后大约几秒钟后,LED闪烁频率发生变化(不确定),表明已经侦测到目标设备,正在建立连接。随后大约一秒钟,很快 LED变成慢双闪状态(每2秒闪一次,每次连闪2下),提示已经配对成功,可以通过蓝牙协议传输数据了 8. 此时,在串口助手中发送一串字符,如果另一个蓝牙模块的串口助手里收到了同样的字符,且回送的字符,对方亦能收到,则通信成功。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值