如何在 Android 上从蓝牙的 InputStream 中读取

Posted

技术标签:

【中文标题】如何在 Android 上从蓝牙的 InputStream 中读取【英文标题】:how to read from the InputStream of a bluetooth on Android 【发布时间】:2014-10-16 02:07:03 【问题描述】:

我正在尝试测试this bluetooth communication example between a PC and an android phone。我的 SPP 客户正是那里的客户,它工作正常。我是 Android 新手,我不想让它在单独的线程中运行,因为我不知道怎么做,所以我只是在 onCreate() 方法中做了所有事情。如果这不是最好的方法,请随时为我指出更好的方法,但这不是我的主要问题。

问题是我想在textView 上显示通过蓝牙接收的文本,但我不知道如何从InputStream 读取。当代码保持这样时,它会显示类似java.io.DataInputStream@41b0cb68 我像here一样尝试了它没有显示任何内容,我也不知道使用的是什么编码。

这是我的安卓应用程序代码:

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.app.Activity;
import android.bluetooth.*;
import android.util.Log;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends Activity 

//based on java.util.UUID
private static UUID MY_UUID = UUID.fromString("446118f0-8b1e-11e2-9e96-0800200c9a66");

// The local server socket
private BluetoothServerSocket mmServerSocket;

// based on android.bluetooth.BluetoothAdapter
private BluetoothAdapter mAdapter;
private BluetoothDevice remoteDevice;
TextView text;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    text = (TextView) findViewById(R.id.textView_Text);

    BluetoothSocket socket = null;
    mAdapter = BluetoothAdapter.getDefaultAdapter();        

    // Listen to the server socket if we're not connected
   // while (true) 

        try 
            // Create a new listening server socket
            Log.d((String) this.getTitle(), ".....Initializing RFCOMM SERVER....");

            // MY_UUID is the UUID you want to use for communication
            mmServerSocket = mAdapter.listenUsingRfcommWithServiceRecord("MyService",    MY_UUID);
            //mmServerSocket =  mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID); // you can also try  using In Secure connection...

            // This is a blocking call and will only return on a
            // successful connection or an exception
            socket = mmServerSocket.accept();

         catch (Exception e) 

        

        try 
            Log.d((String) this.getTitle(), "Closing Server Socket.....");
            mmServerSocket.close();

            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams

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

            DataInputStream mmInStream = new DataInputStream(tmpIn);
            DataOutputStream mmOutStream = new DataOutputStream(tmpOut);

            // here you can use the Input Stream to take the string from the client  whoever is connecting
            //similarly use the output stream to send the data to the client


            text.setText(mmInStream.toString());
         catch (Exception e) 
            //catch your exception here
        
   // 


我注释掉了 while(true) 循环,因为我认为它在调用 onPause() 时使我的应用程序崩溃。我知道这不是最好的实现,但我真的很想从蓝牙读取我觉得我很接近:),其他方面将在之后处理(如使用线程等)。

【问题讨论】:

Reading data from bluetooth device in android的可能重复 【参考方案1】:

基本上,您需要匹配从一台设备发送数据的方式与另一台设备接收数据的方式。

SPP 基于流并传输数据字节。因此,发送设备传输的任何字节都必须被接收方正确解释。

InputStream 可让您访问传输的原始字节,您必须对它们进行处理;即根据需要以某种方式对它们进行解码。例如,如果发送方在传输之前使用ObjectOutputStream 进行编码,则接收方将不得不使用ObjectInputStream 对输入进行解码。

您可能需要阅读InputStream (read())、ObjectInputStreamtoString()

此外,从阻塞流中读取几乎应该总是在单独的线程中完成;尤其是当从某些远程设备/主机/网络/...读取可能存在未知延迟或传输速度时。

【讨论】:

【参考方案2】:

我终于成功地在TextView 中正确显示了从 PC 发送的字符串(“来自 SPP 客户端的测试字符串\r\n”)。

我用了this question,也就是这段代码,就在DataOutputStream mmOutStream = new DataOutputStream(tmpOut);下面:

// Read from the InputStream
            bytes = mmInStream.read(buffer);
            String readMessage = new String(buffer, 0, bytes);
            // Send the obtained bytes to the UI Activity

这是一个非常基本的示例,仅用于展示如何在设备屏幕上显示通过蓝牙接收的字符串。它不是在单独的线程中完成的,在它收到字符串后,您必须关闭应用程序并再次重新启动它,但应用程序的主要目的已经实现(正如我在问这个问题时所说的那样)。我真正非常想要的是从 PC 接收字符串并将其显示在屏幕上。

这是我完整的MainActivity,如果有人希望我发布更完整的方法(例如使用单独的线程),我将在完成后将其发布在这里。

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.app.Activity;
import android.bluetooth.*;
import android.util.Log;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends Activity 

//based on java.util.UUID
private static UUID MY_UUID = UUID.fromString("446118f0-8b1e-11e2-9e96-0800200c9a66");

// The local server socket
private BluetoothServerSocket mmServerSocket;

// based on android.bluetooth.BluetoothAdapter
private BluetoothAdapter mAdapter;
private BluetoothDevice remoteDevice;
TextView text;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    text = (TextView) findViewById(R.id.textView_Text);

    BluetoothSocket socket = null;
    mAdapter = BluetoothAdapter.getDefaultAdapter();        

    // Listen to the server socket if we're not connected
   // while (true) 

        try 
            // Create a new listening server socket
            Log.d((String) this.getTitle(), ".....Initializing RFCOMM SERVER....");

            // MY_UUID is the UUID you want to use for communication
            mmServerSocket = mAdapter.listenUsingRfcommWithServiceRecord("MyService",    MY_UUID);
            //mmServerSocket =  mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID); // you can also try  using In Secure connection...

            // This is a blocking call and will only return on a
            // successful connection or an exception
            socket = mmServerSocket.accept();

         catch (Exception e) 

        

        byte[] buffer = new byte[256];  // buffer store for the stream
        int bytes; // bytes returned from read()
        try 
            Log.d((String) this.getTitle(), "Closing Server Socket.....");
            mmServerSocket.close();

            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams

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

            DataInputStream mmInStream = new DataInputStream(tmpIn);
            DataOutputStream mmOutStream = new DataOutputStream(tmpOut);            
            // here you can use the Input Stream to take the string from the client  whoever is connecting
            //similarly use the output stream to send the data to the client

         // Read from the InputStream
            bytes = mmInStream.read(buffer);
            String readMessage = new String(buffer, 0, bytes);
            // Send the obtained bytes to the UI Activity


            text.setText(readMessage);
         catch (Exception e) 
            //catch your exception here
        
   // 


有什么问题吗? :)

【讨论】:

以上是关于如何在 Android 上从蓝牙的 InputStream 中读取的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 上从 JWT 收集签名、标头和正文

如何在 android 5.1 上从接收器播放音乐,它与 android 4.2 不同

如何在设备上从 github 测试构建的 android 应用程序?

如何直接在 android 上从扬声器播放声音 instaed Headset?

如何在 Ubuntu 服务器上从 Shell 运行 Android 模拟器

如何使用Android蓝牙开发