将蓝牙 Android 客户端连接到蓝牙 Java 服务器

Connect Bluetooth Android Client to Bluetooth Java Server

我一直在关注这两个帖子 SPP Server and Client and this Whosebug post。我在 Linux VM 上安装了服务器 运行ning,在 Samsung Galaxy S6 上安装了 Android 应用程序 运行ning。当我 运行 Intellij 中的服务器代码时,它说:

"Server Started. Waiting for clients to connect".

当我 运行 Android 应用程序时,我收到以下警告框:

"Fatal Error. In OnResume()and an exception occurred during write: socket closed. Check that the SPP UUID: 00001101-0000-1000-8000-00805F9B34FB exists on server. Press OK to exit.

为什么会发生这种情况以及如何解决它以便服务器连接并从 Android 应用程序接收字符串?

SPP 服务器代码:

import java.io.BufferedReader;
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.*;


public class SampleSPPServer {

    //start server
    private void startServer() throws IOException{

        //Create a UUID for SPP
        UUID uuid = new UUID("0000110100001000800000805F9B34FB", false);
        //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();
        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());

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

    }
}

Android 客户代码:

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.UUID;

public class BluetoothClient extends AppCompatActivity {

    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.activity_bluetooth_client);

        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 DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface arg0, int arg1) {
                        finish();
                    }
                }).show();
    }
}

Android工作室Logcat:

android.view.WindowLeaked: Activity         com.example.toby.btclientapp.BluetoothClient has leaked window     com.android.internal.policy.PhoneWindow$DecorView{b73d40d V.E......     R.....I. 0,0-1368,1249} that was originally added here
                                                at     android.view.ViewRootImpl.<init>(ViewRootImpl.java:569)
                                                at     android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:326)
                                                at     android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
                                                at android.app.Dialog.show(Dialog.java:350)
                                                at android.support.v7.app.AlertDialog$Builder.show(AlertDialog.java:955)
                                                at com.example.toby.btclientapp.BluetoothClient.AlertBox(BluetoothClient.java:181)
                                                at com.example.toby.btclientapp.BluetoothClient.onResume(BluetoothClient.java:107)
                                                at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1286)
                                                at android.app.Activity.performResume(Activity.java:6987)
                                                at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4145)
                                                at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4250)
                                                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3361)
                                                at android.app.ActivityThread.access00(ActivityThread.java:222)
                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795)
                                                at android.os.Handler.dispatchMessage(Handler.java:102)
                                                at android.os.Looper.loop(Looper.java:158)
                                                at android.app.ActivityThread.main(ActivityThread.java:7229)
                                                at java.lang.reflect.Method.invoke(Native Method)
                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
07-26 13:09:21.574 3857-3857/? E/WindowManager: android.view.WindowLeaked: Activity com.example.toby.btclientapp.BluetoothClient has leaked window com.android.internal.policy.PhoneWindow$DecorView{9723488 V.E...... R....... 0,0-1368,1249} that was originally added here
                                                at android.view.ViewRootImpl.<init>(ViewRootImpl.java:569)
                                                at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:326)
                                                at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
                                                at android.app.Dialog.show(Dialog.java:350)
                                                at android.support.v7.app.AlertDialog$Builder.show(AlertDialog.java:955)
                                                at com.example.toby.btclientapp.BluetoothClient.AlertBox(BluetoothClient.java:181)
                                                at com.example.toby.btclientapp.BluetoothClient.onResume(BluetoothClient.java:107)
                                                at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1286)
                                                at android.app.Activity.performResume(Activity.java:6987)
                                                at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4145)
                                                at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4250)
                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1839)
                                                at android.os.Handler.dispatchMessage(Handler.java:102)
                                                at android.os.Looper.loop(Looper.java:158)
                                                at android.app.ActivityThread.main(ActivityThread.java:7229)
                                                at java.lang.reflect.Method.invoke(Native Method)
                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
07-26 13:09:21.574 3857-3857/? E/WindowManager: android.view.WindowLeaked: Activity com.example.toby.btclientapp.BluetoothClient has leaked window com.android.internal.policy.PhoneWindow$DecorView{cea821b V.E...... R....... 0,0-1368,799} that was originally added here
                                                at android.view.ViewRootImpl.<init>(ViewRootImpl.java:569)
                                                at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:326)
                                                at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
                                                at android.app.Dialog.show(Dialog.java:350)
                                                at android.support.v7.app.AlertDialog$Builder.show(AlertDialog.java:955)
                                                at com.example.toby.btclientapp.BluetoothClient.AlertBox(BluetoothClient.java:181)
                                                at com.example.toby.btclientapp.BluetoothClient.onPause(BluetoothClient.java:135)
                                                at android.app.Activity.performPause(Activity.java:7033)
                                                at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1339)
                                                at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4577)
                                                at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4550)
                                                at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4525)
                                                at android.app.ActivityThread.access00(ActivityThread.java:222)
                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1813)
                                                at android.os.Handler.dispatchMessage(Handler.java:102)
                                                at android.os.Looper.loop(Looper.java:158)
                                                at android.app.ActivityThread.main(ActivityThread.java:7229)
                                                at java.lang.reflect.Method.invoke(Native Method)
                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

我需要更改蓝牙适配器的 MAC 地址。现在可以使用了。