当前位置: 首页 > 面试题库 >

从蓝牙4.2更新到Android 4.3后,使用蓝牙SPP配置文件的应用程序无法正常工作

罗睿识
2023-03-14
问题内容

我编写了一个基于bluetoothChat的简单应用程序。我使用SPP配置文件在电话和蓝牙模块之间进行通信。电话始终会启动通信。该应用程序在使用Nexus 3和Samsung Galaxy 3的Android 4.2上完美运行。在更新至Android 4.3之后,该应用程序不再起作用。我一直保持连接状态,可以发送输出流并接收正确的数据,但是在执行第一个outputstream命令后,应用程序总是在约6秒后断开连接。如下面的logcat所示,看起来输入流上存在计时器问题。

08-23 14:10:00.726: D/mems(23193): STEVAL-MKI106V1
08-23 14:10:00.804: D/Main Activity(23193): firmware version*setdb106V1
08-23 14:10:00.812: D/Main Activity(23193): sent message*setdb106V1
08-23 14:10:00.812: D/BluetoothMEMSCommunication(23193): dans write3
08-23 14:10:00.812: D/BluetoothMEMSCommunication(23193): envoi stream
08-23 14:10:05.812: W/bt-btif(20368): dm_pm_timer expires
08-23 14:10:05.812: W/bt-btif(20368): dm_pm_timer expires 0
08-23 14:10:05.812: W/bt-btif(20368): proc dm_pm_timer expires
08-23 14:10:11.656: E/bt-btm(20368): btm_sec_disconnected - Clearing Pending flag
08-23 14:10:11.656: W/bt-btif(20368): invalid rfc slot id: 15
08-23 14:10:11.656: I/connection(23193): connectionlost

什么是dm_pm_timer?我尝试用安全和不安全的rfcom连接另一种方式。我知道蓝牙聊天尚未针对接收缓冲区进行优化,因此我对其进行了修改,并非没有效果。我也对输出流使用了flush命令,但也没有效果。

package com.meneujj.memsbtbis;

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

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

public class BluetoothMEMSCommunication {

// debugging
private static final String TAG = "BluetoothMEMSCommunication";
private static final boolean D = true;


// eMotion BT h as this standard UUID
private static final UUID STANDARD_UUID = 
        UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");


// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private int mState;
private int handlerCalling;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;

      // Constants they indicate the current connection state
public static final int STATE_NONE = 0;
public static final int STATE_CONNECTED = 3; // now connected to a remote device

// constructor. Prepares a new Bluetooth Connection
// context The UI Activity Context
// handler an Handler to send messages back to the UI Activity

public BluetoothMEMSCommunication(Context context, Handler handler, int i) {
    mAdapter = BluetoothAdapter.getDefaultAdapter();
    mState = STATE_NONE;
    mHandler = handler;
    handlerCalling = i;

}


private synchronized void setState(int state) {
    mState = state;
    Log.d(TAG, Integer.toString(mState));
    mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}

public synchronized void connect(BluetoothDevice device) {


    // start the thread to connect with the given device
    if (mConnectThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null;

    }

    // cancel any thread currently running a connection
    if (mConnectedThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null; 

    }

    Log.d(TAG,"routine connect lancee");
    mConnectThread = new ConnectThread(device);
    mConnectThread.start();

}


private void ConnectionLost() {
    // Send a failure message back to the activity
    Message msg = mHandler.obtainMessage(MainActivityMemsBT.CONNECTION_LOST_MESSAGE);
    Bundle bundle = new Bundle();
    bundle.putString(MainActivityMemsBT.TOAST_CONNECTION_LOST, "Device connection was lost");
    msg.setData(bundle);
    mHandler.sendMessage(msg);
    Log.i("connection","connectionlost");

    setState(STATE_NONE);
    StopAllThreads();

}



public synchronized void StopAllThreads() {

    if (mConnectThread != null) {
        mConnectThread.cancel();
        mConnectThread = null;
    }

    if (mConnectedThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null;

    }

setState(STATE_NONE);

}

public synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType) {

    // cancel the thread they completed the connection
    if (mConnectThread != null) {
        mConnectThread.cancel();
        mConnectThread = null;
    }

    // Cancel any thread currently running a connection
    if (mConnectedThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null;

    }


    // Start the thread to manage the connection and perform transmission
    mConnectedThread = new ConnectedThread(socket, socketType);
    mConnectedThread.start();

    // Send the name of the connected device back to the UI activity
    Message msg = mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_DEVICE_NAME);
    Bundle bundle = new Bundle();
    bundle.putString(MainActivityMemsBT.DEVICE_NAME, device.getName());
    msg.setData(bundle);
    mHandler.sendMessage(msg);      

    setState(STATE_CONNECTED);

}


      public void write(byte[] out) {
// create temporary object
ConnectedThread r;

Log.d(TAG,"dans write" + Integer.toString(mState));

// synchronize a copy of the ConnectedThread
synchronized (this) {

    if (handlerCalling == 2) setState(STATE_CONNECTED);

    if (mState != STATE_CONNECTED) {
        Log.d(TAG, "different de STATE_CONNECTED");
        Log.i(TAG, Integer.toString(handlerCalling));
        return;}

    r= mConnectedThread;
}

r.write(out);

   }

有办法解决吗?或我的代码中有任何明显的错误

谢谢

// Thread runs while attempting to an an outgoing connection with a device.
// it runs straight through; the connection either succeeds or fails.
private class ConnectThread extends Thread {

    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;
    private String mSocketType;

    public ConnectThread(BluetoothDevice device) {
        mmDevice = device;
        BluetoothSocket tmp = null;

        try {
        tmp = device.createRfcommSocketToServiceRecord(STANDARD_UUID);
            //tmp = device.createInsecureRfcommSocketToServiceRecord(STANDARD_UUID);

/*          try {
                Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
                try {
                    tmp = (BluetoothSocket) m.invoke(device, 1);
                } 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();
                }
            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } */

        } catch (IOException e) {

        }
        mmSocket = tmp;

    }

    public void run () {

        setName("ConnectThread" + mSocketType);
        mAdapter.cancelDiscovery();

        try {
            mmSocket.connect();
        } catch (IOException e) {

            try {
                mmSocket.close();
            } catch (IOException e2) {
                Log.e(TAG, "unable to close() " + mSocketType + "socket during connection failure", e2);
            }

        return; 
        }

    // reset the CoonectThread because the job is over
    synchronized (BluetoothMEMSCommunication.this) {
        mConnectThread = null;
        }

    connected(mmSocket, mmDevice, mSocketType);

    }

    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) {

        }
    }

      // close connectThread class      
}


     private class ConnectedThread extends Thread {

private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;

public ConnectedThread(BluetoothSocket socket, String socketType) {

    mmSocket = socket;
    InputStream tmpIn = null;
    OutputStream tmpOut = null;

    try {
        tmpIn = socket.getInputStream();
        tmpOut = socket.getOutputStream();

    } catch (IOException e) {
        ConnectionLost();

    }

    mmInStream = tmpIn;
    mmOutStream = tmpOut;

}

//  Thread to listen to input sockets

public void run() {

    Log.i(TAG, "Begin mConnectedThread");

    byte[] buffer = new byte[1024];
//  int bytes;
    int bytesRead = -1;
    String message = "";

    // keep listening to the InputStream while connected
    while(true) {


            try {

                // read from the input stream
            //  bytesRead = mmInStream.read(buffer);
        //      message = message+ new String(buffer, 0, bytesRead);

            //  byte[] byteString = message.getBytes();

                Log.i("info","pret a faire read");
                bytesRead = mmInStream.read(buffer, 0, 1024);

                if (bytesRead != -1 && handlerCalling == 1) {
                mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_READ, bytesRead, -1, buffer).sendToTarget(); }

                if (bytesRead !=-1 && handlerCalling == 2) {
                    mHandler.obtainMessage(DemoAccelerometer.MESSAGE_READ, bytesRead, -1, buffer).sendToTarget(); }

                }

             catch (IOException e) {

                 ConnectionLost();
                break;
            }


            }

        }


public void write(byte[] buffer) {

    try{
        mmOutStream.write(buffer);

//      if (handlerCalling == 1) {
//      mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
        Log.d(TAG,"envoi stream");

    //  mmOutStream.flush();
//      }

    } catch (IOException e) {

    }

}

