Android Studio 开发(四)–蓝牙通信

本次Github代码仓库 --crcr1013/BlueToothDemo

文章目录

    • Android Studio 开发(四)--蓝牙通信
  • 一、成果要求
  • 二、关键步骤
    • 1、工程结构
    • 2、清单文件注册权限
    • 3、准备设计资源
    • 4、设计布局
    • 5.编写蓝牙服务
    • 6.启动项目
  • 三、结果测试

一、成果要求

进行蓝牙通信的简要设计与开发。

二、关键步骤

1、工程结构

新建相应的活动组件、布局文件、准备好相应资源,确定整体架构。
(主活动组件MainActivity被重命名为BluetoothChat,它是蓝牙会话的主Activity组件程序。)

2、清单文件注册权限

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />

3、准备设计资源

在文件res/values/strings.xml里,添加程序运行过程中的状态描述文本及配色代码等,其代码如下:

<?xml version="1.0" encoding="utf-8"?>
<resources><string name="app_name">蓝牙Demo</string> <string name="send">发送</string><string name="not_connected">你没有链接一个设备</string><string name="bt_not_enabled_leaving">蓝牙不可用,离开聊天室</string><string name="title_connecting">链接中...</string><string name="title_connected_to">连接到:</string><string name="title_not_connected">无链接</string> <string name="scanning">蓝牙设备搜索中...</string><string name="select_device">选择一个好友链接</string><string name="none_paired">没有配对好友</string><string name="none_found">附近没有发现好友</string><string name="title_paired_devices">已配对好友</string><string name="title_other_devices">其它可连接好友</string><string name="button_scan">搜索好友</string><string name="connect">我的好友</string><string name="discoverable">设置在线</string><string name="back">退出</string><string name="startVideo">开始聊天</string><string name="stopVideo">结束聊天</string>
</resources>

4、设计布局

在默认的主布局文件activity_main.xml里,添加1个Toolbar控件,其内包含2个水平的TextView控件;在Toolbar控件的下方添加1个ListView控件,用于显示聊天内容;最后在ListView控件的下方添加水平放置的1个EditText控件和一个Button控件。使用垂直线性布局并嵌套水平线性布局实现的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/bg01"><!--新版Android支持的Toolbar,对标题栏布局--><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><TextViewandroid:id="@+id/title_left_text"style="?android:attr/windowTitleStyle"android:layout_width="0dp"android:layout_height="match_parent"android:layout_alignParentLeft="true"android:layout_weight="1"android:gravity="left"android:ellipsize="end"android:singleLine="true" /><TextViewandroid:id="@+id/title_right_text"android:layout_width="0dp"android:layout_height="match_parent"android:layout_alignParentRight="true"android:layout_weight="1"android:ellipsize="end"android:gravity="right"android:singleLine="true"android:textColor="#fff" /></LinearLayout></android.support.v7.widget.Toolbar><ListView android:id="@+id/in"android:layout_width="match_parent"android:layout_height="match_parent"android:stackFromBottom="true"android:transcriptMode="alwaysScroll"android:layout_weight="1" /><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content" ><EditText android:id="@+id/edit_text_out"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:layout_gravity="bottom" /><Button android:id="@+id/button_send"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/send"/></LinearLayout>
</LinearLayout>

5.编写蓝牙服务

1、编写用于蓝牙会话的服务组件ChatService,本质上是一个工具类,其文件代码如下:
(仅展示部分代码,完整代码可在github上查看)

