通过蓝牙将文本从 Java Server 发送到 Android 客户端

2022-09-01 19:35:22

首先。。。不要将我重定向到蓝牙聊天,我已经完全阅读了它。

我有一个Android客户端,它可以正确建立与服务器的连接,并且我最多可以将文本发送到PC中的服务器并正确显示它,但是我无法执行相反的操作,从服务器向客户端发送一个简单的字符串并将其显示在我的Android应用程序中。

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

为了方便起见:

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

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

**

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

**.

代码如下:

安卓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();

    }
}

解决方案:这只是服务器端的一个小变化。我不知道为什么,但是我们需要使用PrinterWriter来执行此操作,而不是使用BufferedWrite在套接字中写入。我添加了修改的那段代码:

蓝牙服务器:

    ....
    //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.flush()bWriter.write()

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

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

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


答案 2

推荐