Android通过蓝牙发送数据到Windows PC电脑:Java实现

Android通过蓝牙发送数据到Windows PC电脑:Java实现Android手机设备之间通过蓝牙连接然后发送数据,这在我之前的蓝牙专栏里面有介绍,详情见专栏:https://blog.csdn.net/column/details/17325.html但是通常还有一...

Android通过蓝牙发送数据到Windows PC电脑:Java实现

Android手机设备之间通过蓝牙连接然后发送数据,这在我之前的蓝牙专栏里面有介绍,详情见专栏:https://blog.csdn.net/column/details/17325.html
但是通常还有一种功能需求是Android手机如何通过蓝牙把数据传输到Windows PC上呢?这在需求还很常见,比如用户通过Android手机拍照,然后像把照片传到电脑上,或者反之,电脑上的文件资料打算通过蓝牙传到手机上。
现在就实现这种功能。在编程模型上,这里把电脑设计成服务器端,用Java实现一个Windows电脑上的蓝牙服务器,名为:BluetoothJavaServer。
Java SE本身并没有实现蓝牙功能模块,如果在Windows通过Java实现蓝牙功能,需要额外的导入两个jar(64位):
1,bluecove-2.1.1-SNAPSHOT.jar
  下载:http://snapshot.bluecove.org/distribution/download/2.1.1-SNAPSHOT/2.1.1-SNAPSHOT.63/
  
  2,commons-io-2.6.jar
  下载:http://commons.apache.org/proper/commons-io/download_io.cgi
 
部署在Windows PC电脑上的蓝牙服务器端代码BluetoothJavaServer.java:

import java.io.InputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;

/**
 * 蓝牙的服务器端。部署在Windows操作系统(PC电脑上)。 等待手机客户端或者其他蓝牙设备的连接。 该代码文件是一个Java
 * SE代码文件。运行于Windows PC上。
 * 
 * Java在Windows PC上实现蓝牙,必须依赖两个库: 
 * 
 * 1,bluecove-2.1.1-SNAPSHOT.jar
 * 下载:http://snapshot.bluecove.org/distribution/download/2.1.1-SNAPSHOT/2.1.1-SNAPSHOT.63/
 * 
 * 2,commons-io-2.6.jar
 * 下载:http://commons.apache.org/proper/commons-io/download_io.cgi
 * 
 * @author fly
 *
 */
public class BluetoothJavaServer {
	private StreamConnectionNotifier mStreamConnectionNotifier = null;
	private StreamConnection mStreamConnection = null;

	public static void main(String[] args) {
		new BluetoothJavaServer();
	}

	public BluetoothJavaServer() {
		try {
			// 服务器端的UUID必须和手机端的UUID相一致。手机端的UUID需要去掉中间的-分割符。
			mStreamConnectionNotifier = (StreamConnectionNotifier) Connector
					.open("btspp://localhost:0000110100001000800000805F9B34FB");
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 开启线程读写蓝牙上接收和发送的数据。
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					System.out.println("服务器端开始监听...");
					while (true) {
						mStreamConnection = mStreamConnectionNotifier.acceptAndOpen();
						System.out.println("接受连接");

						InputStream is = mStreamConnection.openInputStream();

						byte[] buffer = new byte[1024];

						System.out.println("开始读数据...");
						// 读数据。
						while (is.read(buffer) != -1) {
							String s = new String(buffer);
							System.out.println(s);
						}

						is.close();
						mStreamConnection.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

		}).start();
	}
}

 

部署在Android手机客户端的BluetoothClientActivity.java

package zhangphil.test;

import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;

/**
 * Android手机客户端通过蓝牙发送数据到部署在Windows PC电脑上。
 * 如果运行失败,请打开手机的设置,检查是否赋予该App权限:
 *
 * <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
 * <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
 *
 * <uses-permission android:name="android.permission.BLUETOOTH" />
 * <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
 *
 * Android手机的蓝牙客户端。
 * 代码启动后检查当前手机是否已经和蓝牙名称为  TARGET_DEVICE_NAME 的配对成功。
 * 如果配对成功,直接发起对服务器的连接并发送数据到服务器端。
 * 如果当前手机蓝牙和服务器端没有配对成功,则先启动蓝牙扫描,去搜索目标蓝牙设备。发现找到目标设备后连接目标设备并发送数据。
 *
 */

public class BluetoothClientActivity extends AppCompatActivity {
    private BluetoothAdapter mBluetoothAdapter;

    //要连接的目标蓝牙设备。
    private final String TARGET_DEVICE_NAME = "PHIL-PC";

    private final String TAG = "蓝牙调试";
    private final String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB";

    // 广播接收发现蓝牙设备。
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                String name = device.getName();
                if (name != null)
                    Log.d(TAG, "发现设备:" + name);

                if (name != null && name.equals("PHIL-PC")) {
                    Log.d(TAG, "发现目标设备,开始线程连接!");

                    // 蓝牙搜索是非常消耗系统资源开销的过程,一旦发现了目标感兴趣的设备,可以考虑关闭扫描。
                    mBluetoothAdapter.cancelDiscovery();

                    new Thread(new ClientThread(device)).start();
                }
            }
        }
    };

    private class ClientThread extends Thread {
        private BluetoothDevice device;

        public ClientThread(BluetoothDevice device) {
            this.device = device;
        }

        @Override
        public void run() {
            BluetoothSocket socket;

            try {
                socket = device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));

                Log.d(TAG, "连接服务端...");
                socket.connect();
                Log.d(TAG, "连接建立.");

                // 开始往服务器端发送数据。
                sendDataToServer(socket);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void sendDataToServer(BluetoothSocket socket) {
            try {
                OutputStream os = socket.getOutputStream();
                os.write(new String("hello,world!").getBytes());
                os.flush();
                os.close();
                Log.d(TAG, "发送成功");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private BluetoothDevice getPairedDevices() {
        // 获得和当前Android已经配对的蓝牙设备。
        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        if (pairedDevices != null && pairedDevices.size() > 0) {
            // 遍历
            for (BluetoothDevice device : pairedDevices) {
                // 把已经取得配对的蓝牙设备名字和地址打印出来。
                Log.d(TAG, device.getName() + " : " + device.getAddress());
                if (TextUtils.equals(TARGET_DEVICE_NAME, device.getName())) {
                    Log.d(TAG, "已配对目标设备 -> " + TARGET_DEVICE_NAME);
                    return device;
                }
            }
        }

        return null;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        BluetoothDevice device = getPairedDevices();
        if (device == null) {
            // 注册广播接收器。
            // 接收蓝牙发现讯息。
            IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
            registerReceiver(mBroadcastReceiver, filter);

            if (mBluetoothAdapter.startDiscovery()) {
                Log.d(TAG, "启动蓝牙扫描设备...");
            }
        } else {
            new ClientThread(device).start();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mBroadcastReceiver);
    }
}

运行Android手机客户端程序后,务必检查当前App是否获得了蓝牙连接的所有权限。本例出于简单演示期间没有添加蓝牙权限申请的功能代码,关于蓝牙权限申请的功能,请看我写的专栏。BluetoothClientActivity如果在Android高版本上运行,第一次可能运行不成功,原因是权限没有授予,可以打开手机应用管理设置,把相关权限全部授予。然后退出当前程序,再次启动BluetoothClientActivity即可。
Android手机的蓝牙客户端首先会检测目标蓝牙设备和当前手机是否已经配对,如果已经配过对,那么直接连接并发送数据到服务器端,如果没有配对成功的目标蓝牙设备,则开启蓝牙的扫描搜索,搜索目标配对蓝牙设备再连接并发送数据。

运行这个例子前,确保Android手机和Windows电脑上的蓝牙均处于打开状态。
本例是假设Android手机客户端要连接的Windows蓝牙服务器端的名称为:PHIL-PC。这个名字是Android手机蓝牙客户端和Windows蓝牙服务器端一致的,不一致则无法进行连接。
UUID是Android手机客户端和服务器端连接的依据,必须一致,本例使用熟知的蓝牙连接UUID:00001101-0000-1000-8000-00805F9B34FB
UUID在Java SE端的代码中,需要去掉UUID里面含有的-分割线,变成:
0000110100001000800000805F9B34FB
而在Android手机客户端代码中,不需要改变,直接使用:
00001101-0000-1000-8000-00805F9B34FB


代码运行后,Windows PC服务器端的日志输出,收到了Android手机发送过来的hello,world字符串:

BlueCove version 2.1.1-SNAPSHOT on winsock
服务器端开始监听...
等待客户端连接...
接受连接
开始读数据...
hello,world!


Android手机连接到Windows PC服务器成功并发送了数据hello,world:

2018-10-18 14:12:04.620 29786-29786/zhangphil.test D/蓝牙调试: PHIL-PC : 44:03:2C:87:28:C7
2018-10-18 14:12:04.622 29786-29786/zhangphil.test D/蓝牙调试: 已配对目标设备 -> PHIL-PC
2018-10-18 14:12:04.635 29786-29815/zhangphil.test D/蓝牙调试: 连接服务端...
2018-10-18 14:12:06.085 29786-29815/zhangphil.test D/蓝牙调试: 连接建立.
2018-10-18 14:12:06.087 29786-29815/zhangphil.test D/蓝牙调试: 发送成功

我把这个代码例子上传到github上,链接地址:https://github.com/zhangphil/AndroidLinkToPC
该连接下放置了部署到Windows PC服务器端的BluetoothJavaServer.java文件,以及运行在Android手机上的BluetoothClientActivity.java代码文件。同时还连同两个Java SE实现蓝牙功能依赖的两个jar库文件:bluecove-2.1.1-SNAPSHOT.jar和commons-io-2.6.jar。(基于Windows 64位)

本文标题为:Android通过蓝牙发送数据到Windows PC电脑:Java实现

基础教程推荐