/*本程序ChatService是蓝牙会话的服务程序定义了3个内部类:AcceptThread(接受新连接)、ConnectThread(发出连接)和ConnectedThread (已连接)
*/
public class ChatService {//本应用的主Activity组件名称private static final String NAME = "BluetoothChat";// UUID:通用唯一识别码,是一个128位长的数字,一般用十六进制表示//算法的核心思想是结合机器的网卡、当地时间、一个随机数来生成//在创建蓝牙连接private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");private final BluetoothAdapter mAdapter;private final Handler mHandler;private AcceptThread mAcceptThread;private ConnectThread mConnectThread;private ConnectedThread mConnectedThread;private int mState;public static final int STATE_NONE = 0;public static final int STATE_LISTEN = 1;public static final int STATE_CONNECTING = 2;public static final int STATE_CONNECTED = 3;//构造方法,接收UI主线程传递的对象public ChatService(Context context, Handler handler) {//构造方法完成蓝牙对象的创建mAdapter = BluetoothAdapter.getDefaultAdapter();mState = STATE_NONE;mHandler = handler;}private synchronized void setState(int state) {mState = state;mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();}public synchronized int getState() {return mState;}public synchronized void start() {if (mConnectThread != null) {mConnectThread.cancel();mConnectThread = null;}if (mConnectedThread != null) {mConnectedThread.cancel();mConnectedThread = null;}if (mAcceptThread == null) {mAcceptThread = new AcceptThread();mAcceptThread.start();}setState(STATE_LISTEN);}
...

2、设计供主Activity使用的菜单文件res/menu/optionmenu.xml、选择好友(即已经配对过的蓝牙设备)的界面布局文件devicelist.xml。
**菜单文件option_menu.xml的代码如下:


<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"><item android:id="@+id/scan"android:icon="@android:drawable/ic_menu_myplaces"android:title="@string/connect" /><item android:id="@+id/discoverable"android:icon="@android:drawable/ic_menu_view"android:title="@string/discoverable" /><item android:id="@+id/back"android:icon="@android:drawable/ic_menu_close_clear_cancel"android:title="@string/back" />
</menu>

**选择好友界面的布局文件device_list.xml的代码如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><TextView android:id="@+id/title_paired_devices"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/title_paired_devices"android:visibility="gone"android:background="#666"android:textColor="#fff"android:paddingLeft="5dp" /><ListView android:id="@+id/paired_devices"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1" /><TextView android:id="@+id/title_new_devices"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/title_other_devices"android:visibility="gone"android:background="#666"android:textColor="#fff"android:paddingLeft="5dp" /><!--android:visibility="gone"表示不占空间的隐藏,invisible是占空间--><ListView android:id="@+id/new_devices"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="2" /><Button android:id="@+id/button_scan"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/button_scan" />
</LinearLayout>

3、 编写Activity组件DeviceList,实现选取与之会话的蓝牙设备,其文件代码如下:

/*本程序供菜单项主界面的选项菜单“我的好友”调用,用于:(1)显示已配对的好友列表;(2)搜索可配对的好友进行配对(3)新选择并配对的蓝牙设备将刷新好友列表注意:发现新的蓝牙设备并请求配对时,需要对应接受关键技术:动态注册一个广播接收者,处理蓝牙设备扫描的结果*/
public class DeviceList extends AppCompatActivity {private BluetoothAdapter mBtAdapter;private ArrayAdapter<String> mPairedDevicesArrayAdapter;private ArrayAdapter<String> mNewDevicesArrayAdapter;public static String EXTRA_DEVICE_ADDRESS = "device_address";  //Mac地址//定义广播接收者,用于处理扫描蓝牙设备后的结果private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (BluetoothDevice.ACTION_FOUND.equals(action)) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (device.getBondState() != BluetoothDevice.BOND_BONDED) {mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());}} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {if (mNewDevicesArrayAdapter.getCount() == 0) {String noDevices = getResources().getText(R.string.none_found).toString();mNewDevicesArrayAdapter.add(noDevices);}}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.device_list);//在被调用活动里,设置返回结果码setResult(Activity.RESULT_CANCELED);init();  //活动界面}......

4、编写蓝牙会话的主Activity组件程序BluetoothChat:
(不同的SDK API对权限的赋予要求不同,可增加动态赋予权限以及检查权限是否被赋予的函数,具体见github完整代码)

public class BluetoothChat extends AppCompatActivity {public static final int MESSAGE_STATE_CHANGE = 1;public static final int MESSAGE_READ = 2;public static final int MESSAGE_WRITE = 3;public static final int MESSAGE_DEVICE_NAME = 4;public static final int MESSAGE_TOAST = 5;public static final String DEVICE_NAME = "device_name";public static final String TOAST = "toast";private static final int REQUEST_CONNECT_DEVICE = 1;  //请求连接设备private static final int REQUEST_ENABLE_BT = 2;private TextView mTitle;private ListView mConversationView;private EditText mOutEditText;private Button mSendButton;private String mConnectedDeviceName = null;private ArrayAdapter<String> mConversationArrayAdapter;private StringBuffer mOutStringBuffer;private BluetoothAdapter mBluetoothAdapter = null;private ChatService mChatService = null;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getSupportActionBar().hide();  //隐藏标题栏if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);}}Toolbar toolbar = findViewById(R.id.toolbar);//创建选项菜单toolbar.inflateMenu(R.menu.option_menu);//选项菜单监听toolbar.setOnMenuItemClickListener(new MyMenuItemClickListener());mTitle = findViewById(R.id.title_left_text);mTitle.setText(R.string.app_name);mTitle = findViewById(R.id.title_right_text);// 得到本地蓝牙适配器checkBlePermission();checkBleDevice();mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter == null) {Toast.makeText(this, "蓝牙不可用", Toast.LENGTH_LONG).show();finish();return;}if (!mBluetoothAdapter.isEnabled()) { //若当前设备蓝牙功能未开启Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(enableIntent, REQUEST_ENABLE_BT); //} else {if (mChatService == null) {setupChat();  //创建会话}}}

6.启动项目

三、结果测试

生成apk包,安装到两个真机上进行测试。
1、生成release安装包

2、打开两个真机的蓝牙,进行配对

3、将该程序安装到两个真机上
在两个真机上均点击设置在线,允许蓝牙权限打开。

3、互相发送消息,并确认收到

蓝牙通讯成功! # 四、总结 1、在本次project中,几篇开发文档都给了我莫大的帮助,从中整合出蓝牙通信开发的基本套路,一步步完成了本次项目;另外,如何设计验证环节是检验一个项目是否成功的重要手段。 蓝牙通信的基础开发仅实现发送消息即可,不过如今蓝牙有发送图片、文件等更高级的应用,还等待我在AS开发中探索并实现。依然感谢帮助我的每一篇博客和每一个网站! 2、apk打包参考博客

Android Studio 打包APK(详细版)

## Android Studio 开发(四)--蓝牙通信相关推荐

