ESP32S蓝牙05

本文介绍如何使用Eclipse为Android编写蓝牙客户端APP,采用代码编程而非APPInventor积木式编程。内容涉及蓝牙连接、数据传输及异常处理,包括开启蓝牙、搜索设备、连接设备及发送数据的实现过程。在实际操作中,遇到模拟器启动失败的问题,解决方案是先断开手机连接,清除电脑连接记录,然后启动Eclipse编译,再连接手机进行测试。
摘要由CSDN通过智能技术生成

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就会和真正的手机相连,并把程序发送到手机中测试运行的情况了。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tongyue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值