ESP32S蓝牙05

继续ESP32S的经典蓝牙学习。今天我们准备重做蓝牙手机客户端APP,不过今天不是用APPInventor积木式编程,而是使用Eclipse的代码编程,继续向着蓝牙通讯的底层探究。

Eclipse是我最近才升级的,Android API24的版本(差不多是Android7.1的系统)。

程序主要还是按照前面的客户端APP界面要求来写的,先上源代码吧:

这个是程序代码,在MainActivity.java

package com.example.bluetooth;

import android.support.v7.app.ActionBarActivity;

import android.util.Log;

import android.os.AsyncTask;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import java.io.BufferedReader;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.ArrayList;

import java.util.List;

import java.util.Set;

import java.util.UUID;

import android.bluetooth.BluetoothAdapter;

import android.bluetooth.BluetoothDevice;

import android.bluetooth.BluetoothGatt;

import android.bluetooth.BluetoothGattCallback;

import android.bluetooth.BluetoothGattCharacteristic;

import android.bluetooth.BluetoothGattDescriptor;

import android.bluetooth.BluetoothGattService;

import android.bluetooth.BluetoothSocket;

import android.content.Intent;

import android.graphics.Bitmap;

import android.view.View;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.Button;

import android.widget.EditText;

import android.widget.ListAdapter;

import android.widget.ListView;

import android.widget.TextView;

import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

private Button onoff, send;

private TextView msgstr;

private EditText sendstr;

private Set<BluetoothDevice> pairedDevices;

private ArrayList list;

private ArrayAdapter adapter;

private ListView lv;

private Intent intent;

private BluetoothAdapter BA;

private ConnectThread mConnectThread;

private ConnectedThread mConnectedThread;

private int mState = 0;

public static final int SUCCESS = 0;

private Handler handler = new Handler() {

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

switch (msg.what) {

case SUCCESS:

msgstr.setText((String) msg.obj);

break;

default:

break;

}

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

onoff = (Button)findViewById(R.id.button1);

send = (Button)findViewById(R.id.button2);

msgstr = (TextView)findViewById(R.id.textView1);

sendstr = (EditText)findViewById(R.id.edittext1);

lv = (ListView)findViewById(R.id.listView1);

//获取蓝牙适配器

mState = 0;

BA = BluetoothAdapter.getDefaultAdapter();

if (BA.isEnabled()) {  //如果蓝牙已经开启

mState = 1;

//设置本机蓝牙为可搜索状态

intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);

startActivityForResult(intent, 0);

//直接查找设备列表,并把设备名称显示在列表中

pairedDevices = BA.getBondedDevices();

list = new ArrayList();

for(BluetoothDevice bt : pairedDevices)

list.add(bt.getAddress() + " " +bt.getName());

adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1, list);

lv.setAdapter(adapter);

onoff.setText("关闭蓝牙");

}else {

onoff.setText("打开蓝牙");

}

onoff.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

if (!BA.isEnabled()) {

msgstr.setText("请稍候");

intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(intent, 0);

try {

Thread.sleep(12000);

} catch (InterruptedException e) {

}

intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);

startActivityForResult(intent, 0);

pairedDevices = BA.getBondedDevices();

list = new ArrayList();

for(BluetoothDevice bt : pairedDevices)

list.add(bt.getAddress() + " " +bt.getName());

adapter = new ArrayAdapter(MainActivity.this,android.R.layout.simple_list_item_1, list);

lv.setAdapter(adapter);

onoff.setText("关闭蓝牙");

msgstr.setText("蓝牙开启");

mState = 1;

}else {

if (mState == 5) {

//往蓝牙服务器端发送关闭服务指令

String str = "close";

mConnectedThread.write(str.getBytes());

try {

Thread.sleep(300);

} catch (InterruptedException e) {

}

mConnectThread.cancel();

mConnectThread = null;

mConnectedThread.cancel();

mConnectedThread = null;

}

BA.disable();

list.clear(); //清空list

adapter = new ArrayAdapter(MainActivity.this,android.R.layout.simple_list_item_1, list);

lv.setAdapter(adapter);

onoff.setText("打开蓝牙");

msgstr.setText("蓝牙关闭");

mState = 1;

//Toast.makeText(getApplicationContext(),"Turned off" ,

//Toast.LENGTH_LONG).show();

}

}

});

send.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

String str = sendstr.getText().toString();

if(mState == 5)

mConnectedThread.write(str.getBytes());

}

});

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

BluetoothDevice mDevice;

@Override

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

//当用户选中列表中的某一个蓝牙设备时

if(mState == 1) {

msgstr.setText(list.get(position).toString());

int i = 0;

for(BluetoothDevice bt : pairedDevices) {

if(i == position) { mDevice = BA.getRemoteDevice(bt.getAddress()); break;} else i += 1;

}

//开启连接蓝牙线程

mState = 2;

mConnectThread = new ConnectThread(mDevice);

mConnectThread.start();

}

}

});

}

//连接蓝牙的线程

private class ConnectThread extends Thread {

private final String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB";

private BluetoothSocket socket;

private BluetoothDevice device;

//构造函数中启动连接到服务器

public ConnectThread(BluetoothDevice device)  {

this.device = device;

BluetoothSocket tmp = null;

try {

tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));

} catch (IOException e) {

e.printStackTrace();

}

this.socket = tmp;

}

//进入线程等待

public void run() {

BA.cancelDiscovery();

Message msg = new Message();

try {

//当成功连接到服务器的时候

socket.connect();

mState = 3;

msg.what = SUCCESS;

msg.obj = "连接成功01";

handler.sendMessage(msg);

//创建一个侦听输入、发送输出的服务线程

mConnectedThread = new ConnectedThread(socket);

mConnectedThread.start();

//从这里结束连接线程

} catch (IOException e) {

try {

socket.close();

} catch (IOException ee) {

ee.printStackTrace();

}

msg.what = SUCCESS;

msg.obj = "连接失败01";

handler.sendMessage(msg);

return;

}

}

public void cancel() {

try {

socket.close();

} catch (IOException e) {

}

}

}

// 双方蓝牙连接成功后一直运行的输入输出服务线程

private class ConnectedThread extends Thread {

private BluetoothSocket socket;

private InputStream inputStream;

private OutputStream outputStream;

//构造函数中定义了输入输出的流

public ConnectedThread(BluetoothSocket socket) {

this.socket = socket;

InputStream input = null;

OutputStream output = null;

try {

input = socket.getInputStream();

output = socket.getOutputStream();

mState = 5;

} catch (IOException e) {

e.printStackTrace();

}

this.inputStream = input;

this.outputStream = output;

}

public void run() {

byte[] buff = new byte[1024];

int bytes;

//这里设置一个循环,让线程的不停地侦听输入

while (true) {

try {

bytes = inputStream.read(buff);

if(bytes > 0) {

String str = new String(buff, "ISO-8859-1");

str = str.substring(0, bytes);

Message msg = new Message();

msg.what = SUCCESS;

msg.obj = str;

handler.sendMessage(msg);

}

} catch (IOException e) {

e.printStackTrace();

break;

}

}

}

//这个是输出到服务器的操作

public void write(byte[] bytes) {

try {

outputStream.write(bytes);

outputStream.flush();

} catch (IOException e) {

e.printStackTrace();

}

}

public void cancel() {

try {

inputStream.close();

outputStream.close();

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

//下面这个是作为服务器端的侦听线程

//private class AcceptThread extend Thread{

//    private final BluetoothServerSocket mServerSocket;

//    public AcceptThread(){

//        mServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME,MY_UUID);

//    }

//

//    public void run(){

//        BluetoothSocket socket = null;

//        while(true){

//            socket = mServerSocket.accept();

//            if(socket!=null){

//                // 自定义方法

//                manageConnectedSocket(socket);

//                mServerSocket.close();

//               break;

//            }

//        }

//    }

//    public void cancle(){

//        mServerSocket.close();

//    }

//}

}

这个是界面文件,在activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context=".MainActivity" >

<ListView

android:id="@+id/listView1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:visibility="visible" />

<Button

android:id="@+id/button1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="断开蓝牙" />

<EditText

android:id="@+id/edittext1"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="hello server" />

<Button

android:id="@+id/button2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="发送" />

<TextView

android:id="@+id/textView1"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

</LinearLayout>

//这个是版本号和权限的申请。在androidManifest.xml

<uses-sdk

android:minSdkVersion="11"

android:targetSdkVersion="21" />

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

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

<!--6.0以上才要加的额外权限 -->

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

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

这个是确定模拟器的版本号,添加在project.properties文件的末尾

sdk.buildtools=24.0.0

到了代码编程的时候,没有点耐心是真的受不了了,都是一大片一大片的代码,都是精雕细琢的过程。

当然,在编译测试这个程序的时候,因为要用到蓝牙,所以必须连接真机(必须连接一部真正的手机到电脑,把程序传入手机中测试运行情况),还是出现了一点诡异的事情:我们在点击编译程序是,总是提示启动模拟器失败,但是模拟器是可以正常启动的,但是还是在编译启动模拟器时出现了错误。(后来我是这样理解的,可能是当我们手机连接电脑时,因为电脑中360手机助手的原因,导致连接手机出现了问题。而当我们在Eclipse中启动编译时,Eclipse发现电脑时有连接真机的,所以就尝试连接真机,但有连接不同,所以出现了模拟器启动失败的警告)。  解决的办法是,先在拔下手机连接,再清除电脑中360手机助手的进程,让电脑接触所有连接手机的痕迹。接着启动Eclipse的编译,这时候,Eclipse发现电脑中没有连接真机,所以自然就选择启动软件模拟器进行编译。等软件模拟器打开了,程序编译成功了,这时候关掉软件模拟器,在换连接真机(把手机插入电脑,打开电脑360手机助手连接好手机),这时候重新编辑编译,Eclipse就会和真正的手机相连,并把程序发送到手机中测试运行的情况了。

经过测试,这个蓝牙客户端程序已经能正常和其他的蓝牙服务器设备通讯的,及时做前面的三方会话的通讯连接测试,也能通过了。

ESP32S蓝牙05相关推荐

  1. ESP32S蓝牙03

    ESP32S蓝牙03 继续ESP32S的经典蓝牙学习.经典的蓝牙告诉我们,蓝牙只能在两个设备握手连接中传递讯息,可是我们却偏偏想让多个蓝牙设备互相通讯,这次我准备了两部手机,一块ESP32S开发板,准 ...

  2. ESP32S蓝牙02

    ESP32S蓝牙02 继续ESP32S的经典蓝牙学习 经典蓝牙的工作模式 在上一篇中,我们认识了一个非常简单的经典蓝牙程序.所谓的经典蓝牙,指的是传统的蓝牙工作模式.蓝牙设备的工作模式有这样的特点: ...

  3. 基于HUAWEI AppGallery Connect开发了一款App,我得出了这几点结论!

    点击"开发者技术前线",选择"星标????" 在看|星标|留言,  真爱 来自:开发者技术前线 作者:GC 1 背景介绍 最近,笔者开发了一款App,深刻体会到 ...

  4. spotify音乐下载_如何从Spotify下载音乐

    spotify音乐下载 Bring your music with you. Spotify Premium users can listen to the streaming service's e ...

  5. ESP32的BLE使用学习

    UUID生成网站: Online UUID Generator Tool 0.前言 什么是低功耗蓝牙? BLE之所以被称为低功耗蓝牙,就是需要通讯的时候才握手,数据传输完成后,就断开连接.在通讯过程中 ...

  6. 连接 蓝牙HC - 05 模块 读写操作

    连接 蓝牙HC - 05 模块 进行读写操作 1. 开启蓝牙进行连接 //藍牙private BluetoothAdapter bluetoothAdapter;private Set<Blue ...

  7. ESP32 入门笔记05: BLE 蓝牙客户端和服务器 (ESP32 for Arduino IDE)

    目录 1. BLE 服务器和客户端 2. GATT 协议 3. UUID 4. 项目概述 4.1 材料清单 4.2 ESP32 BLE 服务器 4.3 ESP32 BLE 客户端 参考资料 1. BL ...

  8. 【微信小程序控制硬件16 】 安信可 ESP32-S 开发板实现移植腾讯物联开发平台蓝牙 llsync 协议,实现一键蓝牙快速配网+远程控制。(附带源码)

    文章目录 一.前言 二.源码目录说明 三.编译指导 四.常见问题 五.开源微信物联网控制一览表 另外,不要把我的博客作为学习标准,我的只是笔记,难有疏忽之处,如果有,请指出来,也欢迎留言哈! 微信物联 ...

  9. 05、HC-05蓝牙通讯模块

    文章目录 1.HC-05蓝牙通讯模块实物图 2.HC-05蓝牙通讯模块引脚介绍 3.HC-05蓝牙通讯模块电气特性参数 4.HC-05蓝牙通讯模块原理图 5.HC-05蓝牙通讯模块介绍 6.模块自带S ...

最新文章

  1. base64开源库介绍及使用
  2. 最新!这所顶尖大学录取线全国第三!毕业生深造率超九成!
  3. 解决django关于图片无法显示的问题
  4. android从放弃到精通 第四天 happy
  5. PyQt5 技术篇-如何彻底删除控件?布局移除控件方法。
  6. maven中packaging的三个属性值pom、jar、war
  7. 传统的线性降维方法效果不佳。_高压断路器机械故障诊断与定位的新思路:KPCA-SoftMax诊断方法...
  8. 大漠插件 win10 绑定
  9. [转] Apache日志分析常用Shell命令
  10. php mvc多态实例,asp.net mvc-多态模型绑定
  11. dataframe 控对象_iOS知识 - 常用小技巧大杂烩
  12. mysql pdo prepare_PDO::prepare
  13. mysql改了排序规则不生效_Mysql数据库表排序规则不一致导致联表查询,索引不起作用问题...
  14. ECharts 入门真的很简单
  15. mysql longtext db2_从 MySQL 或 PostgreSQL 迁移到 DB2 Express-C
  16. CodeForces888E Maximum Subsequence(折半枚举+two-pointers)
  17. 6.MongoDB之索引
  18. selenium RC优化代码3
  19. 【应用】Android平台最佳健身
  20. 201621123062《java程序设计》第11周作业总结

热门文章

  1. linux开启dhcpclient服务,dhcp client 配置
  2. office:word在编辑内容时反应迟钝的解决办法
  3. android-ProGuard混淆
  4. 【k8s】 k8s | 一 | 介绍
  5. 桌面文档另存计算机怎么存,如何把word保存到桌面
  6. 项目管理中的团队建设
  7. 爆火的Web3.0背后,百度营销如何抓住流量密码?
  8. nginx的全局配置和HTTP相关配置
  9. 计算机网络知识点整理---应用层(六)
  10. 递归查询Sdcarad文件中的音乐,图片类同