  1. Android Studio开发之蓝牙通信

    安卓开发-蓝牙通信 功能需求:在微信程序的第一子项中完成"蓝牙聊天功能" 开发步骤: 配置文件注册 设计界面布局 编写用于蓝牙会话的服务组件ChatService 分别建立供主Ac ...

  2. Android Studio开发(六)短距离无线通信——蓝牙通信

    Android Studio开发(六)短距离无线通信--蓝牙通信 Android Studio开发(六)蓝牙通信 一.任务需求 二.短距离无线通信技术(Short-Distance Wirleless ...

  3. Android Studio开发——蓝牙聊天功能

    Android Studio开发--蓝牙聊天功能 蓝牙工作流程 功能要求 实现要点 声明蓝牙权限 添加程序运行的状态描述文本及配色代码 布局文件 蓝牙会话的服务组件ChatService Activi ...

  4. Android Studio开发(四)SQLite数据库的DAO标准CRUD操作模拟微信通讯录

    Android Studio开发(四)SQLite数据库的DAO标准CRUD操作模拟微信通讯录 Android Studio开发(四)SQLite数据库的DAO标准CRUD操作模拟微信通讯录 一.任务 ...

  5. Android Studio开发蓝牙应用(二)

    Android Studio开发蓝牙应用(二) 实现的功能 与蓝牙模块HC-06交换信息 过程 新建Empty Activity 创建布局 activity_btread_and_write.xml ...

  6. Android Studio开发蓝牙应用(一)

    Android Studio开发蓝牙应用(一) 环境 window 11 安卓12 HC-06蓝牙模块 创建空project 选择Empty Activity,后点击Next 可修改项目名,自定义,后 ...

  7. 《Android Studio开发实战 从零基础到App上线》源码运行问题解答

    本书提供了所有章节的完整源码下载,自上市以来陆续收到读者的意见反馈,现将与源码有关的问题汇总归类如下,方便更多的朋友解决源码运行过程中发现的问题: 一.打开本书源码时,出现"Plugin w ...

  8. 《Android Studio开发实战 从零基础到App上线》第一版的资源下载和内容勘误

    资源下载 下面是<Android Studio开发实战 从零基础到App上线>(第一版)一书用到的工具和代码资源: 1.本书使用的Android Studio版本为2.2.3,因为Andr ...

  9. 基于TCP/IP协议的物联网安卓应用开发基础教程(Android Studio开发)

    [华为云IOT物联网论坛外部版主:中华小能能] 第0章 简介 大家好,在上上上期发布的教程中,教大家如何利用Android Studio开发出一款接入华为云物联网平台并调用相关API完成设备属性查询. ...

  10. Android Studio 开发--近场通信技术

    Android Studio 开发–近场通信技术 文章目录 Android Studio 开发--近场通信技术 一.三种近场通信技术的特点 1.BlueTooth蓝牙技术 1.1概念 1.2主要特点 ...

最新文章

  1. 梅尔频率倒谱系数(MFCC)资源
  2. pycharm:格式化python代码
  3. 真实实验测试多少节电池可以点亮白炽灯泡!
  4. Linux下怎么改分辨率和刷新率?
  5. 基于MySQL的高可用可扩展架构探讨
  6. 天龙八部网单服务器技能修改,天龙八部3门派技能修改介绍
  7. 每个程序员都该学习的5种开发语言,不可错过!
  8. 三段式状态机_Verilog实战篇(5)——FIFO amp; 状态机
  9. [comsol]求协调初始值失败,奇异矩阵。
  10. openSUSE 安装 Torch
  11. 详解Autosar Arxml中的CANFD报文及格式
  12. win10显示rpc服务器不可用,win10系统RpC服务器不可用的详细办法
  13. jQuery类似QQ空间时间轴效果_事件展示时光轴js特效代码
  14. case when 多条件查询
  15. 为什么有那么多编码员音乐家?
  16. office常用的快捷键
  17. 01 【nodejs简介】
  18. stm32 开发软件分享
  19. 在ubuntu下使用Vim学习C++
  20. cs1.5服务器指定ip,CS1.5 IP 服务器

热门文章

  1. android自动连接wifi,Android自动连接WiFi优先级规则,以及查看已连接WiFi的密码
  2. PE安装Win10纯净版教程【附Win10企业版/专业版/64/32位系统下载地址以及系统激活工具和解压软件安装包】
  3. npm 同时安装同一个包的不同版本(npm@6.9 alias)
  4. SQL语句 操作实例
  5. win10兼容模式怎么设置_win10开始菜单没反应怎么办?是因为没有设置这个
  6. 《电脑十万个为什么》 第四卷 第一章
  7. Linux导出Excel图片水印中文乱码解决
  8. 【算法入坑】(一)双指针yyds,学完双指针刷题贼爽嘞
  9. 基于Proteus基本元器件的认识
  10. 【金三银四】Java基础知识面试题(2021最新版)