从 Android 4.2 更新到 Android 4.3 后,使用蓝牙 SPP 配置文件的应用程序不起作用 [英] Application using bluetooth SPP profile not working after update from Android 4.2 to Android 4.3

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

问题描述

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

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

什么是 dm_pm_timer?我尝试以不同的方式连接安全和不安全的 rfcom.我知道蓝牙聊天没有优化接收缓冲区,所以我修改了它,不是没有效果.我也对输出流使用了刷新命令,但也没有效果.

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

谢谢

// 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 应用程序通信到外部蓝牙心电图(医疗设备)时,在 6 秒后确认蓝牙断开连接.这特别发生在具有大量入站数据(从 ECG 到 Android 应用程序)但没有出站数据的 ECG 测量期间.正常"的蓝牙通信与一些不时的入站和出站数据似乎不受影响.

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.

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

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

Android 端的此计时器到期会触发外部蓝牙心电图上的某些内容(因为没有出站数据而关闭输出流?)安卓 4.2.

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.

更改 Android 应用实现以偶尔向 ECG 发送任意保持活动"命令可解决此问题.计时器到期不再出现在 adb 日志中,心电图测量现在的行为与 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.

感谢 JJM 的提示.

Thanks to JJM for the hints.

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

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