| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- /**
- * adb method: send-img-to-device — 将本地图片推送到手机并加入相册(1+ 等 Android 通用)
- * inVars: [本地图片路径] 路径可为相对 folderPath 或绝对
- */
- const { spawnSync } = require('child_process')
- const path = require('path')
- const fs = require('fs')
- // .../nodejs/ef-compiler/actions/fun/adb/send-img-to-device.js → 上溯 5 层到仓库根
- const defaultRoot = path.resolve(__dirname, '..', '..', '..', '..', '..')
- const configPath = process.env.STATIC_ROOT
- ? path.join(path.dirname(path.resolve(process.env.STATIC_ROOT)), 'config.js')
- : path.join(defaultRoot, 'config.js')
- const config = fs.existsSync(configPath) ? require(configPath) : {}
- const projectRoot = (config.projectRoot && fs.existsSync(config.projectRoot)) ? config.projectRoot : defaultRoot
- const adbPath = config.adbPath?.path
- ? (path.isAbsolute(config.adbPath.path) ? config.adbPath.path : path.resolve(projectRoot, config.adbPath.path))
- : path.join(projectRoot, 'lib', 'scrcpy-adb', process.platform === 'win32' ? 'adb.exe' : 'adb')
- // Android 10+ 相册对 Pictures 目录更友好,1+ 等机型也常从此处读
- const DEVICE_PICTURES = '/sdcard/Pictures/'
- const DEVICE_DCIM = '/sdcard/DCIM/'
- /**
- * 将本地图片推送到设备相册(供 run 与 CLI 复用)
- * @param {string} localPath - 本地图片绝对路径
- * @param {string} deviceId - 设备 ID
- * @param {string} [adbExe] - 可选,默认用 config
- */
- function doSendImageToDevice(localPath, deviceId, adbExe = adbPath) {
- const resolved = path.resolve(localPath)
- if (!fs.existsSync(resolved)) {
- return { success: false, error: `本地文件不存在: ${resolved}` }
- }
- const basename = path.basename(resolved)
- // 优先推送到 Pictures,Android 10+ 相册更容易识别
- const deviceFile = DEVICE_PICTURES + basename
- const localForAdb = resolved.replace(/\\/g, '/')
- const args = deviceId ? ['-s', deviceId, 'push', localForAdb, deviceFile] : ['push', localForAdb, deviceFile]
- const push = spawnSync(adbExe, args, { encoding: 'utf-8', timeout: 60000 })
- const ok = push.status === 0
- if (!ok) {
- const msg = (push.stderr || push.stdout || '').trim()
- const code = push.status
- const sig = push.signal
- let err = msg || (code != null ? `adb push 退出码 ${code}` : sig ? `adb push 被终止 (${sig})` : 'adb push 未正常结束(可能超时或 adb 未找到)')
- if (code == null && !msg) err += '。请检查设备连接与 adb 路径'
- return { success: false, error: err }
- }
- // Android 10/11+ 需带 --receiver-include-background 扫描才易在相册中显示
- const scan = (d) => {
- const base = ['shell', 'am', 'broadcast', '-a', 'android.intent.action.MEDIA_SCANNER_SCAN_FILE', '-d', d, '--receiver-include-background']
- const a = deviceId ? ['-s', deviceId, ...base] : base
- spawnSync(adbExe, a, { encoding: 'utf-8', timeout: 8000 })
- }
- scan(`file://${deviceFile}`)
- scan('file:///sdcard/Pictures')
- scan('file:///sdcard/DCIM')
- return { success: true, devicePath: deviceFile }
- }
- async function run(action, ctx) {
- const { device, folderPath, variableContext, extractVarName, logMessage } = ctx
- const inVars = action.inVars || []
- let localPath = inVars.length > 0 ? (variableContext[extractVarName(inVars[0])] || inVars[0]) : action.value
- if (!localPath) return { success: false, error: 'send-img-to-device 操作缺少本地图片路径' }
- if (!device || String(device).trim() === '') return { success: false, error: 'send-img-to-device 需要设备 ID,请确保流程已连接设备' }
- const fullPath = localPath.startsWith('/') || (localPath.length >= 2 && localPath[1] === ':') ? localPath : path.resolve(folderPath, localPath)
- if (!fs.existsSync(fullPath)) return { success: false, error: `本地文件不存在: ${fullPath}(流程目录: ${folderPath})` }
- const result = doSendImageToDevice(fullPath, device, adbPath)
- if (!result.success) return result
- return { success: true, devicePath: result.devicePath }
- }
- module.exports = { run, doSendImageToDevice }
|