Android通过Bluetooth蓝牙发送手机照片文件到Windows PC:Java实现
本文在《Android通过蓝牙发送数据到Windows PC电脑:Java实现(链接地址:https://blog.csdn.net/zhangphil/article/details/83146705 )》基础上改进代码,还是用Java实现把Android手机上的一张照片,通过Bluetooth蓝牙连接,发送到Windows PC电脑上,实现上仍区分为Windows电脑端的蓝牙服务器端BluetoothJavaServer:
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
/**
* BluetoothJavaServer是蓝牙的服务器端。部署在Windows操作系统(PC电脑上)。 等待手机客户端或者其他蓝牙设备的连接。
*
* @author fly
*
*/
public class BluetoothJavaServer {
// 蓝牙服务器端的UUID必须和手机端的UUID一致。
// 手机端的UUID需要去掉中间的-分割符。
private String MY_UUID = "0000110100001000800000805F9B34FB";
public static void main(String[] args) {
new BluetoothJavaServer();
}
public BluetoothJavaServer() {
StreamConnectionNotifier mStreamConnectionNotifier = null;
try {
mStreamConnectionNotifier = (StreamConnectionNotifier) Connector.open("btspp://localhost:" + MY_UUID);
} catch (Exception e) {
e.printStackTrace();
}
try {
System.out.println("服务器端开始监听客户端连接请求...");
while (true) {
StreamConnection connection = mStreamConnectionNotifier.acceptAndOpen();
System.out.println("接受客户端连接");
new ClientThread(connection).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 开启一个线程专门从与客户端蓝牙设备中读取文件数据,并把文件数据存储到本地。
*
* @author fly
*
*/
private class ClientThread extends Thread {
private StreamConnection mStreamConnection = null;
public ClientThread(StreamConnection sc) {
mStreamConnection = sc;
}
@Override
public void run() {
try {
BufferedInputStream bis = new BufferedInputStream(mStreamConnection.openInputStream());
// 本地创建一个image.jpg文件接收来自于手机客户端发来的图片文件数据。
FileOutputStream fos = new FileOutputStream("image.jpg");
int c = 0;
byte[] buffer = new byte[1024];
System.out.println("开始读数据...");
while (true) {
c = bis.read(buffer);
if (c == -1) {
System.out.println("读取数据结束");
break;
} else {
fos.write(buffer, 0, c);
}
}
fos.flush();
fos.close();
bis.close();
mStreamConnection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Android手机端的蓝牙客户端BluetoothClientActivity:
package zhangphil.test;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
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.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
public class BluetoothClientActivity extends AppCompatActivity {
private BluetoothAdapter mBluetoothAdapter;
//要连接的目标蓝牙设备(Windows PC电脑的名字)。
private final String TARGET_DEVICE_NAME = "PHIL-PC";
private final String TAG = "蓝牙调试";
//UUID必须是Android蓝牙客户端和Windows PC电脑端一致。
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, "发现目标蓝牙设备,开始线程连接");
new Thread(new ClientThread(device)).start();
// 蓝牙搜索是非常消耗系统资源开销的过程,一旦发现了目标感兴趣的设备,可以关闭扫描。
mBluetoothAdapter.cancelDiscovery();
}
}
}
};
/**
* 该线程往蓝牙服务器端发送文件数据。
*/
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, "连接建立.");
// 开始往服务器端发送数据。
Log.d(TAG, "开始往蓝牙服务器发送数据...");
sendDataToServer(socket);
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendDataToServer(BluetoothSocket socket) {
try {
FileInputStream fis = new FileInputStream(getFile());
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] buffer = new byte[1024];
int c;
while (true) {
c = fis.read(buffer);
if (c == -1) {
Log.d(TAG, "读取结束");
break;
} else {
bos.write(buffer, 0, c);
}
}
bos.flush();
fis.close();
bos.close();
Log.d(TAG, "发送文件成功");
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 发给给蓝牙服务器的文件。
* 本例发送一张位于存储器根目录下名为 image.jpg 的照片。
*
* @return
*/
private File getFile() {
File root = Environment.getExternalStorageDirectory();
File file = new File(root, "image.jpg");
return file;
}
/**
* 获得和当前Android蓝牙已经配对的蓝牙设备。
*
* @return
*/
private BluetoothDevice getPairedDevices() {
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices != null && pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
// 把已经取得配对的蓝牙设备名字和地址打印出来。
Log.d(TAG, device.getName() + " : " + device.getAddress());
//如果已经发现目标蓝牙设备和Android蓝牙已经配对,则直接返回。
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客户端选择文件的代码实现,事先作为测试文件,先在Android手机的存储器根目录放置一张名为image.jpg的图片。
务必保证Windows电脑和Android手机上的蓝牙均处于打开状态。然后先启动服务器端程序,再启动Android手机客户端程序。
Windows电脑端输出:
Android studio的logcat输出: