Java Android 蓝牙读取 InputStream
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22846076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android Bluetooth Read InputStream
提问by
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());
}
}
}
采纳答案by Lesto
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).
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; 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)!
该InputStream.read()
方法是阻塞的,这意味着它会阻塞你的代码,直到一些数据到达,或者某些东西破坏了管道(比如主机断开连接或关闭流)。阻塞是 CPU 友好的,因为线程被置于 WAIT 状态(睡眠),直到中断将其置于 READY 状态,因此它将被安排在 CPU 上运行;所以你不会在等待数据时使用 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()
给出了实际可用的数据,因为串行通信真的很慢(8n1 下的 115200 波特意味着 11520 字节/秒)并且您的循环运行速度至少快了一两个数量级,您将读取很多 0,并且使用了很多cpu 要求零...这意味着您使用了大量电池。
looping on available is not a problem on the arduino, as you have only one thread/process: your code. 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. 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)
在 arduino 上循环可用不是问题,因为您只有一个线程/进程:您的代码。但是在多线程系统中循环检查数据(称为“轮询”)总是一个坏主意,只有在您别无选择时才应该这样做,并且总是添加一点 sleep() 以便您的代码不会' t 窃取 CPU 给系统和其他线程。好主意是使用阻塞调用(初学者易于使用)或像您为图形事件所做的那样的事件系统(您使用的库并不总是支持,并且需要同步,所以这很棘手,但您不会在其中产生其他线程您自己的代码,但请记住来自串行和图形的数据以及您的应用程序可能位于不同的线程中,并且应该同步)
回答by shruti
You are using
您正在使用
import java.util.logging.Handler;
Change it to
将其更改为
import android.os.Handler;