public void cancel() {
    try{
        mmSocket.close();
    } catch (IOException e) {

    }
}

   }

    }

问题答案:

从Android 4.2升级到4.3后,当从我们的Nexus 4应用与外部蓝牙ECG(医疗设备)进行通信时,我们可以在6秒后确认蓝牙断开连接。这种情况特别发生在ECG测量中,其中包含大量入站数据(从ECG到Android应用),但没有出站数据。似乎不时会与某些入站和出站数据进行“正常”蓝牙通信。

6秒后,我们将看到JJM报告的相同adb日志消息

dm_pm_timer expires
dm_pm_timer expires 0
proc dm_pm_timer expires
btm_sec_disconnected - Clearing Pending flag

Android端的计时器到期会触发外部蓝牙ECG上的某些事件(关闭输出流,因为没有出站数据?),这反过来又发送了我们在输入流上收到的ECG特定命令,而在Android 4.2的Nexus 4上却从未收到过。

更改Android应用程序的实现以偶尔向ECG发送任意的“保持活动”命令即可解决此问题。计时器到期时间不再显示在adb日志中,ECG测量现在的行为与Android 4.2相同。

感谢JJM的提示。



 类似资料:
  • 这让我困惑了好几天。 在开始时,当我实现的功能,我使用GATT配置文件BLE蓝牙通信。 然后我想到了蓝牙插座。这将SPP配置文件用于蓝牙通信。 其中提到: 最常见的蓝牙套接字类型是RFCOMM,这是Android API支持的类型。RFCOMM是一种面向连接的蓝牙流式传输。它也称为串行端口配置文件(SPP)。 我的要求是- 1)使用BLE蓝牙扫描并将我的android设备与黑匣子连接。 2) 然后

  • 本文向大家介绍蓝牙用法和应用,包括了蓝牙用法和应用的使用技巧和注意事项,需要的朋友参考一下 蓝牙使用 蓝牙的使用大致可分为三个领域: 数据和语音的接入点-蓝牙通过无线连接便携式和固定网络设备来提供实时语音和数据传输。 电缆更换-蓝牙替代了有线网络的大量电线和电缆。即使设备不在范围内,连接也可以立即建立并保持。设备的范围通常为10m。但是,可以通过使用放大器扩大范围。 Ad hoc网络-网络设备即席

  • jd.closeBluetoothAdapter(Object object) 关闭蓝牙模块。调用该方法将断开所有已建立的连接并释放系统资源。建议在使用蓝牙流程后,与 jd.openBluetoothAdapter 成对调用。 参数 Object object 属性 类型 默认值 必填 说明 success function 否 接口调用成功的回调函数 fail function 否 接口调用失败

  • 蓝牙模块能够使你的作品与 Makeblock 蓝牙适配器 或支持蓝牙4.0的设备建立无线连接,使你能够无线地控制你的作品。 蓝牙的连接设置参看:通过蓝牙连接设备 蓝牙的灯效及含义 闪烁:蓝牙未被连接 常亮:蓝牙已连接,工作正常 灭:断电或故障 参数 尺寸:24×24mm 推荐使用距离:10m以内 蓝牙版本:BT4.0 频带范围:2402~2480MHz 天线增益:1.5dBi 能耗等级:≤4dBm

  • 蓝牙模块能够使你的作品与 Makeblock 蓝牙适配器 或支持蓝牙4.0的设备建立无线连接,使你能够无线地控制你的作品。 蓝牙的连接设置参看:通过蓝牙连接设备 蓝牙的灯效及含义 闪烁:蓝牙未被连接 常亮:蓝牙已连接,工作正常 灭:断电或故障 参数 尺寸:24×24mm 推荐使用距离:10m以内 蓝牙版本:BT4.0 频带范围:2402~2480MHz 天线增益:1.5dBi 能耗等级:≤4dBm

  • 1.1.1. btflinger 1.1.2. 以下为相关的接口: 1.1.1. btflinger btflinger是RokidOS提供的蓝牙服务 1.1.2. 以下为相关的接口: int bluetooth_rokid_open(char *name);//打开蓝牙 int bluetooth_rokid_close(void);//关闭蓝牙 int bluetooth_rokid_us