基于Electron实现桌面与Android端蓝牙/WiFi文件传输可行性咨询
嗨Bala,这个需求完全是可以实现的!我来给你拆解一下蓝牙和WiFi两种方式的具体方案,附带代码示例参考:
一、WiFi 方式实现文件共享(相对简单易上手)
WiFi方案的核心是在Electron桌面端搭建一个本地HTTP服务器,Android设备通过局域网IP访问这个服务器来完成文件的上传和下载,这种方式稳定性高、传输速度快,是比较推荐的方案。
桌面端(Electron)代码示例
const { app, BrowserWindow, http } = require('electron'); const fs = require('fs'); const path = require('path'); let mainWindow; function createWindow() { mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, contextIsolation: false } }); // 搭建本地HTTP服务器用于文件传输 const server = http.createServer((req, res) => { // 处理Android端的文件下载请求 if (req.method === 'GET' && req.url === '/send-file') { const filePath = path.join(__dirname, 'test-file.txt'); const stat = fs.statSync(filePath); res.writeHead(200, { 'Content-Type': 'application/octet-stream', 'Content-Length': stat.size, 'Content-Disposition': `attachment; filename=${path.basename(filePath)}` }); const readStream = fs.createReadStream(filePath); readStream.pipe(res); } // 处理Android端的文件上传请求 else if (req.method === 'POST' && req.url === '/receive-file') { const writeStream = fs.createWriteStream(path.join(__dirname, 'received-from-android.txt')); req.pipe(writeStream); req.on('end', () => { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('文件接收成功!'); // 通知渲染层文件已接收 mainWindow.webContents.send('file-received', 'received-from-android.txt'); }); } else { res.writeHead(404); res.end('无效请求'); } }); // 监听0.0.0.0让局域网内设备都能访问,端口选8080 server.listen(8080, '0.0.0.0', () => { console.log('文件传输服务器已启动,局域网访问地址:http://你的桌面端IP:8080'); }); mainWindow.loadFile('index.html'); } app.whenReady().then(createWindow);
Android端(Kotlin)代码示例
import java.io.FileOutputStream import java.io.FileInputStream import java.net.HttpURLConnection import java.net.URL // 从桌面端下载文件 fun downloadFileFromDesktop() { // 替换成你的桌面端局域网IP val url = URL("http://192.168.1.100:8080/send-file") val connection = url.openConnection() as HttpURLConnection connection.requestMethod = "GET" val inputStream = connection.inputStream val outputStream = FileOutputStream("/sdcard/Download/received-file.txt") val buffer = ByteArray(1024) var bytesRead: Int while (inputStream.read(buffer).also { bytesRead = it } != -1) { outputStream.write(buffer, 0, bytesRead) } outputStream.close() inputStream.close() connection.disconnect() } // 上传文件到桌面端 fun uploadFileToDesktop() { // 替换成你的桌面端局域网IP val url = URL("http://192.168.1.100:8080/receive-file") val connection = url.openConnection() as HttpURLConnection connection.requestMethod = "POST" connection.doOutput = true val file = File("/sdcard/Download/send-to-desktop.txt") val outputStream = connection.outputStream val inputStream = FileInputStream(file) val buffer = ByteArray(1024) var bytesRead: Int while (inputStream.read(buffer).also { bytesRead = it } != -1) { outputStream.write(buffer, 0, bytesRead) } outputStream.close() inputStream.close() val responseCode = connection.responseCode if (responseCode == HttpURLConnection.HTTP_OK) { // 上传成功,可在这里添加提示逻辑 } connection.disconnect() }
二、蓝牙方式实现文件共享
蓝牙方案适合没有WiFi的场景,Electron可以借助Node.js的蓝牙第三方库来实现,Android端则用系统自带的蓝牙API来建立Socket连接。
桌面端(Electron)代码示例
首先需要安装依赖:npm install node-bluetooth
const bluetooth = require('node-bluetooth'); const fs = require('fs'); const path = require('path'); // 获取默认蓝牙适配器 const adapter = bluetooth.defaultAdapter(); // 监听适配器状态变化 adapter.on('stateChange', (state) => { console.log('蓝牙适配器状态:', state); }); // 开始扫描蓝牙设备 adapter.startDiscovery() .then(() => { console.log('开始扫描蓝牙设备...'); adapter.on('found', (device) => { console.log('发现设备:', device.address, device.name); // 匹配你的Android设备名称 if (device.name === 'MyAndroidDevice') { adapter.stopDiscovery(); connectToDevice(device.address); } }); }) .catch(err => console.error('扫描失败:', err)); // 连接到目标设备并传输文件 function connectToDevice(address) { // 使用RFCOMM通道(蓝牙串口协议)连接,通道号通常为1 adapter.connect(address, 1) .then((socket) => { console.log('已成功连接到Android设备'); // 发送文件到Android const sendFilePath = path.join(__dirname, 'bluetooth-send.txt'); fs.readFile(sendFilePath, (err, data) => { if (err) throw err; socket.write(data); console.log('文件发送完成'); }); // 接收Android发来的文件 const receiveStream = fs.createWriteStream(path.join(__dirname, 'bluetooth-received.txt')); socket.pipe(receiveStream); socket.on('end', () => { console.log('文件接收完成'); receiveStream.close(); }); }) .catch(err => console.error('连接失败:', err)); }
Android端(Kotlin)代码示例
import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothServerSocket import android.bluetooth.BluetoothSocket import java.io.FileOutputStream import java.io.FileInputStream import java.util.UUID private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter() private var bluetoothSocket: BluetoothSocket? = null // 启动蓝牙服务,监听桌面端连接 fun startBluetoothServer() { // 使用通用的RFCOMM UUID val uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") val serverSocket: BluetoothServerSocket? = bluetoothAdapter?.listenUsingRfcommWithServiceRecord("FileTransferService", uuid) Thread { try { // 等待桌面端连接 bluetoothSocket = serverSocket?.accept() // 连接成功后开始传输文件 transferFileViaBluetooth() } catch (e: Exception) { e.printStackTrace() } finally { serverSocket?.close() } }.start() } // 蓝牙文件传输逻辑 fun transferFileViaBluetooth() { bluetoothSocket?.let { socket -> // 读取桌面端发来的文件 val inputStream = socket.inputStream val outputStream = FileOutputStream("/sdcard/Download/bluetooth-received.txt") val buffer = ByteArray(1024) var bytesRead: Int while (inputStream.read(buffer).also { bytesRead = it } != -1) { outputStream.write(buffer, 0, bytesRead) } // 发送文件到桌面端 val fileInputStream = FileInputStream("/sdcard/Download/bluetooth-send.txt") val socketOutputStream = socket.outputStream while (fileInputStream.read(buffer).also { bytesRead = it } != -1) { socketOutputStream.write(buffer, 0, bytesRead) } // 关闭所有流和连接 inputStream.close() outputStream.close() fileInputStream.close() socketOutputStream.close() socket.close() } }
注意事项
- WiFi方式:需要确保Android和桌面端处于同一局域网,桌面端要获取自己的局域网IP(可以通过
os.networkInterfaces()在Electron中获取)提供给Android端;Android端需要申请INTERNET和WRITE_EXTERNAL_STORAGE权限。 - 蓝牙方式:双方设备需要提前配对;桌面端需要蓝牙硬件支持,并且在Windows/macOS上可能需要申请蓝牙权限;Android端需要申请
BLUETOOTH、BLUETOOTH_ADMIN、ACCESS_FINE_LOCATION(用于扫描设备)等权限。 - Electron打包:使用蓝牙依赖时,打包需要确保native模块被正确打包,可以用
electron-builder并配置build.dependencies。
内容的提问来源于stack exchange,提问作者Bala
相关产品推荐
相关产品推荐

