使用蓝牙SPP配置文件无法正常工作更新后从安卓4.2应用到Android 4.3 [英] Application using bluetooth SPP profile not working after update from Android 4.2 to Android 4.3

查看:733
本文介绍了使用蓝牙SPP配置文件无法正常工作更新后从安卓4.2应用到Android 4.3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了基于bluetoothChat一个简单的应用程序。我的手机和使用SPP模式的蓝牙模块之间的通信。这款手机总是启动通信。该应用程序的工作pefectly在Android 4.2,使用的Nexus 3和三星Galaxy 3。 升级到Android 4.3之后,应用程序不工作了。我连接所有的时间,我可以发送outpustream和接收正确的数据,但是第一个OutputStream的命令后,该应用程序周围的6S后总是断开。 如下面所述的logcat,它看起来是有问题计时器上的InputStream

  08-23 14:10:00.726:D / MEMS(23193):STEVAL-MKI106V1
08-23 14:10:00.804:D /主要活动(23193):固件版本* setdb106V1
08-23 14:10:00.812:D /主要活动(23193):发送消息* setdb106V1
08-23 14:10:00.812:D / BluetoothMEMSCommunication(23193):丹斯write3
08-23 14:10:00.812:D / BluetoothMEMSCommunication(23193):envoi流
08-23 14:10:05.812:W / BT-BTIF(20368):dm_pm_timer到期
08-23 14:10:05.812:W / BT-BTIF(20368):dm_pm_timer期满0
08-23 14:10:05.812:W / BT-BTIF(20368):PROC dm_pm_timer到期
08-23 14:10:116.56:E / BT-BTM(20368):btm_sec_disconnected  - 清除标志位
08-23 14:10:116.56:W / BT-BTIF(20368):无效的RFC槽位号:15
08-23 14:10:116.56:I /连接(23193):connectionlost
 

什么是dm_pm_timer? 我试图连接不同的方式,具有安全和不安全rfcom。我知道蓝牙聊天未优化接收缓冲区,所以我修改了它,没有任何效果。我用flush命令为outpustream过,但要么没有效果。

 包com.meneujj.memsbtbis;

进口java.io.IOException异常;
进口的java.io.InputStream;
进口java.io.OutputStream中;
进口java.lang.reflect.InvocationTargetException;
进口java.lang.reflect.Method中;
进口java.util.UUID中;

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

公共类BluetoothMEMSCommunication {

// 调试
私有静态最后字符串变量=BluetoothMEMSCommunication;
私有静态最终布尔D =真;


//情绪BT H作为该标准的UUID
私有静态最后UUID STANDARD_UUID =
        UUID.fromString(00001101-0000-1000-8000-00805F9B34FB);


//会员领域
私人最终BluetoothAdapter mAdapter;
私人最终处理程序mHandler;
私人诠释mState;
私人诠释handlerCalling;
私人ConnectThread mConnectThread;
私人ConnectedThread mConnectedThread;

      //常量,他们指示当前连接状态
公共静态最终诠释STATE_NONE = 0;
公共静态最终诠释STATE_CONNECTED = 3; //现在连接到远程设备

//构造函数。 prepares新的蓝牙连接
//上下文UI活动上下文
//处理程序的处理程序,以回消息发送到用户界面活动

公共BluetoothMEMSCommunication(上下文的背景下,处理程序处理,int i)以{
    mAdapter = BluetoothAdapter.getDefaultAdapter();
    mState = STATE_NONE;
    mHandler =处理程序;
    handlerCalling =我;

}


私人同步无效的setState(INT状态){
    mState =状态;
    Log.d(TAG,Integer.toString(mState));
    mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_STATE_CHANGE,州,-1).sendToTarget();
}

市民同步无效连接(BluetoothDevice类设备){


    //启动线程与给定的设备连接
    如果(mConnectThread!= NULL){
        mConnectedThread.cancel();
        mConnectedThread = NULL;

    }

    //取消任何线程当前正在运行的连接
    如果(mConnectedThread!= NULL){
        mConnectedThread.cancel();
        mConnectedThread = NULL;

    }

    Log.d(TAG,常规连接lancee);
    mConnectThread =新ConnectThread(设备);
    mConnectThread.start();

}


私人无效ConnectionLost(){
    //发送失败消息发送回活动
    消息味精= mHandler.obtainMessage(MainActivityMemsBT.CONNECTION_LOST_MESSAGE);
    束束=新包();
    bundle.putString(MainActivityMemsBT.TOAST_CONNECTION_LOST,设备连接丢失);
    msg.setData(包);
    mHandler.sendMessage(MSG);
    Log.i(连接,connectionlost);

    的setState(STATE_NONE);
    StopAllThreads();

}



