You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:40:14