send-img-to-device.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #!/usr/bin/env node
  2. /**
  3. * 通过 ADB 将本地图片推送到手机并加入相册(1+ 等 Android 通用)
  4. * 用法: node send-img-to-device.js <本地图片路径> [deviceId]
  5. * 或 require 后调用: sendImageToDevice(localPath, deviceId) => { success, error }
  6. */
  7. const { spawnSync } = require('child_process')
  8. const path = require('path')
  9. const fs = require('fs')
  10. const configPath = process.env.STATIC_ROOT
  11. ? path.join(path.dirname(process.env.STATIC_ROOT), 'configs', 'config.js')
  12. : path.join(__dirname, '..', '..', 'configs', 'config.js')
  13. const projectRoot = path.dirname(path.dirname(path.resolve(configPath)))
  14. const config = fs.existsSync(configPath) ? require(configPath) : {}
  15. const adbPath = config.adbPath?.path
  16. ? (path.isAbsolute(config.adbPath.path) ? config.adbPath.path : path.resolve(projectRoot, config.adbPath.path))
  17. : path.join(projectRoot, 'lib', 'scrcpy-adb', process.platform === 'win32' ? 'adb.exe' : 'adb')
  18. /** 设备 DCIM 目录,相册会扫描此处 */
  19. const DEVICE_DCIM = '/sdcard/DCIM/'
  20. /**
  21. * 将本地图片推送到设备相册
  22. * @param {string} localPath - 本地图片绝对或相对路径
  23. * @param {string} [deviceId] - 设备 ID,如 192.168.42.129 或 192.168.42.129:5555
  24. * @returns {{ success: boolean, error?: string, devicePath?: string }}
  25. */
  26. function sendImageToDevice(localPath, deviceId = '') {
  27. const resolved = path.resolve(localPath)
  28. if (!fs.existsSync(resolved)) {
  29. return { success: false, error: `本地文件不存在: ${resolved}` }
  30. }
  31. const basename = path.basename(resolved)
  32. const deviceFile = DEVICE_DCIM + basename
  33. const args = deviceId ? ['-s', deviceId, 'push', resolved, deviceFile] : ['push', resolved, deviceFile]
  34. const push = spawnSync(adbPath, args, { encoding: 'utf-8', timeout: 30000 })
  35. if (push.status !== 0) {
  36. const err = (push.stderr || push.stdout || '').trim() || `adb push 退出码 ${push.status}`
  37. return { success: false, error: err }
  38. }
  39. const scanArgs = deviceId ? ['-s', deviceId, 'shell', 'am', 'broadcast', '-a', 'android.intent.action.MEDIA_SCANNER_SCAN_FILE', '-d', `file://${deviceFile}`] : ['shell', 'am', 'broadcast', '-a', 'android.intent.action.MEDIA_SCANNER_SCAN_FILE', '-d', `file://${deviceFile}`]
  40. spawnSync(adbPath, scanArgs, { encoding: 'utf-8', timeout: 5000 })
  41. return { success: true, devicePath: deviceFile }
  42. }
  43. if (require.main === module) {
  44. const localPath = process.argv[2]
  45. const deviceId = process.argv[3] || ''
  46. if (!localPath) {
  47. console.error('用法: node send-img-to-device.js <本地图片路径> [deviceId]')
  48. process.exit(1)
  49. }
  50. const result = sendImageToDevice(localPath, deviceId)
  51. if (result.success) {
  52. console.log(result.devicePath || 'ok')
  53. } else {
  54. console.error(result.error)
  55. process.exit(1)
  56. }
  57. }
  58. module.exports = { sendImageToDevice }