Android Studio制作手机App:通过手机蓝牙(Bluetooth)与STM32上的低功耗蓝牙(HC-42)连接通信,实现手机端对单片机的控制。

news/2024/11/23 1:43:43/

背景:

本文的内容是针对单片机蓝牙模块(HC-42)开发的手机App。在这之前,我想先声明一点,手机与手机间的蓝牙连接方式”与“手机与HC间的蓝牙连接方式”是不一样的。原因就是手机搭配的是“经典蓝牙”模块,HC等蓝牙属于“低功耗蓝牙”模块。(二者的区别想了解的话建议你去看看其他朋友的文章),我在这里只想简单说一下这二者在功能代码实现上可以说是完全不一样的。这就解释了有一些朋友制作的软件明明可以与手机,平板等设备配对连接,却一直与HC蓝牙配对失败。

前言:

本文的内容只讲如何实现手机与HC蓝牙的配对,如果想了解一下手机与手机,手机与平板间的“经典蓝牙”通信方式,可以看我往期的博文,这篇博文讲的是如何制作一个基于蓝牙通信的聊天软件(类似于微信功能),也是一个挺有意思的项目(Android Studio制作蓝牙聊天通讯软件)

本文内容简介:

制作一个手机APP,无线连接HC蓝牙模块,将手机端数据发送给HC,从而控制STM32,文末会有资源分享。

简单通讯原理图:

如何制作这样一个App?

首先看一下本次的效果图:

 一、软件UI界面部分的设计实现

可以看 软件UI界面设计的实现 这篇博文,先实现界面设计后,再完成接下来的功能代码实现。

二、功能代码的实现。

1、在AndroidManifest.xml中添加依赖:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"

 2、新建文件BlueToothController .java,完整代码及其解析如下:

package BluetoothPackage;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.content.Context;
import android.content.Intent;
import java.util.ArrayList;
import java.util.List;
/*** Created by WYB on 2023/4/28.*/
public class BluetoothController {private BluetoothAdapter mAdapter;//本手机的蓝牙适配器private BluetoothLeScanner mLeScanner;//本手机蓝牙适配器上的扫描硬件private Activity mActivity;public static final int REQUEST_CODE_ENABLE_BLUETOOTH = 0;public BluetoothController(Activity activity){mAdapter = BluetoothAdapter.getDefaultAdapter();//获取本机蓝牙适配器mLeScanner = mAdapter.getBluetoothLeScanner();//获取本机蓝牙扫描器mActivity = activity;}public BluetoothAdapter getAdapter() {return mAdapter;}public BluetoothLeScanner getmLeScanner(){return mLeScanner;}/*打开蓝牙设备*/public void  turnOnBlueTooth(){Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);mActivity.startActivityForResult(intent,REQUEST_CODE_ENABLE_BLUETOOTH);}/*关闭蓝牙设备*/public void  turnOffBlueTooth(){mAdapter.disable();}/*** 打开蓝牙可见性,让别的设备发现我*/public void enableVisibily(Context context){Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);context.startActivity(intent);}/*查找未绑定的蓝牙设备*/public void findDevice(){assert (mAdapter!=null);mAdapter.startDiscovery();}/*查看已绑定的蓝牙设备*/public List<BluetoothDevice> getBondedDeviceList(){return new ArrayList<>(mAdapter.getBondedDevices());}/*开启扫描*/public void scanBlueTooth(ScanCallback scanCallback){mLeScanner.startScan(scanCallback);}/*关闭扫描*/public void stopBlueTooth(ScanCallback scanCallback){mLeScanner.stopScan(scanCallback);}/*连接设备*/public BluetoothGatt connectBlueTooth(BluetoothDevice bluetoothDevice, boolean autoConnect, BluetoothGattCallback gattCallback){return bluetoothDevice.connectGatt(this.mActivity,autoConnect,gattCallback);}
}

3、MainActivity .java,完整代码及其解析如下:

package com.example.wyb.bluetoothchatui;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import BluetoothPackage.BluetoothController;
import MyClass.DeviceAdapter;
import MyClass.DeviceClass;
public class MainActivity extends AppCompatActivity {private DeviceAdapter mAdapter1,mAdapter2;private List<DeviceClass> mbondDeviceList = new ArrayList<>();//搜索到的所有已绑定设备保存为列表(仅保留名称与地址)private List<DeviceClass> mfindDeviceList = new ArrayList<>();//搜索到的所有未绑定设备保存为列表(仅保留名称与地址)private List<BluetoothDevice> bondDevices = new ArrayList<>();//搜索到的所有的已绑定设备private List<BluetoothDevice> findDevices = new ArrayList<>();//搜索到的所有的未绑定设备private BluetoothController mbluetoothController;private Toast mToast;private mScanCallBack myScanCallBack;private static final int PERMISSION_REQUEST_COARSE_LOCATION=1;private Button findBtn;private Handler mHandler = new Handler();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mbluetoothController = new BluetoothController(this);Init_listView();//初始化设备列表findBtn = (Button) findViewById(R.id.button1);Init_Bluetooth();//开启蓝牙相关权限}//扫描蓝牙功能的实现private class mScanCallBack extends ScanCallback{@Overridepublic void onScanResult(int callbackType, ScanResult result){super.onScanResult(callbackType,result);if(!findDevices.contains(result.getDevice())){mfindDeviceList.add(new DeviceClass(result.getDevice().getName(),result.getDevice().getAddress()));findDevices.add(result.getDevice());mAdapter2.notifyDataSetChanged();}}@Overridepublic void onBatchScanResults(List<ScanResult> results){super.onBatchScanResults(results);}@Overridepublic void onScanFailed(int errorCode){super.onScanFailed(errorCode);}}//初始化蓝牙权限private void Init_Bluetooth(){myScanCallBack = new mScanCallBack();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);}}mbluetoothController.turnOnBlueTooth();}//初始化列表,适配器的加载public void Init_listView(){mAdapter1 = new DeviceAdapter(MainActivity.this, R.layout.device_item, mbondDeviceList);ListView listView1 = (ListView)findViewById(R.id.listview1);listView1.setAdapter(mAdapter1);mAdapter1.notifyDataSetChanged();mAdapter2 = new DeviceAdapter(MainActivity.this, R.layout.device_item, mfindDeviceList);ListView listView2 = (ListView)findViewById(R.id.listview2);listView2.setAdapter(mAdapter2);mAdapter2.notifyDataSetChanged();listView2.setOnItemClickListener(toBondDevices);//点击设备,进行绑定}//点击开始查找蓝牙设备public View findDevice(View view){//先执行其他代码,8s后执行run()里面的代码mHandler.postDelayed(new Runnable() {@Overridepublic void run() {change_Button_Text("搜索设备","ENABLE");mbluetoothController.stopBlueTooth(myScanCallBack);}}, 8000);change_Button_Text("搜索中...","DISABLE");mbluetoothController.scanBlueTooth(myScanCallBack);Log.e("提示","---------->findDevice");return view;}//点击按键搜索后按键的变化private void change_Button_Text(String text,String state){if("ENABLE".equals(state)){findBtn.setEnabled(true);findBtn.getBackground().setAlpha(255); //0~255 之间任意调整findBtn.setTextColor(ContextCompat.getColor(this, R.color.black));}else {findBtn.setEnabled(false);findBtn.getBackground().setAlpha(150); //0~255 之间任意调整findBtn.setTextColor(ContextCompat.getColor(this, R.color.colorAccent));}findBtn.setText(text);}//点击设备后执行的函数,跳转到第二个操作界面,并将选中的蓝牙设备信息传递过去private AdapterView.OnItemClickListener toBondDevices =new AdapterView.OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int i, long l){mbluetoothController.stopBlueTooth(myScanCallBack);BluetoothDevice device = findDevices.get(i);Intent intent = new Intent(MainActivity.this,Main2Activity.class);intent.putExtra("device",device);startActivity(intent);}};//设置toast的标准格式private void showToast(String text){if(mToast == null){mToast = Toast.makeText(this, text,Toast.LENGTH_SHORT);mToast.show();}else {mToast.setText(text);mToast.show();}}
}

4、MainActivity2 .java,完整代码及其解析如下:

package com.example.wyb.bluetoothchatui;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import BluetoothPackage.BluetoothController;
public class Main2Activity extends AppCompatActivity {private BluetoothDevice Device;private TextView textView;private EditText editText;private mGattCallback myGattCallBack;private BluetoothGatt mybluetoothGatt;private BluetoothController mbluetoothController;private String SERVICE_EIGENVALUE_SED = "0000ffe1-0000-1000-8000-00805f9b34fb";private android.os.Handler mytimeHandler = new android.os.Handler();private BluetoothGattCharacteristic mneedGattCharacteristic;private TextView deviceState;private TextView appname;@Overrideprotected void onDestroy() {//返回第一个界面时取消蓝牙配对mybluetoothGatt.disconnect();super.onDestroy();}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);Intent intent = getIntent();Device = intent.getParcelableExtra("device");textView = (TextView) findViewById(R.id.textView1);editText = (EditText) findViewById(R.id.input_text);deviceState = (TextView) findViewById(R.id.device_state);appname = (TextView) findViewById(R.id.AppName);appname.setText("");deviceState.setText("Device:"+Device.getName()+"(未连接)");mbluetoothController = new BluetoothController(this);myGattCallBack = new mGattCallback();mybluetoothGatt = mbluetoothController.connectBlueTooth(Device,false,myGattCallBack);}//蓝牙绑定功能的实现private class mGattCallback extends BluetoothGattCallback {@Overridepublic void onConnectionStateChange(BluetoothGatt gatt,int status,int newState){Log.e("提示","蓝牙连接成功");super.onConnectionStateChange(gatt,status,newState);mytimeHandler.postDelayed(new Runnable(){@Overridepublic void run(){mybluetoothGatt.discoverServices();deviceState.setText("Device:"+Device.getName()+"(已连接)");}},1000);}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt,int status){List<BluetoothGattService> services = mybluetoothGatt.getServices();for(int i=0;i<services.size();i++){Log.e("提示","第"+i+"个"+services.get(i));List<BluetoothGattCharacteristic> characteristics = services.get(i).getCharacteristics();for (int j=0;j<characteristics.size();j++){Log.e("提示","第"+i+"个服务,第"+j+"个特征值"+characteristics.get(j));if(characteristics.get(j).getUuid().toString().equals(SERVICE_EIGENVALUE_SED)){Log.e("提示","我找到我需要的特征了");mneedGattCharacteristic = characteristics.get(j);mybluetoothGatt.setCharacteristicNotification(mneedGattCharacteristic,true);}}}super.onServicesDiscovered(gatt,status);Log.e("提示","onServicesDiscovered");}@Overridepublic void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,int status){super.onCharacteristicRead(gatt,characteristic,status);Log.e("提示","onCharacteristicRead");}@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic){super.onCharacteristicChanged(gatt,characteristic);Log.e("提示","onCharacteristicChanged");}}//发送信息的实现public void sendData(BluetoothGatt bluetoothGatt,BluetoothGattCharacteristic bluetoothGattCharacteristic,String text){bluetoothGattCharacteristic.setValue(text);bluetoothGatt.writeCharacteristic(bluetoothGattCharacteristic);}//处理要发送的信息,并更新界面内容public View sendMessage(View view){sendData(mybluetoothGatt,mneedGattCharacteristic,editText.getText().toString());textView.setText(textView.getText().toString()+editText.getText().toString());editText.getText().clear();return view;}
}

三、本项目的最终分享

链接:https://pan.baidu.com/s/1rX6GbTvHRU3Mb18tgwEjHg  提取码:td1d

四、后文

那么到此你就已经完成了本项目的制作,此软件制作其实没有想象中的那么难,至于STM32上的程序编写教程可以看往期博文: Bluetooth(HC)与STM32的连接通讯(在手机端通过蓝牙控制STM32板子小灯)


http://www.ppmy.cn/news/481889.html

相关文章

pc机的usb接口的打印机设置

1、进控制面板&#xff0c;添加打印机 2、选“手动添加。。。”&#xff0c;端口选择“USB虚拟打印机端口“。 点“下一步” 3、打印测试页。

安装打印机时LPT,COM、USB端口区别

LPT(并口):LPT是用于使用打印机或其它设备的。LPT并口是一种增强了的双向并行传输接口&#xff0c;在USB接口出现以前是扫描仪&#xff0c;打印机最常用的接口。(目前使用滴少) COM&#xff08;串口&#xff09;:COM端口通常用于连接鼠标及通讯设备&#xff08;如连接外置式MOD…

计算机端口里没有usb,解决打印机端口设置中没有USB选项的方法

《解决打印机端口设置中没有USB选项的方法》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《解决打印机端口设置中没有USB选项的方法(3页珍藏版)》请在人人文库网上搜索。 1、解决打印机端口设置中没有USB选项的方法今天用USB连接线连接了打印机&#xff0c;装上驱动过…

windows虚拟机安装打印机的方式

设备 主机系统&#xff1a;win10&#xff0c; 虚拟机软件&#xff1a;VMware &#xff0c; 虚拟机系统&#xff1a;win7 步骤&#xff1a; 一.主机打印机共享 1.打开“控制面板”->“设备和打印机”&#xff0c;选择你需要的打印机“右键”->“打印机属性”->“共…

计算机控制器如何调用打印机,怎样设置打印机的虚拟usb端口

选择USB端口&#xff0c;下载好打印机驱动&#xff0c;里面有安装程序全部自动安装&#xff0c;你只要按提示打开打印机、连接数据线即可。 一&#xff1a;检查打印机是否开机 如果打印机处于关机状态&#xff0c;连接USB设备会出现无法识别的现象&#xff0c;需要开机状态下连…

计算机端口里没有usb,电脑联接USB打印机 没有USB虚拟端口

不用说选择USB端口&#xff0c;下载好打印机驱动&#xff0c;里面有安装程序全部自动安装&#xff0c;你只要按提示打开打印机、连接数据线即可。 一&#xff1a;检查打印机是否开机 如果打印机处于关机状态&#xff0c;连接USB设备会出现无法识别的现象&#xff0c;需要开机状…

重置Windows打印机COM端口USB端口

Windows频繁连接打印机后&#xff0c;会有很多无法删除&#xff0c;无法使用的COM USB端口&#xff1b;选错端口会导致打印机连接失败&#xff0c;下面介绍如何重置这些端口 Win R 运行regedit 清理COM 定位到注册表位置&#xff1a; HKEY_LOCAL_MACHINE\SYSTEM\CurrentCont…

Dos命令打印文件以及Dos打印到USB打印端口

MS-DOS命令范例 要将当前目录中的 Report.txt 发送到连上本地计算机的 LPT2&#xff0c;请键入&#xff1a; print /d:LPT2 report.txt 要将 c:\Accounting 目录中的 Report.txt 文件发送到服务器 \\CopyRoom 上的 Printer1 打印队列&#xff0c;请键入&#xff1a; prin…