简体   繁体   English

Android蓝牙读取InputStream

[英]Android Bluetooth Read InputStream

I'm trying to read serial data sent from an external bluetooth module to my HTC Sensation but when I call InputStream.available() - it returns 0 so I can't iterate over the bytes recieved and call InputStream.read(byteArray). 我正在尝试读取从外部蓝牙模块发送到我的HTC Sensation的串行数据,但是当我调用InputStream.available()时 - 它返回0,所以我不能迭代收到的字节并调用InputStream.read(byteArray)。

Could somebody help me solve this problem? 有人可以帮我解决这个问题吗?

Do I need to check for available bytes before reading them? 在阅读之前我需要检查可用字节吗?

I apologise for my technically inacurrate post. 我为技术上不准确的帖子道歉。

Here's my code: 这是我的代码:

public class BluetoothTest extends Activity
{
TextView myLabel;
TextView snapText;
EditText myTextbox;
BluetoothAdapter mBluetoothAdapter;
BluetoothSocket mmSocket;
BluetoothDevice mmDevice;
OutputStream mmOutputStream;
InputStream mmInputStream;
Thread workerThread;
byte[] readBuffer;
int readBufferPosition;
int counter;
volatile boolean stopWorker;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Button openButton = (Button)findViewById(R.id.open);
    Button closeButton = (Button)findViewById(R.id.close);

    Button chkCommsButton  = (Button)findViewById(R.id.chkCommsButton);
    Button offButton = (Button)findViewById(R.id.offButton);

    myLabel = (TextView)findViewById(R.id.mylabel);
    snapText = (TextView)findViewById(R.id.snapText);


    //Open Bluetooth
    openButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {
            try 
            {
                findBT();
                openBT();
            }
            catch (IOException ex) { }
        }
    });

    //Close Bluetooth
    closeButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {
            try 
            {
                closeBT();
            }
            catch (IOException ex) { }
        }
    });


    // Check Comms     - multicast all SNAP nodes and pulse their  BLUE led
     chkCommsButton.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            try {
                chkcommsButton();
            } catch (Exception e) {
                // TODO: handle exception
            }

        }
    });

  //Off Button    - set strip to all OFF
    offButton.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            try {
                offButton();
            } catch (Exception e) {
                // TODO: handle exception
            }

        }
    });


}


void findBT()
{
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if(mBluetoothAdapter == null)
    {
        myLabel.setText("No bluetooth adapter available");
    }

    if(!mBluetoothAdapter.isEnabled())
    {
        Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBluetooth, 0);
    }

    Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
    if(pairedDevices.size() > 0)
    {
        for(BluetoothDevice device : pairedDevices)
        {
            if(device.getName().equals("BTNODE25"))    // Change to match RN42 - node name
            {
                mmDevice = device;
                Log.d("ArduinoBT", "findBT found device named " + mmDevice.getName());
                Log.d("ArduinoBT", "device address is " + mmDevice.getAddress());
                break;
            }
        }
    }
    myLabel.setText("Bluetooth Device Found");
}

void openBT() throws IOException
{
    UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard SerialPortService ID
    mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);        
    mmSocket.connect();
    mmOutputStream = mmSocket.getOutputStream();
    mmInputStream = mmSocket.getInputStream();

    beginListenForData();

    myLabel.setText("BT  << " + mmDevice.getName()  + " >> is now open ");
}

void closeBT() throws IOException
{
    stopWorker = true;
    mmOutputStream.close();
    mmInputStream.close();
    mmSocket.close();
    myLabel.setText("Bluetooth Closed");
}

void beginListenForData()
{
    final Handler handler = new Handler(); 
    final byte delimiter = 10; //This is the ASCII code for a newline character

    stopWorker = false;
    readBufferPosition = 0;
    readBuffer = new byte[1024];
    workerThread = new Thread(new Runnable()
    {
        public void run()
        {                
           while(!Thread.currentThread().isInterrupted() && !stopWorker)
           {
                try 
                {

                    int bytesAvailable = mmInputStream.available();  
                    if(bytesAvailable > 0)
                    {
                        byte[] packetBytes = new byte[bytesAvailable];
                        mmInputStream.read(packetBytes);
                        for(int i=0;i<bytesAvailable;i++)
                        {
                            byte b = packetBytes[i];
                            if(b == delimiter)
                            {
                                byte[] encodedBytes = new byte[readBufferPosition];
                                System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
                                final String data = new String(encodedBytes, "US-ASCII");
                                readBufferPosition = 0;

                                handler.post(new Runnable()
                                {
                                    public void run()
                                     {
                                        snapText.setText(data);
                                     }
                                });
                            }
                            else
                            {
                                readBuffer[readBufferPosition++] = b;
                            }
                        }
                    }
                } 
                catch (IOException ex) 
                {
                    stopWorker = true;
                }
           }
        }
    });

    workerThread.start();
}


  void offButton() throws IOException
{
    mmOutputStream.write("0".getBytes());
}


