通过蓝牙从 Java 服务器向 Android 客户端发送文本

Posted

技术标签:

【中文标题】通过蓝牙从 Java 服务器向 Android 客户端发送文本【英文标题】:Send text through Bluetooth from Java Server to Android Client 【发布时间】:2012-06-11 09:17:00 【问题描述】:

首先...不要将我重定向到蓝牙聊天,我已完整阅读。

我有一个 android 客户端,它可以正确地与服务器建立连接,最重要的是我可以在我的电脑中向服务器发送文本并正确显示,但我不能做相反的动作,发送一个简单的字符串服务器到客户端并将其显示在我的 android 应用程序中。

我不想实现聊天只是为了展示 BT 通信如何在 Java 服务器和 Android 客户端之间工作。

为了方便:

我在服务器类的 startServer() 方法末尾发送文本。

我尝试在 onPause() 开始时从服务器读取文本。

**

[已解决]下面的解决方案

**.

代码如下:

Android BT 客户端:

/*...libraries here...*/
  public class ConnectTest extends Activity 
  TextView out;
  private static final int REQUEST_ENABLE_BT = 1;
  private BluetoothAdapter btAdapter = null;
  private BluetoothSocket btSocket = null;
  private OutputStream outStream = null;

  // Well known SPP UUID
  private static final UUID MY_UUID =
      UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

  // Insert your server's MAC address
  private static String address = "00:10:60:AA:B9:B2";

  /** Called when the activity is first created. */
  public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    out = (TextView) findViewById(R.id.out);

    out.append("\n...In onCreate()...");

    btAdapter = BluetoothAdapter.getDefaultAdapter();
    CheckBTState();
  

  public void onStart() 
    super.onStart();
    out.append("\n...In onStart()...");
  

  public void onResume() 
    super.onResume();

    out.append("\n...In onResume...\n...Attempting client connect...");

    // Set up a pointer to the remote node using it's address.
    BluetoothDevice device = btAdapter.getRemoteDevice(address);

    // Two things are needed to make a connection:
    //   A MAC address, which we got above.
    //   A Service ID or UUID.  In this case we are using the
    //     UUID for SPP.
    try 
      btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
     catch (IOException e) 
      AlertBox("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
    

    // Discovery is resource intensive.  Make sure it isn't going on
    // when you attempt to connect and pass your message.
    btAdapter.cancelDiscovery();

    // Establish the connection.  This will block until it connects.
    try 
      btSocket.connect();
      out.append("\n...Connection established and data link opened...");
     catch (IOException e) 
      try 
        btSocket.close();
       catch (IOException e2) 
        AlertBox("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
      
    

    // Create a data stream so we can talk to server.
    out.append("\n...Sending message to server...");
    String message = "Hello from Android.\n";
    out.append("\n\n...The message that we will send to the server is: "+message);

    try 
      outStream = btSocket.getOutputStream();
     catch (IOException e) 
      AlertBox("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + ".");
    

    byte[] msgBuffer = message.getBytes();
    try 
      outStream.write(msgBuffer);
     catch (IOException e) 
      String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
      if (address.equals("00:00:00:00:00:00")) 
        msg = msg + ".\n\nUpdate your server address from 00:00:00:00:00:00 to the correct address on line 37 in the java code";
      msg = msg +  ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";

      AlertBox("Fatal Error", msg);       
    
  

  public void onPause() 
    super.onPause();

    //out.append("\n...Hello\n");
    InputStream inStream;
    try 
        inStream = btSocket.getInputStream();
        BufferedReader bReader=new BufferedReader(new InputStreamReader(inStream));
        String lineRead=bReader.readLine();
        out.append("\n..."+lineRead+"\n");

     catch (IOException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    

    out.append("\n...In onPause()...");



    if (outStream != null) 
      try 
        outStream.flush();
       catch (IOException e) 
        AlertBox("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
      
    

    try     
      btSocket.close();
     catch (IOException e2) 
      AlertBox("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
    
  

  public void onStop() 
    super.onStop();
    out.append("\n...In onStop()...");
  

  public void onDestroy() 
    super.onDestroy();
    out.append("\n...In onDestroy()...");
  

  private void CheckBTState() 
    // Check for Bluetooth support and then check to make sure it is turned on

    // Emulator doesn't support Bluetooth and will return null
    if(btAdapter==null)  
      AlertBox("Fatal Error", "Bluetooth Not supported. Aborting.");
     else 
      if (btAdapter.isEnabled()) 
        out.append("\n...Bluetooth is enabled...");
       else 
        //Prompt user to turn on Bluetooth
        Intent enableBtIntent = new Intent(btAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
      
    
  

  public void AlertBox( String title, String message )
    new AlertDialog.Builder(this)
    .setTitle( title )
    .setMessage( message + " Press OK to exit." )
    .setPositiveButton("OK", new OnClickListener() 
        public void onClick(DialogInterface arg0, int arg1) 
          finish();
        
    ).show();
  

和 Java BT 服务器:

    import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import javax.bluetooth.*;
import javax.microedition.io.*;

/**
* Class that implements an SPP Server which accepts single line of
* message from an SPP client and sends a single line of response to the client.
*/
public class SimpleSPPServer 

    //start server
    private void startServer() throws IOException

        //Create a UUID for SPP
        UUID uuid = new UUID("1101", true);
        //Create the servicve url
        String connectionString = "btspp://localhost:" + uuid +";name=Sample SPP Server";

        //open server url
        StreamConnectionNotifier streamConnNotifier = (StreamConnectionNotifier)Connector.open( connectionString );

        //Wait for client connection
        System.out.println("\nServer Started. Waiting for clients to connect...");
        StreamConnection connection=streamConnNotifier.acceptAndOpen();

        RemoteDevice dev = RemoteDevice.getRemoteDevice(connection);
        System.out.println("Remote device address: "+dev.getBluetoothAddress());
        System.out.println("Remote device name: "+dev.getFriendlyName(true));

        //read string from spp client
        InputStream inStream=connection.openInputStream();
        BufferedReader bReader=new BufferedReader(new InputStreamReader(inStream));
        String lineRead=bReader.readLine();
        System.out.println(lineRead);

        //send response to spp client
        OutputStream outStream=connection.openOutputStream();
        BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter(outStream));
        bWriter.write("Response String from SPP Server\r\n");

        /*PrintWriter pWriter=new PrintWriter(new OutputStreamWriter(outStream));
        pWriter.write("Response String from SPP Server\r\n");
        pWriter.flush();
        pWriter.close();*/

        streamConnNotifier.close();

    


    public static void main(String[] args) throws IOException 

        //display local device address and name
        LocalDevice localDevice = LocalDevice.getLocalDevice();
        System.out.println("Address: "+localDevice.getBluetoothAddress());
        System.out.println("Name: "+localDevice.getFriendlyName());

        SimpleSPPServer sampleSPPServer=new SimpleSPPServer();
        sampleSPPServer.startServer();

    

解决方案: 这只是服务器端的一个小改动。 我不知道为什么,但不是使用 BufferedWrite 在套接字中写入,我们需要使用 PrinterWriter 这样做。我添加了那段修改过的代码:

BT 服务器:

    ....
    //read string from spp client
    InputStream inStream=connection.openInputStream();
    BufferedReader bReader=new BufferedReader(new InputStreamReader(inStream));
    String lineRead=bReader.readLine();
    System.out.println(lineRead);

    //send response to spp client
    OutputStream outStream=connection.openOutputStream();
    PrintWriter pWriter=new PrintWriter(new OutputStreamWriter(outStream));
    pWriter.write("Response String from SPP Server\r\n");
    pWriter.flush();

    pWriter.close();

    streamConnNotifier.close();
    ...

【问题讨论】:

【参考方案1】:

看起来您的 BufferedWriter 缓存没有被刷新,数据只是保留在缓冲区中而没有被发送。在bWriter.write() 之后调用bWriter.flush() 应该可以解决问题并导致数据被刷新到输出流。您还可以考虑更改代码以遵循以下原则:

PrintWriter pWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outStream)));

这将导致 PrintWriter 输出被缓冲,而不是立即写入输出流,这可能是低效的。

不过,出于您的目的,省略 BufferedWriter 应该没问题,因为您很可能希望立即刷新到输出流(PrintWriter 会这样做)。

【讨论】:

以上是关于通过蓝牙从 Java 服务器向 Android 客户端发送文本的主要内容,如果未能解决你的问题,请参考以下文章

向远程蓝牙设备发送数据

如何在后台的两个 android 活动之间交换数据以通过蓝牙发送数据?

无法连接到android上的蓝牙套接字

通过蓝牙将数据从Arduino发送到Java程序

Android 5.0+ 在通知区域向用户隐藏“蓝牙配对请求”

Android 蓝牙服务器客户端应用程序