市民同步无效StopAllThreads(){

    如果(mConnectThread!= NULL){
        mConnectThread.cancel();
        mConnectThread = NULL;
    }

    如果(mConnectedThread!= NULL){
        mConnectedThread.cancel();
        mConnectedThread = NULL;

    }

的setState(STATE_NONE);

}

市民同步无效连接(的BluetoothSocket插座,BluetoothDevice类设备,最后弦乐socketType){

    //取消线程他们完成了连接
    如果(mConnectThread!= NULL){
        mConnectThread.cancel();
        mConnectThread = NULL;
    }

    //取消任何线程当前正在运行的连接
    如果(mConnectedThread!= NULL){
        mConnectedThread.cancel();
        mConnectedThread = NULL;

    }


    //启动线程来管理连接,并进行传输
    mConnectedThread =新ConnectedThread(插座,socketType);
    mConnectedThread.start();

    //发送连接设备的名称回UI活动
    消息味精= mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_DEVICE_NAME);
    束束=新包();
    bundle.putString(MainActivityMemsBT.DEVICE_NAME,device.getName());
    msg.setData(包);
    mHandler.sendMessage(MSG);

    的setState(STATE_CONNECTED);

}


      公共无效的write(byte []的输出){
//创建临时对象
ConnectedThreadř;

Log.d(TAG,丹斯写+ Integer.toString(mState));

//同步ConnectedThread副本
同步(本){

    如果(handlerCalling == 2)的setState(STATE_CONNECTED);

    如果(mState!= STATE_CONNECTED){
        Log.d(TAG,不同的去STATE_CONNECTED);
        Log.i(TAG,Integer.toString(handlerCalling));
        返回;}

    R = mConnectedThread;
}

r.write(出);

   }
 

任何想法是有解决方法?还是在我的code任何明显的错误

感谢

在尝试与设备的输出连接

  //线程运行。
//运行直通;连接成功或失败。
私有类ConnectThread继承Thread {

    私人最终的BluetoothSocket mmSocket;
    私人最终BluetoothDevice类mmDevice;
    私人字符串mSocketType;

    公共ConnectThread(BluetoothDevice类设备){
        mmDevice =设备;
        的BluetoothSocket TMP = NULL;

        尝试 {
        TMP = device.createRfcommSocketToServiceRecord(STANDARD_UUID);
            // TMP = device.createInsecureRfcommSocketToServiceRecord(STANDARD_UUID);

/*          尝试 {
                方法M = device.getClass()实现getMethod(createRfcommSocket,新的等级[] {} int.class)。
                尝试 {
                    TMP =(的BluetoothSocket)m.invoke(设备,1);
                }赶上(抛出:IllegalArgumentException E){
                    // TODO自动生成的catch块
                    e.printStackTrace();
                }赶上(IllegalAccessException E){
                    // TODO自动生成的catch块
                    e.printStackTrace();
                }赶上(的InvocationTargetException E){
                    // TODO自动生成的catch块
                    e.printStackTrace();
                }
            }赶上(NoSuchMethodException E){
                // TODO自动生成的catch块
                e.printStackTrace();
            } * /

        }赶上(IOException异常E){

        }
        mmSocket = TMP;

    }

    公共无效的run(){

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

        尝试 {
            mmSocket.connect();
        }赶上(IOException异常E){

            尝试 {
                mmSocket.close();
            }赶上(IOException异常E2){
                Log.e(TAG,E2连接失败时插座无法关闭()+ mSocketType +);
            }

        返回;
        }

    //重新设置CoonectThread因为工作结束
    同步(BluetoothMEMSCommunication.this){
        mConnectThread = NULL;
        }

    连接(mmSocket,mmDevice,mSocketType);

    }

    公共无效取消(){
        尝试 {
            mmSocket.close();
        }赶上(IOException异常E){

        }
    }

      //关闭connectThread类
}


     私有类ConnectedThread继承Thread {

私人最终的BluetoothSocket mmSocket;
私人最终的InputStream mmInStream;
私人最终的OutputStream mmOutStream;

公共ConnectedThread(的BluetoothSocket插座,串socketType){

    mmSocket =插座;
    InputStream的tmpIn = NULL;
    OutputStream的tmpOut = NULL;

    尝试 {
        tmpIn = socket.getInputStream();
        tmpOut = socket.getOutputStream();

    }赶上(IOException异常E){
        失去连接();

    }

    mmInStream = tmpIn;
    mmOutStream = tmpOut;

}

//线程听输入插口

公共无效的run(){

    Log.i(TAG,开始mConnectedThread);

    byte []的缓冲区=新的字节[1024];
// INT字节;
    INT读取动作= -1;
    字符串消息=;

    //继续听InputStream的同时连接
    而(真){


            尝试 {

                //从输入流中读取
            //读取动作= mmInStream.read(缓冲液);
        //消息=信息+新的String(缓冲,0,读取动作);

            // byte []的字节字符串= message.getBytes();

                Log.i(信息,preT一个自由放任读);
                读取动作= mmInStream.read(缓冲液,0,1024);

                如果(!读取动作= -1&安培;&安培; handlerCalling == 1){
                mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_READ,读取动作,-1,缓冲液).sendToTarget(); }

                如果(读取动作=  -  1安培;!&安培; handlerCalling == 2){
                    mHandler.obtainMessage(DemoAccelerometer.MESSAGE_READ,读取动作,-1,缓冲液).sendToTarget(); }

                }

             赶上(IOException异常E){

                 失去连接();
                打破;
            }


            }

        }


公共无效的write(byte []的缓冲区){

    尝试{
        mmOutStream.write(缓冲液);

//如果(handlerCalling == 1){
// mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_WRITE,-1,-1,缓冲液).sendToTarget();
        Log.d(TAG,envoi流);

    // mmOutStream.flush();
//}

    }赶上(IOException异常E){

    }

}

公共无效取消(){
    尝试{
        mmSocket.close();
    }赶上(IOException异常E){

    }
}

   }

    }
 

解决方案

升级的安卓4.2到4.3后,从我们的Nexus 4的应用程序到外部蓝牙心电图(医疗设备)进行通信时,我们可以确认6秒后的蓝牙断开。这会发生特别心电图测量大量入站数据(从心电图的Andr​​oid应用程序),但没有出站数据中。似乎与不时有些入站和出站数据正常蓝牙通信不会受到影响。

经过6秒我们看到报道由朱镇模同亚行日志信息

  dm_pm_timer到期
dm_pm_timer期满0
PROC dm_pm_timer到期
btm_sec_disconnected  - 清除标志位
 

这对Android侧计时器到期触发的东西(关闭输出流,因为没有出站数据?)外部蓝牙心电图从而将心电图特定的命令,我们收到的,我们从来没有收到关于Nexus的4输入流安卓4.2。

更改Android应用程序执行偶尔发送任意的保持命令心电图解决问题。计时器到期未出现在亚行日志中再和心电图测量现在的行为一样采用Android 4.2。

感谢朱镇模的提示。

I wrote a simple application based on bluetoothChat. I communicate between the phone and a bluetooth module using SPP profile. The phone always initiates the communication. The application worked pefectly on Android 4.2, using Nexus 3 and Samsung Galaxy 3. After the update to Android 4.3, the application does not work anymore. I connect all the time, I can send an outpustream and receive the right data, but after the 1st outputstream command, the application always disconnected after around 6s. As shown in the logcat below, it looks there is a timer issue on the inputstream.

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

What is dm_pm_timer? I tried to connect a different way, with secure and insecure rfcom. I know the bluetooth chat is not optimized to receive the buffer, so I modified it, not no effect. I used the flush command for the outpustream too, but no effect either.

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);

   }

Any idea is there is a workaround? Or any obvious mistake in my code

Thanks

// 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) {

    }
}

   }

    }

解决方案

We can confirm the Bluetooth disconnect after 6 seconds when communicating from our Nexus 4 app to an external Bluetooth ECG (medical device) after upgrading from Android 4.2 to 4.3. This happens specifically during an ECG measurement with lots of inbound data (from ECG to the Android app) but no outbound data. "Normal" Bluetooth communication with some inbound and outbound data from time to time does not seem to be affected.

After 6 seconds we see the same adb log messages reported by JJM

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

This timer expiry on the Android side triggers something (closing output stream because no outbound data?) on the external Bluetooth ECG which in turn sends an ECG specific command we receive on the input stream that we never receive on the Nexus 4 with Android 4.2.

Changing the Android app implementation to occasionally send an arbitrary "keep alive" command to the ECG solves the problem. The timer expiry does not appear in the adb logs anymore and the ECG measurement now behaves the same as with Android 4.2.

Thanks to JJM for the hints.

这篇关于使用蓝牙SPP配置文件无法正常工作更新后从安卓4.2应用到Android 4.3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