void chkcommsButton() throws IOException
{
    mmOutputStream.write("1".getBytes());
}

} }

the InputStream.read() method is blocking, that means it will block your code until some data arrive, OR something break the pipe (like a disconnection of the host or closing the stream). InputStream.read()方法是阻塞的,这意味着它会阻塞你的代码,直到一些数据到达,或者某些东西破坏管道(如断开主机或关闭流)。 Blocking is CPU friendly, as the thread is put on the WAIT state (sleep) until an interrupt put it in the READY state, so it will be scheduled to be run on the CPU; 阻塞是CPU友好的,因为线程处于WAIT状态(休眠),直到中断使其处于READY状态,因此它将被安排在CPU上运行; so you WONT use cpu while waiting for data, and this mean you'll use less battery (or that you leave that CPU time to others thread)! 所以你在等待数据时WONT使用cpu,这意味着你将使用更少的电池(或者你将CPU时间留给其他人的线程)!

available() gives the actual available data, and because Serial communication is really slow (115200 Baud at 8n1 means 11520 byte/second) and your loop run at least one or two order of magnitude faster, you will read a lot of 0, and using A LOT of cpu to ask for that zero... that means you use a lot of battery. available()给出了实际可用的数据,并且因为串行通信非常慢(11n00波特在8n1意味着11520字节/秒)并且你的循环运行速度至少快一到两个数量级,你会读到很多0,并且使用大量的cpu来要求零......这意味着你要使用大量的电池。

looping on available is not a problem on the arduino, as you have only one thread/process: your code. 循环可用在arduino上不是问题,因为你只有一个线程/进程:你的代码。 BUT in a multi-thread system looping to check for data (that's called "polling") is ALWAYS a bad idea, and should be done only if you have no other choice, and always add a little sleep() so your code won't steal CPU to system and other thread. 但是在多线程系统中循环检查数据(称为“轮询”)总是一个坏主意,并且只有在你没有其他选择时才应该完成,并且总是添加一点sleep()以便你的代码赢得' t窃取CPU到系统和其他线程。 Good idea is to use blocking call (easy to use for beginner) or an event system like you do for graphics event (not always supported by the library you use, and need synchronization, so it's tricky but you don't spawn other thread in your own code, but remember that data from serial and graphics and your application PROBABLY are in different thread, and should be synchronized) 好主意是使用阻塞调用(对于初学者来说很容易使用)或者像你对图形事件那样使用事件系统(并不总是被你使用的库支持,并且需要同步,所以它很棘手,但你不会产生其他线程你自己的代码,但请记住,串行和图形的数据和你的应用程序PROBABLY在不同的线程中,应该同步)

You are using 您正在使用

import java.util.logging.Handler;

Change it to 将其更改为

import android.os.Handler;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果不使用,则在蓝牙套接字上读取的输入流会挂起 - Inputstream read on bluetooth socket hangs if not used 如何在Android中通过蓝牙处理InputStream和OutputStream - How to handle InputStream and OutputStream via Bluetooth in Android 将蓝牙输入流转换为图像,java android app - Conversion Bluetooth inputstream to an image, java android app 蓝牙 InputStream.read() 不会永远返回数据和块 - Bluetooth InputStream.read() doesn't return Data and Blocks forever 使用InputStream.read()后蓝牙传输应用程序停止,没有错误 - Bluetooth transfer App stops after using InputStream.read() with no error Android - Arduino 蓝牙通信:应用程序停止读取输入流 - Android - Arduino Bluetooth communication: app stops reading inputstream 如何在 Kivy 中将 android.bluetooth.socket 输入流转换为 python 字符串? - how to convert android.bluetooth.socket inputstream to python string in Kivy? 对于Android平台上的蓝牙套接字,无法使用InputStream创建ObjectInputStream - Cannot create ObjectInputStream with InputStream for a Bluetooth Socket on the Android Platform Android Bluetooth定期调用inputStream和outputStream:时间戳不一致 - Android Bluetooth periodic calls to inputStream and outputStream: inconsistent timestamps 使用库将输入流读入android中的数组 - Using libraries to read inputstream into arrays in android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM