找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3962|回复: 4
打印 上一主题 下一主题
收起左侧

基于安卓经典蓝牙开发-串口 附源码

  [复制链接]
跳转到指定楼层
楼主
  • 展现广播的三种方式
  • 通知; 2、对话框; 3、消息提示框
  • 在使用Android蓝牙适配器中的startDiscovery需要先打开定位服务
  • 在连接蓝牙之前,还要先取消蓝牙设备的扫描,否则容易连接失败
前段时间自己学做了一个基于安卓经典蓝牙的app,也遇到不少坑,在网上相对与BLE低功耗蓝牙来说,它的资料方面都是比较缺少的,而且网上经典蓝牙源码大部分都很长,对于入门的同学来说,看没两分钟就产生放弃的念头了。
第一步:在AndroidManifest中添加:
<!--管理蓝牙需要-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!--搜索蓝牙需要,因为蓝牙可以被用来定位,所以需要定位权限-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
上面都是我们使用到设备功能的权限申请。
第二步:设置两个按钮分别是打开和关闭蓝牙
对蓝牙设备干事情,那么我们就得拿到它的接口来控制它
//获取蓝牙适配器
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
打开蓝牙:
1、
public void OpenBlueTooth(View view) {
    if(isSupportBlueTooth() == true) {
        if(!BlueToothState()) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent,0);
            showToast("亲,打开了噢!需要什么帮助吗?");
        }
        else {
            showToast("亲,已经打开了噢,无需重复打开。");
        }
    }
    else {
        showToast("亲,您不支持此蓝牙设备!");
    }
}
2、打开蓝牙应该先确定使用的手机是否支持蓝牙设备(手机没有就没必要进行下一步了)
//判断是否支持蓝牙
public boolean isSupportBlueTooth() {
    if(mBluetoothAdapter != null) {
        return true;
    }
    else {
        return false;
    }
}
3、然后打开前还需要知道手机是否打开蓝牙了吧!那就获取手机现在蓝牙设备的状态
//获取蓝牙状态
public  boolean BlueToothState() {
    assert (mBluetoothAdapter != null);   //若不支持该蓝牙设备会有个断言
    return mBluetoothAdapter.isEnabled();  
}
2、3小步骤都只是个函数功能体,都是为1、步骤使用的,初学者会疑惑什么是断言,就是做判断,真的那么下面就不执行咯!还有下面是是一个消息对象,
获取用户对蓝牙适配器申请打开的请求消息,使用startActivityForResult对消息做出应答,会有对话框的提示效果
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent,0);
关闭蓝牙:
public void CloseBlueTooth(View view) {
    mBluetoothAdapter.disable();
    showToast("亲,我们会再见面的!");
}
先说明一点我这里的还是都在有View view形参接口,这是一个动作的监听接口,下图有设置的图片,这里设置就可以了。

感觉打开蓝牙和关闭蓝牙挺简单的吧!
难度开始来了噢!

第三步:
打开了蓝牙我们就得弄一个来搜索周围的设备吧!
下面是一个定义好的搜索蓝牙函数
public void startDiscovery() {
    if (mBluetoothAdapter.isDiscovering()) {mBluetoothAdapter.cancelDiscovery();  Toast.makeText(this,"搜索器打开",Toast.LENGTH_SHORT).show();}
    mBluetoothAdapter.startDiscovery();
    if (!mBluetoothAdapter.isDiscovering()) {Toast.makeText(this,"搜索器没打开",Toast.LENGTH_SHORT).show();}
}
有点看不懂吗,其实还好吧,就是第一次判断是否开启搜索周围蓝牙设备,开启了就把它关了,重新打开在搜索,在判断我是否开启了搜索没。(isDiscovery是开启搜索,cancelDiscovery是关闭搜索的意思)
有搜索蓝牙设备函数了,我们就搞一个按键让其有触发效果吧!
//按钮搜寻蓝牙
Button button_discovery = (Button) findViewById(R.id.DiscoveryBT);
button_discovery.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        startDiscovery();
    }
});
开启了搜索蓝牙设备我们得有东西接收这些设备吧,不然它偷偷摸摸搜索鬼知道它搜了什么东西。那我们就得用广播把这些偷偷摸摸搜索到了设备把它弄出来,放进“箱子”里。
这就是我们定义的广播接收器
public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
            Toast.makeText(context, "开始", Toast.LENGTH_SHORT).show();
        } else if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            //////////////////////////////////////////////创建搜索蓝牙列表的///////////////////////////////////////////////////////////////////
            for (int i = 0; i < deviceAdress.size(); i++) {
                if (deviceAdress.get(i).getAddress().equals(device.getAddress())) return;
                //上面if语句就是去除已经获取的蓝牙设备
            }
            // 不是重复的就添加到列表中(获取未配对的蓝牙设备)
            deviceAdress.add(device);  //添加地址到列表中   用于鉴别是否已经添加列表和点击事件用的
            deviceName.add("地址:"+device.getAddress()+"\n"+"名称:"+device.getName());  //存放蓝牙名称和地址用于显示到列表上的

        } else if(intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
        }
    }
}
代码都有注释我就不一一说明了,说一下箱子要在外面定义
public ArrayList<BluetoothDevice> deviceAdress = new ArrayList<>();  //存放蓝牙设备(这里Adress我忘了改过来了,这是存放设备不是设备地址)
public ArrayList<String> deviceName = new ArrayList<>();  //存放蓝牙名称和地址
然后就是用广播类里面用if那些进行信息筛选(用蓝牙设备这个方法获取设备的信息BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE
然后就是把搜索到的device
你可以用Toast.make()打印一下信息看看效果
记得广播接收器的使用一定要注册广播接收器,不然就废掉了
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//发现蓝牙
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索停止
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED );//搜索启动
//上面是添加动作事件
//注册广播接收者的对象
registerReceiver(myReceiver,intentFilter);
都放在箱子里了,我们应该把它拿出来一个一个展示一下吧!
这展示的方法就是用列表把它展示出来:
public ListView listView;   //定义展示列表

//////////////////////////////////////////////创建搜索蓝牙列表的///////////////////////////////////////////////////////////////////并把
arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1,deviceName);  //实例化ArrayAdapter对象deviceName集合数据放入arrayAdapter适配器集合内
listView = (ListView) findViewById(R.id.list);  //获取列表框的
listView.setAdapter(arrayAdapter);  //将arrayAdapter集合内的数据加载到列表框 就是适配器对象与ListView关联
这样放进列表你以为就可以了吗,你怎么知道它加载了多少个已发现的设备呢?这需要我们到广播接收器这个线程中间断刷新载入新设备
arrayAdapter.notifyDataSetChanged();  //更新列表
下面是我定义的一个刷新列表搜索
        Button button= (Button) findViewById(R.id.Broadcast);  //获取布局文件中的广播按钮
        button.setOnClickListener(new View.OnClickListener() { //为按钮设置单击事件
            @Override
            public void onClick(View v) {
                //////////蓝牙刷新///////////////
                deviceAdress.clear();         //
                deviceName.clear();           //
                startDiscovery();             //
                ////////////////////////////////
            }
        });
到现在你就可以试试你做的可不可以将搜索到的蓝牙加载到列表中显示了,可以的化,看看可不可以刷新列表。

第四步:
把我们列表中的设备能进行点击触发
    //连接蓝牙
    public void Connect_BT(ArrayList<BluetoothDevice> deviceAdress) {
        //MainActivity 实现OnItemClickListener 然后重写方法
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                BluetoothDevice clickDevice = (BluetoothDevice)deviceAdress.get(position);
                String s1 = String.valueOf(position);  //编号
                Toast.makeText(MainActivity.this, s1 + "--" + clickDevice.getName() + "--" + clickDevice.getAddress(),Toast.LENGTH_SHORT).show();
                //在连接前需要先关闭搜索
            }
        });
    }
把我们列表按键触发这个类放到广播接收器这个线程中
Connect_BT(deviceAdress);
按下列表就有这个提示框咯!开心吧

第五步:
连接我们选中的蓝牙
连接这些蓝牙都需要协议的,都是厂家底层工作人员定好的
//手机连接的UUID
//设备连接的UUID由厂商决定。
private final String BLUETOOTH_UUID = "00001101-0000-1000-8000-00805F9B34FB";   //蓝牙通信的UUID,必须为这个,如果换成其他的UUID会无法通信
private BluetoothSocket bluetoothSocket = null;
UUID我就步详细说了,你们自行百度。BluetoothSocket套接字就是连接蓝牙服务器用的。
在Connect_BT添加下面代码即可()
                //在连接前需要先关闭搜索
                //点击列表,去请求服务器
                if (clickDevice != null) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                bluetoothSocket = clickDevice.createRfcommSocketToServiceRecord(UUID.fromString(BLUETOOTH_UUID));
                                bluetoothSocket.connect();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }).start();
                }
这我要说明一下connect方法会阻塞线程,我们需要在下面创建一个子线程来运行,不然程序奔溃别找我就可以了。
到这我们就所有基本弄好了

第五步:
接收和发送数据
这里我略微讲一下
// 用来收数据
InputStream inputStream = bluetoothSocket.getInputStream();
// 用来发数据
OutputStream outputStream;
下面是我用按键发送数据的代码(参考)
Button button_oc3 = (Button) findViewById(R.id.button_open_close3);
button_oc3.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String text = "d12";
        try {
            outputStream = bluetoothSocket.getOutputStream();
            outputStream.write(text.getBytes());
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
});
记住完成BluetoothSocket的一系列操作后,记住用close()方法关闭套接字噢,不然手机很耗电,烧坏别找我麻烦。
接收数据的话会比较麻烦一点点,需要用一个线程和while死循环继续时刻接收(因为InputStream 也会阻塞线程的)

到这就告一段落了。
我有一个老师是这样说过的游戏打累了就休息一下,休息的方法就是敲代码。

在社会学到的要学会分享回报社会

(有什么好的想法和建议可以分享一下给我)
广州大学华软软件学院djw

全部资料51hei下载地址(源码):
mybluetooth_finish.zip (412.24 KB, 下载次数: 61)
经典蓝牙开发过程.docx (148.04 KB, 下载次数: 53)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏7 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:882411 发表于 2021-2-3 22:07 来自手机 | 只看该作者
楼主,这个是用eclipse编写的嘛
回复

使用道具 举报

板凳
ID:413056 发表于 2021-3-22 20:37 | 只看该作者
思庆 发表于 2021-2-3 22:07
楼主,这个是用eclipse编写的嘛

android studio
回复

使用道具 举报

地板
ID:368534 发表于 2021-4-7 17:45 | 只看该作者
感谢楼主的无私奉献,文件可以打开,可以生成APK,内容也很通俗易解。有参考价值。
回复

使用道具 举报

5#
ID:298011 发表于 2023-12-27 11:28 | 只看该作者
写得很详细,学习下。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表