精华内容
下载资源
问答
  • Android蓝牙串口开发指南
  • android 蓝牙串口客户端,通过与蓝牙串口配对(自动扫描设备),可以实现按数据帧发送和接收数据,考虑到android 蓝牙操作顺序,对各种bug都有处理。
  • Android 蓝牙串口调试程序开发〇、蓝牙串口开发的流程一、添加需要用到的权限二、检测和打开蓝牙设备1.检测蓝牙设备2.打开蓝牙设备三、搜索并连接蓝牙设备1.搜索蓝牙设备2.连接蓝牙设备四、发送并接受串口数据1.发送...
  • Android 蓝牙串口调试助手源码,在Android最新版本上验证过能用。 主要功能: 1.搜索连接设备; 2.按字节数接收对齐; 3.发送接收都支持ASCII与HEX切换; 4.定时发送; 5.暂停接收,清除窗口数据
  • Android蓝牙串口通信附源码:可用于蓝牙打印技术,附有多个实例
  • 基于android 蓝牙串口通信搜索,配对,收发数据。很好的android 蓝牙通信代码。
  • 问题一,连接不上蓝牙串口直接在android自带的蓝牙例子上尝试,发现根本连接不上蓝牙串口,后来对比别人的代码发现uuid不一样.因为以前用过UUID.randomUUID();所以想当然的认为所有uuid都是随机生成的.通过搜索发现,...

    最近做的项目用到了蓝牙串口通讯功能.毕竟是接触到底层的一些东西,让吾等局限于java编程思想的小菜遇到了一些意想不到的问题.

    问题一,连接不上蓝牙串口

    直接在android自带的蓝牙例子上尝试,发现根本连接不上蓝牙串口,后来对比别人的代码发现uuid不一样.因为以前用过UUID.randomUUID();所以想当然的认为所有uuid都是随机生成的.通过搜索发现,android连接蓝牙串口的话,必须要这个UUID

    UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    问题二,在读取从蓝牙串口返回的数据时,一直阻塞在inpustream.read(buffer);那里.

    起初是因为仿照网上的例子,直接发送指令的16进制字符串过去,返回不到数据.后来通过反编译可以使用的蓝牙串口助手apk发现,需要发送的不是16进制字符串的byte数组.而是将16进制字符串转换成的byte数组.

    String string = "01 00 05 07 00 00 00 00";

    string = string.replaceAll(" ", "");

    byte[] bytes = hexString2Bytes(string);//正确,要发送这个bytes

    byte[] bytes = string.getBytes();//错误,发送这个bytes获取不到数据.

    附上hexString2Bytes方法

    /**

    * Convert hex string to byte[] 把为字符串转化为字节数组

    *

    * @param hexString

    * the hex string

    * @return byte[]

    */

    public static byte[] hexStringToBytes(String hexString) {

    hexString = hexString.replaceAll(" ", "");

    if (hexString == null || hexString.equals("")) {

    return null;

    }

    hexString = hexString.toUpperCase(Locale.getDefault());

    int length = hexString.length() / 2;

    char[] hexChars = hexString.toCharArray();

    byte[] d = new byte[length];

    for (int i = 0; i < length; i++) {

    int pos = i * 2;

    d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

    }

    return d;

    }

    /**

    * Convert char to byte

    *

    * @param c

    * char

    * @return byte

    */

    private static byte charToByte(char c) {

    return (byte) "0123456789ABCDEF".indexOf(c);

    }

    得出结论.串口通讯时,如果获取到错误的信息,是不返回数据的.在socket连接时.如果没有获取到数据.inputstream.read(buffer);是会一直阻塞的.

    展开全文
  • android蓝牙串口连接

    2019-03-14 10:12:40
    在做android蓝牙串口连接的时候一般会使用 BluetoothSocket tmp = null; 1 2 3 4 5 6 7 // Get a BluetoothSocket for a connection with the // given BluetoothDevice try { ...

    在做android蓝牙串口连接的时候一般会使用
    BluetoothSocket tmp = null;

    1
    2
    3
    4
    5
    6
    7
            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
              tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
           } catch (IOException e) {
                Log.e(TAG, "create() failed", e);
          }
    

    然后是tmp。connect方法
    可是 BluetoothSocket 。connect方法本身就会报很多错误

    这是我自己修改的方法
    private class ConnectThread extends Thread {
            private  BluetoothSocket mmSocket;
            private  BluetoothDevice mmDevice;
            ImprovedBluetoothDevice improvedBluetoothDevice;
            public ConnectThread(BluetoothDevice device) {
                mmDevice = device;
                BluetoothSocket tmp = null;

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
            improvedBluetoothDevice = new ImprovedBluetoothDevice(device);
        }
    
    
        public void run() {
            Log.i(TAG, "BEGIN mConnectThread");
            setName("ConnectThread");
    
    
            // Always cancel discovery because it will slow down a connection
            mAdapter.cancelDiscovery();
    
    
    
    
            String connectionType = "?";
    

    //蓝牙设备有三十个端口号,是,从1到30,可以一个一个试,这个办法虽然笨,可是管用
    for(int port = 1; port < 31; port++) {
        Log.d(TAG, "Connecting with port: " + port);

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    try {
    connectionType = "Secure";
    Log.d(TAG, "Attempting createRfcommSocket");
    
         BluetoothSocket s = improvedBluetoothDevice.createRfcommSocket(port);
           s.connect();
    
           mmSocket = s;
    } catch (Exception ex) {
    Log.e(TAG, ex.toString());
    mmSocket = null;
    try {
    connectionType = "Insecure";
    Log.d(TAG, "Attempting createInsecureRfcommSocket");
    
         BluetoothSocket s = improvedBluetoothDevice.createInsecureRfcommSocket(port);
           s.connect();
    
           mmSocket = s;
    } catch (Exception ex2) {
    Log.e(TAG, ex2.toString());
    mmSocket = null;
    }
    }
    
    if (mmSocket != null) {
    Log.d(TAG, "Connection succeeded with " + connectionType + " connection on port " + port);
    break;
    }
    }
    

    //如果还没有获取到mmSocket ,就使用以下方法

    1
    2
    if (mmSocket == null) {   
    try {
    

    mmSocket = improvedBluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID);
    mmSocket.connect();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
        }

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
            // Reset the ConnectThread because we're done
            synchronized (BluetoothChatService.this) {
                mConnectThread = null;
            }
    
    
            // Start the connected thread
            connected(mmSocket, mmDevice);
        }
    
    
        public void cancel() {
            try {
            if(mmSocket!=null)
            {
            mmSocket.close();
            }
    
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }
    

    ImprovedBluetoothDevice 这个类
    /* Copyright (C) 2011, Kenneth Skovhede
    http://www.hexad.dk, opensource@hexad.dk

    * This library is free software; you can redistribute it and/or
    * modify it under the terms of the GNU Lesser General Public
    * License as published by the Free Software Foundation; either
    * version 2.1 of the License, or (at your option) any later version.

    * This library is distributed in the hope that it will be useful,
    * but WITHOUT ANY WARRANTY; without even the implied warranty of
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    * Lesser General Public License for more details.

    * You should have received a copy of the GNU Lesser General Public
    * License along with this library; if not, write to the Free Software
    * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    */
    package com.example.bluetoothconnection.util;

    import java.io.IOException;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.UUID;

    import com.example.bluetoothconnection.R;
    import com.example.bluetoothconnection.R.string;

    import android.app.AlertDialog;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothClass;
    import android.bluetooth.BluetoothDevice;
    import android.bluetooth.BluetoothSocket;
    import android.content.ActivityNotFoundException;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.os.Parcel;
    import android.os.ParcelUuid;
    import android.util.AndroidRuntimeException;
    import android.view.View;
    import android.view.Window;
    import android.view.WindowManager;

    //Class that mimics a regular android.bluetooth.BluetoothDevice,
    // but exposes some of the internal methods as regular methods

    public class ImprovedBluetoothDevice {
    public final BluetoothDevice mDevice;

    private static Method getMethod(Class<?> cls, String name, Class<?>[] args) {
    try {
    return cls.getMethod(name, args);
    } catch (Exception ex) {
    return null;
    }
    }

    private static Constructor<?> getConstructor(Class<?> cls, Class<?>[] args) {
    try {
    Constructor<?> c = cls.getDeclaredConstructor(args);
    if (!c.isAccessible())
    c.setAccessible(true);
    return c;
    } catch (Exception ex) {
    return null;
    }
    }

    public static void ActivateBluetooth(Context c, View v) {
    try {
    //Play nice and use the system dialog for this
    c.startActivity(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE));
    } catch (ActivityNotFoundException ax) {
    ManualAskBluetoothActivate(c, v);
    } catch (AndroidRuntimeException ax) {
    ManualAskBluetoothActivate(c, v);
    }
    }

    private static void ManualAskBluetoothActivate(Context c, View v) {
    //If it fails, do this directly
    AlertDialog.Builder builder = new AlertDialog.Builder(c);

    1
        builder.setCancelable(true);
    

    builder.setMessage(R.string.bluetooth_enable_question);
    builder.setTitle(R.string.bluetooth_enable_dialog_title);

    builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
    BluetoothAdapter.getDefaultAdapter().enable();
    }}
    );

    builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
    }}
    );

    //If we are running in the IME, we need to do something special
    if (v != null) {
    AlertDialog dlg = builder.create();

    Window window = dlg.getWindow(); 
           WindowManager.LayoutParams lp = window.getAttributes();
           lp.token = v.getWindowToken();
           lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
           window.setAttributes(lp);
           window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

    dlg.show();
    }
    else 
    builder.show();

    }

    public static void DeactivateBluetooth(Context c) {
    AlertDialog.Builder dlg = new AlertDialog.Builder(c);
    dlg.setCancelable(true);
    dlg.setMessage(R.string.bluetooth_disable_question);
    dlg.setTitle(R.string.bluetooth_disable_dialog_title);

    dlg.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
    BluetoothAdapter.getDefaultAdapter().disable();
    }}
    );

    dlg.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
    }}
    );

    dlg.show();
    }

    //private static final int TYPE_RFCOMM = 1;
    //private static final int TYPE_SCO = 2;
    private static final int TYPE_L2CAP = 3;

    private static final Method _createRfcommSocket = getMethod(BluetoothDevice.class, "createRfcommSocket", new Class[] { int.class });
    private static final Method _createInsecureRfcommSocket = getMethod(BluetoothDevice.class, "createInsecureRfcommSocket", new Class[] { int.class });
    private static final Method _setPin = getMethod(BluetoothDevice.class, "setPin", new Class[] { byte[].class });
    private static final Method _setPasskey = getMethod(BluetoothDevice.class, "setPasskey", new Class[] { int.class });
    private static final Constructor<?> _socketConstructor = getConstructor(BluetoothSocket.class, new Class[] {int.class, int.class, boolean.class, boolean.class, BluetoothDevice.class, int.class, ParcelUuid.class});

    public ImprovedBluetoothDevice(BluetoothDevice base) {
    if (base == null)
    throw new NullPointerException();

    mDevice = base;
    }

    public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException {
    return mDevice.createRfcommSocketToServiceRecord(uuid);
    }

    public int describeContents() {
    return mDevice.describeContents();
    }

    public String getAddress() {
    return mDevice.getAddress();
    }

    public BluetoothClass getBluetoothClass() {
    return mDevice.getBluetoothClass();
    }

    public int getBondState() {
    return mDevice.getBondState();
    }

    public String getName() {
    return mDevice.getName();
    }

    public String toString() {
    return mDevice.toString();
    }

    public void writeToParcel(Parcel out, int flags) {
    mDevice.writeToParcel(out, flags);
    }

    public BluetoothSocket createRfcommSocket(int channel) throws Exception {
    if (_createRfcommSocket == null) 
    throw new NoSuchMethodException("createRfcommSocket");
    try {
    return (BluetoothSocket)_createRfcommSocket.invoke(mDevice, channel);
    } catch (InvocationTargetException tex) {
    if (tex.getCause() instanceof Exception)
    throw (Exception)tex.getCause();
    else
    throw tex;
    }
    }

    public BluetoothSocket createInsecureRfcommSocket(int channel) throws Exception {
    if (_createInsecureRfcommSocket == null) 
    throw new NoSuchMethodException("createInsecureRfcommSocket");

    try {
    return (BluetoothSocket)_createInsecureRfcommSocket.invoke(mDevice, channel);
    } catch (InvocationTargetException tex) {
    if (tex.getCause() instanceof Exception)
    throw (Exception)tex.getCause();
    else
    throw tex;
    }
    }

    public BluetoothSocket createLCAPSocket(int channel) throws Exception {
    if (_socketConstructor == null)
    throw new NoSuchMethodException("new BluetoothSocket");

    try {
    return (BluetoothSocket)_socketConstructor.newInstance(TYPE_L2CAP, -1, true, true, mDevice, channel, null);
    } catch (InvocationTargetException tex) {
    if (tex.getCause() instanceof Exception)
    throw (Exception)tex.getCause();
    else
    throw tex;
    }
    }

    public BluetoothSocket createInsecureLCAPSocket(int channel) throws Exception {
    if (_socketConstructor == null)
    throw new NoSuchMethodException("new BluetoothSocket");

    try {
    return (BluetoothSocket)_socketConstructor.newInstance(TYPE_L2CAP, -1, false, false, mDevice, channel, null);
    } catch (InvocationTargetException tex) {
    if (tex.getCause() instanceof Exception)
    throw (Exception)tex.getCause();
    else
    throw tex;
    }
    }

    public boolean setPin(byte[] pin) throws Exception {
    if (_setPin == null)
    throw new NoSuchMethodException("setPin");

    try {
    return (Boolean)_setPin.invoke(mDevice, pin);
    } catch (InvocationTargetException tex) {
    if (tex.getCause() instanceof Exception)
    throw (Exception)tex.getCause();
    else
    throw tex;
    }
    }

    public boolean setPasskey(int passkey) throws Exception {
    if (_setPasskey == null)
    throw new NoSuchMethodException("setPasskey");

    try {
    return (Boolean)_setPasskey.invoke(mDevice, passkey);
    } catch (InvocationTargetException tex) {
    if (tex.getCause() instanceof Exception)
    throw (Exception)tex.getCause();
    else
    throw tex;
    }
    }
    }

    声明:eoe文章著作权属于作者,受法律保护,转载时请务必以超链接形式附带如下信息

    原文作者: haojunming

    原文地址: http://my.eoe.cn/111464/archive/1651.html

    展开全文
  • Android蓝牙串口调试助手 蓝牙通信 透传模块
  • Android蓝牙串口连接

    2016-11-01 22:19:42
    最近在做蓝牙开锁的小项目,手机去连接单片机总是出现问题,和手机的连接也不稳定,看了不少蓝牙方面的文档,做了个关于蓝牙连接的...在做Android蓝牙串口连接的时候一般会使用 [java] view plaincopy

    转自:http://blog.csdn.NET/jason0539/article/details/17782035

    最近在做蓝牙开锁的小项目,手机去连接单片机总是出现问题,和手机的连接也不稳定,看了不少蓝牙方面的文档,做了个关于蓝牙连接的小结。

    在做Android蓝牙串口连接的时候一般会使用

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. BluetoothSocket tmp = null;  
    2. // Get a BluetoothSocket for a connection with the  
    3. // given BluetoothDevice  
    4. try {  
    5.          tmp = device.createRfcommSocketToServiceRecord(MY_UUID);  
    6. catch (IOException e) {  
    7.     Log.e(TAG, "create() failed", e);  
    8. }  

    然后是tmp赋给BluetoothSocket,接着调用connect方法进行蓝牙设备的连接。

    可是 BluetoothSocket 的connect方法本身就会报很多异常错误。

    以下根据对蓝牙开发的一点研究可通过以下方法解决:

    方法1.先进行蓝牙自动配对,配对成功,通过UUID获得BluetoothSocket,然后执行connect()方法。

    方法2.通过UUID获得BluetoothSocket,然后先根据mDevice.getBondState()进行判断是否需要配对,最后执行connnect()方法。

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. private class ConnectThread extends Thread {  
    2.     String macAddress = "";  
    3.   
    4.     public ConnectThread(String mac) {  
    5.         macAddress = mac;  
    6.     }  
    7.   
    8.     public void run() {  
    9.         connecting = true;  
    10.         connected = false;  
    11.         if(mBluetoothAdapter == null){  
    12.             mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();  
    13.         }  
    14.         mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress);  
    15.         mBluetoothAdapter.cancelDiscovery();  
    16.         try {  
    17.             socket = mBluetoothDevice.createRfcommSocketToServiceRecord(uuid);  
    18.               
    19.         } catch (IOException e) {  
    20.             // TODO Auto-generated catch block  
    21.             //e.printStackTrace();  
    22.             Log.e(TAG, "Socket", e);  
    23.         }               
    24.         //adapter.cancelDiscovery();  
    25.         while (!connected && connetTime <= 10) {                  
    26.             connectDevice();  
    27.         }  
    28.         // 重置ConnectThread   
    29.         //synchronized (BluetoothService.this) {  
    30.            //ConnectThread = null;  
    31.         //}  
    32.     }  
    33.   
    34.     public void cancel() {  
    35.         try {  
    36.             socket.close();  
    37.             socket = null;  
    38.         } catch (Exception e) {  
    39.             e.printStackTrace();  
    40.         } finally {  
    41.             connecting = false;  
    42.         }  
    43.     }  
    44. }  

    接下来是调用的连接设备方法connectDevice():

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. protected void connectDevice() {    
    2.         try {    
    3.             // 连接建立之前的先配对    
    4.             if (mBluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE) {    
    5.                 Method creMethod = BluetoothDevice.class    
    6.                         .getMethod("createBond");    
    7.                 Log.e("TAG""开始配对");    
    8.                 creMethod.invoke(mBluetoothDevice);    
    9.             } else {    
    10.             }    
    11.         } catch (Exception e) {    
    12.             // TODO: handle exception    
    13.             //DisplayMessage("无法配对!");    
    14.             e.printStackTrace();    
    15.         }    
    16.         mBluetoothAdapter.cancelDiscovery();    
    17.         try {    
    18.             socket.connect();    
    19.             //DisplayMessage("连接成功!");   
    20.             //connetTime++;  
    21.             connected = true;  
    22.         } catch (IOException e) {    
    23.             // TODO: handle exception    
    24.             //DisplayMessage("连接失败!");  
    25.             connetTime++;  
    26.             connected = false;  
    27.             try {    
    28.                 socket.close();  
    29.                 socket = null;  
    30.             } catch (IOException e2) {    
    31.                 // TODO: handle exception    
    32.                 Log.e(TAG, "Cannot close connection when connection failed");    
    33.             }    
    34.         } finally {  
    35.             connecting = false;  
    36.         }    
    37.     }  


     

    方法3.利用反射通过端口获得BluetoothSocket,然后执行connect()方法。

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. private class ConnectThread extends Thread {  
    2.     String macAddress = "";  
    3.   
    4.     public ConnectThread(String mac) {  
    5.         macAddress = mac;  
    6.     }  
    7.   
    8.     public void run() {  
    9.         connecting = true;  
    10.         connected = false;  
    11.         if(mBluetoothAdapter == null){  
    12.             mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();  
    13.         }  
    14.         mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress);  
    15.         mBluetoothAdapter.cancelDiscovery();  
    16.         initSocket();                           
    17.         //adapter.cancelDiscovery();  
    18.         while (!connected && connetTime <= 10) {  
    19.             try {  
    20.                 socket.connect();  
    21.                 connected = true;  
    22.             } catch (IOException e1) {  
    23.                 connetTime++;  
    24.                 connected = false;  
    25.                 // 关闭 socket  
    26.                 try {  
    27.                     socket.close();  
    28.                     socket = null;  
    29.                 } catch (IOException e2) {  
    30.                     //TODO: handle exception    
    31.                     Log.e(TAG, "Socket", e2);  
    32.                 }  
    33.             } finally {  
    34.                 connecting = false;  
    35.             }  
    36.             //connectDevice();  
    37.         }  
    38.         // 重置ConnectThread   
    39.         //synchronized (BluetoothService.this) {  
    40.            //ConnectThread = null;  
    41.         //}  
    42.     }  
    43.   
    44.     public void cancel() {  
    45.         try {  
    46.             socket.close();  
    47.             socket = null;  
    48.         } catch (Exception e) {  
    49.             e.printStackTrace();  
    50.         } finally {  
    51.             connecting = false;  
    52.         }  
    53.     }  
    54. }  

    接下来是初始化并得到BluetoothSocket的方法

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. /** 
    2.      * 取得BluetoothSocket 
    3.      */  
    4.     private void initSocket() {  
    5.         BluetoothSocket temp = null;  
    6.         try {              
    7.             Method m = mBluetoothDevice.getClass().getMethod(  
    8.                     "createRfcommSocket"new Class[] { int.class });  
    9.             temp = (BluetoothSocket) m.invoke(mBluetoothDevice, 1);//这里端口为1              
    10.         } catch (SecurityException e) {  
    11.             e.printStackTrace();  
    12.         } catch (NoSuchMethodException e) {  
    13.             e.printStackTrace();  
    14.         } catch (IllegalArgumentException e) {  
    15.             e.printStackTrace();  
    16.         } catch (IllegalAccessException e) {  
    17.             e.printStackTrace();  
    18.         } catch (InvocationTargetException e) {  
    19.             e.printStackTrace();  
    20.         }  
    21.         socket = temp;  
    22.     }  

     

    要点:1.蓝牙配对和连接是两回事,不可混为一谈。

       2.蓝牙串口连接可通过端口 (1-30)和UUID两种方法进行操作。

       3.通过UUID进行蓝牙连接最好先进行配对操作。


    说明:在连接蓝牙过程中总是不稳定,先配对后,情况明显好转。

    另外装载作者的另外一个补充,详细过程还没有试验

    http://www.aiseminar.cn/bbs/forum.PHP?mod=viewthread&tid=2369&fromuid=3

    如前文“第二个Activity中onStop设置Service为第一个Activity的handler为什么不起作用?”所描述的问题,开始以为是handle出了问题:“蓝牙使用UUID进行连接,第一设备之间可以正常连接。而socket关闭后,后续连接都会出现service discovery failed错误”。


    后来查阅资料发现,这是Android蓝牙连接经常遇到的问题。有人怀疑是Android系统的bug,而且提出使用反射方法解决此问题。经过AIS蓝牙对讲机的使用测试结果表明:使用Reflect方法进行蓝牙连接,可以重复连接任意多次,不会再出现上述问题。


    所谓使用反射方式,就是通过Java的反射机制,取出Bluetooth的监听和创建连接socket的方法,使用反射的方法进行操作,而再使用listenUsingRfcommWithServiceRecord和createRfcommSocketToServiceRecord这样的问题函数。实现时,同样如同这样连个函数,需要将反射操作配对使用。如下:

    替换listenUsingRfcommWithServiceRecord的反射操作:

    1.                 public BluetoothServerSocket listenUsingRfcommWithReflect()
    2.                 {
    3.                         BluetoothServerSocket tmp = null;
    4.                         Method m;
    5.                         try 
    6.                         {
    7.                                 m = mBTAdapter.getClass().getMethod("listenUsingRfcommOn", new Class[] { int.class });
    8.                                 try
    9.                                 {
    10.                                         tmp = (BluetoothServerSocket) m.invoke(mBTAdapter, 1); // 1为监听端口号
    11.                                 } 
    12.                                 catch (IllegalAccessException e) {
    13.                                         // TODO Auto-generated catch block
    14.                                         e.printStackTrace();
    15.                                 } 
    16.                                 catch (IllegalArgumentException e) {
    17.                                         // TODO Auto-generated catch block
    18.                                         e.printStackTrace();
    19.                                 } 
    20.                                 catch (InvocationTargetException e) {
    21.                                         // TODO Auto-generated catch block
    22.                                         e.printStackTrace();
    23.                                 }
    24.                         } 
    25.                         catch (NoSuchMethodException e) {
    26.                                 // TODO Auto-generated catch block
    27.                                 e.printStackTrace();
    28.                         }
    29.                         
    30.                         return tmp;
    31.                 }
    复制代码
    替换createRfcommSocketToServiceRecord的反射操作:
    1.                 public BluetoothSocket createRFcommSocketWithReflect(BluetoothDevice device)
    2.                 {
    3.                         BluetoothSocket tmp = null;
    4.                         Method reflectMethod = null;
    5.                         try 
    6.                         {
    7.                                 reflectMethod = mRemoteDevice.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
    8.                                 try 
    9.                                 {
    10.                                         tmp = (BluetoothSocket)reflectMethod.invoke(device, Integer.valueOf(1)); // 1为监听端口号
    11.                                 } 
    12.                                 catch (IllegalAccessException e) {
    13.                                         // TODO Auto-generated catch block
    14.                                         e.printStackTrace();
    15.                                 } 
    16.                                 catch (IllegalArgumentException e) {
    17.                                         // TODO Auto-generated catch block
    18.                                         e.printStackTrace();
    19.                                 } 
    20.                                 catch (InvocationTargetException e) {
    21.                                         // TODO Auto-generated catch block
    22.                                         e.printStackTrace();
    23.                                 }
    24.                         }
    25.                         catch (NoSuchMethodException e) 
    26.                         {
    27.                         }
    28.                         
    29.                         return tmp;
    30.                 }
    复制代码
    上面函数中的常量1为蓝牙端口号,据说:蓝牙串口连接可通过端口号:1-30。

    Referred to:
    [1] 第二个Activity中onStop设置Service为第一个Activity的handler为什么不起作用?http://www.aiseminar.cn/bbs/forum.php?mod=viewthread&tid=2314&fromuid=3
    [2] java.io.IOException: Service discovery failed. http://stackoverflow.com/questions/17812222/java-io-ioexception-service-discovery-failed
    [3] Android listen for connections without UUID. http://stackoverflow.com/questions/13362774/android-listen-for-connections-without-uuid

    [4] android开发之蓝牙配对连接的方法. http://blog.csdn.Net/jason0539/article/details/17782035


    另外两篇关于蓝牙的文章:

    蓝牙开发:http://www.cnblogs.com/wenjiang/p/3200138.html


    展开全文
  • qt for Android蓝牙串口助手app PC端和手机端均可使用。
  • Android蓝牙串口通讯 闲着无聊玩起了Android蓝牙模块与单片机蓝牙模块的通信,简单思路就是要手机通过蓝牙发送控制指令给单片机,并作简单的控制应用。单片机的蓝牙模块连接与程序暂且略过,此文主要描述Android...

    本文转载自:http://blog.sina.com.cn/s/blog_631e3f2601012ixi.html

    Android蓝牙串口通讯

    闲着无聊玩起了Android蓝牙模块与单片机蓝牙模块的通信,简单思路就是要手机通过蓝牙发送控制指令给单片机,并作简单的控制应用。单片机的蓝牙模块连接与程序暂且略过,此文主要描述Android手机蓝牙客户端遇到的那点破事。进入正题:

    连接蓝牙设备——蓝牙客户端:

    Android手机一般以客户端的角色主动连接SPP协议设备(接上蓝牙模块的数字传感器),客户端连接流程是:

    1.使用registerReceiver注册BroadcastReceiver来获取蓝牙状态、搜索设备等消息;

        private BroadcastReceiver searchDevices new BroadcastReceiver() { 

           public void onReceive(Context context, Intent intent) {

               String action = intent.getAction();

               Bundle b = intent.getExtras();

               Object[] lstName = b.keySet().toArray(); 

               // 显示所有收到的消息及其细节

               for (int i = 0; i < lstName.length; i++) {

                  String keyName = lstName[i].toString();

                  Log.e(keyName, String.valueOf(b.get(keyName)));

               }

               //搜索设备时,取得设备的MAC地址

               if (BluetoothDevice.ACTION_FOUND.equals(action)) {

                  BluetoothDevice device = intent

                         .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                  String str= device.getName() + "|" + device.getAddress();

                 

                  if (lstDevices.indexOf(str) == -1)// 防止重复添加

                      lstDevices.add(str); // 获取设备名称和mac地址

                  adtDevices.notifyDataSetChanged();

               }

           }

        };

     

    2.使用BlueAdatper的搜索:

        btAdapt.startDiscovery();
        3.在BroadcastReceiver的onReceive()里取得搜索所得的蓝牙设备信息(如名称,MAC,RSSI);
        4.通过设备的MAC地址来建立一个BluetoothDevice对象;

    5.由BluetoothDevice衍生出BluetoothSocket,准备SOCKET来读写设备;

    6.通过BluetoothSocket的createRfcommSocketToServiceRecord()方法来选择连接的协议/服务,这里用的       是SPP(UUID:00001101-0000-1000-8000-00805F9B34FB);

    try {     

           btSocket = btDev.createRfcommSocketToServiceRecord(uuid);

        } catch (IOException e) {

        // TODO Auto-generated catch block

           Log.e(TAG"Low: Connection failed.", e);     

        }

    成功后进行连接:

    try {

        btSocket.connect();            

        Log.e(TAG" BT connection established, data transfer link open.");

        mangeConnectedSocket(btSocket);//自定义函数进行蓝牙通信处理

     

    catch (IOException e) {

        Log.e(TAG" Connection failed.", e); 

        setTitle("连接失败..");

    }  

    7.Connect之后(如果还没配对则系统自动提示),使用

      BluetoothSocket的getInputStream()和getOutputStream()来读写蓝牙设备。

     读写可以归到一个独立线程去实现~ 注意:读时必须一直循环读取串口缓冲区,写可以不需要。 

    按以上7步逐次走过后,你就会发现Android蓝牙模块是多么的坑爹了。

    出现问题:

            在第6步一般初学者都会报错: 执行.connect()发生异常Connection refused

        此时执行不下去咯,怎么办怎么办呢?

        于是边debug边网上找攻略,总算在Google出老外的一些做法,尝试了下,貌似还可行。也即把

        btSocket的建立方法采用另一种方法替代,这里都使用端口1

    Method m;

    try {

        m = btDev.getClass().getMethod("createRfcommSocket"new Class[] {int.class});

        btSocket = (BluetoothSocket) m.invoke(btDev, Integer.valueOf(1));

                  } catch (SecurityException e1) {

                      // TODO Auto-generated catch block

                      e1.printStackTrace();

                  } catch (NoSuchMethodException e1) {

                      // TODO Auto-generated catch block

                      e1.printStackTrace();

                  } catch (IllegalArgumentException e) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

                  } catch (IllegalAccessException e) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

                  } catch (InvocationTargetException e) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

               } 

    至此,这个问题貌似倒也解决了,程序继续往下跑。

    但这里请记住之前的异常,先别急着抛开~人家不一定一直都是异常哦

     

    接下来的任务是,让手机通过蓝牙跟单片机的蓝牙模块通信,并发送数据,通过电脑串口调试助手显示出来。具体实现,在mangeConnectedSocket(btSocket)方法中实现,里面通过启动另一个Activity实现。不是重点,略过。

     

    直到这里,我们都只是把手机蓝牙模块充当客户端来使用,那什么时候会用到服务端呢?其实,之前手机蓝牙与单片机蓝牙模块的通信,单片机蓝牙模块就充当了服务端(处于监听状态,被手机蓝牙连接)。为了更好地搞清楚Android蓝牙通信,我们接下来使用2个手机的蓝牙进行通信。简单地说,就是做一个“手机蓝牙扣扣”,⊙﹏⊙b汗

     

    一开始就想天真地把之前的程序同时烧到2部手机中,发现只有一部手机能正常建立socket连接(主动连接的那台),而另一部却迟迟没有响应。原因很简单,服务端的程序还没有编写! 

    于是,开始服务端程序:开辟一个新的线程实现

    连接蓝牙设备——蓝牙服务端:

        class AcceptThread extends Thread {

        private final BluetoothServerSocket serverSocket;

        public AcceptThread() {

            // Use a temporary object that is later assigned to mmServerSocket,

            // because mmServerSocket is final 

        BluetoothServerSocket tmp=null;

        try {

    //tmp = btAdapt.listenUsingRfcommWithServiceRecord("MyBluetoothApp", uuid);

        Log.e(TAG"++BluetoothServerSocket established!++");

      Method listenMethod =        btAdapt.getClass().getMethod("listenUsingRfcommOn",

       new   Class[]{int.class});

        tmp = ( BluetoothServerSocket) listenMethod.invoke(btAdapt,                                                  Integer.valueOf( 1));

              

           } catch (SecurityException e) {

               // TODO Auto-generated catch block

               e.printStackTrace();

           } catch (IllegalArgumentException e) {

               // TODO Auto-generated catch block

               e.printStackTrace();

           } catch (NoSuchMethodException e) {

               // TODO Auto-generated catch block

               e.printStackTrace();

           } catch (IllegalAccessException e) {

               // TODO Auto-generated catch block

               e.printStackTrace();

           } catch (InvocationTargetException e) {

               // TODO Auto-generated catch block

               e.printStackTrace();

           }

          

           serverSocket=tmp;

        }   

       

       public void run() {

           

            // Keep listening until exception occurs or a socket is returned

             //mState!=STATE_CONNECTED

       while(true) {//这里是一直循环监听,也可以设置mState来判断

            try {

               socket serverSocket.accept();

               Log.e(TAG"++BluetoothSocket established! DataLink open.++");

                } catch (IOException e) {

                    break;

                }

                // If a connection was accepted

                if (socket != null) {

                    // Do work to manage the connection (in a separate thread)

                    manageConnectedSocket();    

                    try {

                      serverSocket.close();

                  } catch (IOException e) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

                  }

                    break;

                }

            }       

    }

     

        public void cancel() {

            try {

                serverSocket.close();

            } catch (IOException e) { }

        }

    }

     

    安装测试:2部手机都装上并打开同样的程序后,通过蓝牙检索并连接,经测试可以成功连接上,双双进入“聊天界面”,嘿嘿

    关于Android蓝牙串口通信那点破事

     

    注意,这时候重新拾回之前那个异常,把socket连接建立的方法重新改为

    btSocket = btDev.createRfcommSocketToServiceRecord(uuid);//客户端

    对应的服务端程序:

    tmp = btAdapt.listenUsingRfcommWithServiceRecord("MyBluetoothApp", uuid);//服务端

     

    这样继续重新运行安装测试,在2部手机上运行发现之前那个bug消失了~2部手机又双双进入聊天界面。

    神奇

    存在bug

    任一一部手机都只能成功启动一次作为客户端的主动连接,当退出聊天界面回到主界面时(服务端的AcceptThread还在继续运行着),可再次主动连接另一部手机时就又报异常Connection refused。也就是说 客户端的蓝牙套接字2次连接时出错~哎(注意我的客户端蓝牙连接程序是没有放到一个独立线程,而是放到一个按钮监听事件中) 

    又折腾了好久,没发现个所以然来,看来连完一次退出再连时就只好重启程序咯。有哪位大神知道为什么的麻烦告知下哈!

    若需要代码,code下载

    转载于:https://www.cnblogs.com/zzb-Dream-90Time/p/6571879.html

    展开全文
  • Android蓝牙串口连接总结

    千次阅读 2016-05-23 10:59:06
    这里重点说下蓝牙连接: ...在做Android蓝牙串口连接的时候一般会使用  BluetoothSocket tmp = null;  // Get a BluetoothSocket for a connection with the  // given BluetoothDevice  try {  
  • Android 蓝牙串口调试助手源码(保证正确)

    千次下载 热门讨论 2012-11-19 09:35:30
    买别人的代码,这里分享。已经编译生成apk。可以改源码供自己需要。
  • 蓝牙串口调试助手_com.bluetooth_com_7.apk
  • 基于html5+的nativejs实现android蓝牙串口通讯

    万次阅读 热门讨论 2018-07-20 22:50:48
    代码实现摸索了一下,自己写了一个蓝牙串口连接接收数据的小示例。还是希望有大神告知如何开启多线程来接收数据。如果要测试此代码需要自行引入vue.js。
  • Ubuntu18.10连接Android蓝牙串口助手 突然间想这么玩一下,结果发现似乎没有合适的中文资料。 环境:PC机系统为Ubuntu18.10(刚刚全新安装的) 安卓手机:蓝牙串口助手(豌豆荚搜索第一个就是了) 环境类似也可。 ...
  • Android蓝牙串口传输心电数据画图的小程序

    千次下载 热门讨论 2011-04-26 10:46:56
    Andriod 2.2的蓝牙串口协议传输的一个小范例程序。可以查找蓝牙设备,建立连接,传输心电数据并画出波形图。 如果要进行测试,请在有蓝牙适配器的电脑上安装支持虚拟蓝牙串口的...PS:Android蓝牙只能在真机上运行。
  • 关于Android蓝牙串口通信那点破事

    千次阅读 2014-05-22 10:29:55
    关于Android蓝牙串口通信那点破事 (2012-10-17 14:15:59) 转载▼ 标签: android蓝牙 connect异常 蓝牙客户端 蓝牙服务端 分类: 小试牛刀   Android蓝牙串口通讯 闲着无聊...
  • 在学校和机电的同学组队准备做一个智能小车去参加比赛,需要我开发一个小车的控制app,所以我开始学习蓝牙串口通信的相关知识。 在看了别人的博客之后,我写了一个蓝牙串口通信的Demo。但由于我没有那些硬件,所以...
  • Android蓝牙串口通讯

    千次阅读 2017-04-18 10:54:58
    蓝牙串口模块就是使用单片机的TX ,RX与蓝牙模块通信,单片机通过TX发送数据给蓝牙模块,然后蓝牙模块在通过蓝牙协议把数据发送出去,蓝牙模块与Android的通信方式使用spp协议。 2.蓝牙通信 蓝牙的通信需要服务端和...
  • Android蓝牙串口通讯 闲着无聊玩起了Android蓝牙模块与单片机蓝牙模块的通信,简单思路就是要手机通过蓝牙发送控制指令给单片机,并作简单的控制应用。单片机的蓝牙模块连接与程序暂且略过,此文主要描述Android...
  • 本文主要介绍了针对android蓝牙串口上位机开发。 程序下载地址:点击打开链接 一、帧定义 androidclient依照一定的数据帧格式通过蓝牙串口发送数据到连接到MCU的蓝牙从机。MCU接收到数据后。依照帧格式的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 621
精华内容 248
关键字:

android蓝牙串口