Procházet zdrojové kódy

激活手机功能

yichael před 2 týdny
rodič
revize
9c1f6d726d
46 změnil soubory, kde provedl 144 přidání a 52 odebrání
  1. 2 2
      electron/main.js
  2. 4 3
      lib/scrcpy-adb/scrcpy-noconsole.vbs
  3. 19 3
      nodejs/adb/screenshot.js
  4. 57 0
      nodejs/enable-wirless-connect.js
  5. 0 0
      package/package-arm64.bat
  6. 0 0
      package/package-arm64.js
  7. 0 0
      package/package-x64.bat
  8. 0 0
      package/package-x64.js
  9. binární
      python/py/_asyncio.pyd
  10. binární
      python/py/_bz2.pyd
  11. binární
      python/py/_ctypes.pyd
  12. binární
      python/py/_decimal.pyd
  13. binární
      python/py/_elementtree.pyd
  14. binární
      python/py/_hashlib.pyd
  15. binární
      python/py/_lzma.pyd
  16. binární
      python/py/_msi.pyd
  17. binární
      python/py/_multiprocessing.pyd
  18. binární
      python/py/_overlapped.pyd
  19. binární
      python/py/_queue.pyd
  20. binární
      python/py/_socket.pyd
  21. binární
      python/py/_sqlite3.pyd
  22. binární
      python/py/_ssl.pyd
  23. binární
      python/py/_uuid.pyd
  24. binární
      python/py/_wmi.pyd
  25. binární
      python/py/_zoneinfo.pyd
  26. binární
      python/py/libcrypto-3-arm64.dll
  27. binární
      python/py/libffi-8.dll
  28. binární
      python/py/libssl-3-arm64.dll
  29. binární
      python/py/pyexpat.pyd
  30. binární
      python/py/python.cat
  31. binární
      python/py/python.exe
  32. binární
      python/py/python3.dll
  33. 5 0
      python/py/python312._pth
  34. binární
      python/py/python312.dll
  35. binární
      python/py/python312.zip
  36. binární
      python/py/pythonw.exe
  37. binární
      python/py/select.pyd
  38. binární
      python/py/sqlite3.dll
  39. binární
      python/py/unicodedata.pyd
  40. binární
      python/py/vcruntime140.dll
  41. binární
      python/py/vcruntime140_1.dll
  42. binární
      python/py/winsound.pyd
  43. 23 11
      src/page/device/connect-item/connect-item.js
  44. 18 23
      src/page/device/device.js
  45. 3 2
      src/page/device/device.jsx
  46. 13 8
      src/page/device/device.scss

+ 2 - 2
electron/main.js

@@ -128,8 +128,8 @@ ipcMain.handle('run-nodejs-script', async (event, scriptName, ...parameters) =>
       stderr += data.toString()
       stderr += data.toString()
     })
     })
     
     
-    const isRunProcess = scriptName === 'run-process'
-    const timeoutId = isRunProcess ? null : setTimeout(() => {
+    const waitForExit = scriptName === 'run-process' || scriptName === 'enable-wirless-connect'
+    const timeoutId = waitForExit ? null : setTimeout(() => {
       if (!resolved) {
       if (!resolved) {
         finish({
         finish({
           success: false,
           success: false,

+ 4 - 3
lib/scrcpy-adb/scrcpy-noconsole.vbs

@@ -1,7 +1,8 @@
-strCommand = "cmd /c scrcpy.exe"
+' 在 VBS 所在目录执行 scrcpy.exe,确保能找到 exe 及同目录 dll
+strCommand = "cmd /c cd /d """ & CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName) & """ && scrcpy.exe"
 
 
 For Each Arg In WScript.Arguments
 For Each Arg In WScript.Arguments
-    strCommand = strCommand & " """ & replace(Arg, """", """""""""") & """"
+    strCommand = strCommand & " """ & Replace(Arg, """", """") & """"
 Next
 Next
 
 
-CreateObject("Wscript.Shell").Run strCommand, 0, false
+CreateObject("Wscript.Shell").Run strCommand, 0, False

+ 19 - 3
nodejs/adb/screenshot.js

@@ -37,12 +37,28 @@ function killPidIfRunning(pid) {
   }).unref()
   }).unref()
 }
 }
 
 
-// 启动 scrcpy
+/** 判断是否为 IP(或 IP:port),用于无线设备选择器 */
+function isDeviceIp(val) {
+  return val && !/^\d+$/.test(val) && /[\d.]/.test(val)
+}
+
+/** 根据传入的 IP 得到 adb/scrcpy 设备选择器,无线默认 5555 */
+function toDeviceSelector(ipOrSelector) {
+  return ipOrSelector.includes(':') ? ipOrSelector : `${ipOrSelector}:5555`
+}
+
+// 启动 scrcpy:若传入 IP 则先 adb connect 再以该设备启动 lib/scrcpy-adb/scrcpy-noconsole.vbs
 function startScrcpy() {
 function startScrcpy() {
   const targetPid = pidArg && /^\d+$/.test(pidArg) ? parseInt(pidArg) : 7788
   const targetPid = pidArg && /^\d+$/.test(pidArg) ? parseInt(pidArg) : 7788
   killPidIfRunning(targetPid)
   killPidIfRunning(targetPid)
-  
-  const vbsArgs = pidArg && !/^\d+$/.test(pidArg) ? ` "${pidArg}"` : ''
+
+  let deviceSelector = ''
+  if (isDeviceIp(pidArg)) {
+    deviceSelector = toDeviceSelector(pidArg)
+    execSync(`"${adbPath}" connect ${deviceSelector}`, { encoding: 'utf-8', cwd: scrcpyDir })
+  }
+
+  const vbsArgs = deviceSelector ? ` "${deviceSelector}"` : (pidArg && !/^\d+$/.test(pidArg) ? ` "${pidArg}"` : '')
   execSync(`wscript.exe "${scrcpyVbs}"${vbsArgs}`, {
   execSync(`wscript.exe "${scrcpyVbs}"${vbsArgs}`, {
     cwd: scrcpyDir,
     cwd: scrcpyDir,
     stdio: 'ignore'
     stdio: 'ignore'

+ 57 - 0
nodejs/enable-wirless-connect.js

@@ -0,0 +1,57 @@
+#!/usr/bin/env node
+const { execSync } = require('child_process')
+const path = require('path')
+
+// 项目根 = 脚本所在目录的上一级(nodejs -> 项目根)
+// 打包后 nodejs 在 app.asar 内执行,但 lib/configs 在 app.asar.unpacked,需用 unpacked 路径才能找到 adb
+let PROJECT_ROOT = path.resolve(__dirname, '..')
+if (PROJECT_ROOT.includes('app.asar') && !PROJECT_ROOT.includes('app.asar.unpacked')) {
+  PROJECT_ROOT = PROJECT_ROOT.replace('app.asar', 'app.asar.unpacked')
+}
+const TCPIP_PORT = 5555
+
+/** 从配置解析并返回 ADB 可执行文件路径 */
+function getAdbPath() {
+  const configPath = path.join(PROJECT_ROOT, 'configs', 'config.js')
+  const config = require(configPath)
+  return config.adbPath?.path
+    ? path.resolve(PROJECT_ROOT, config.adbPath.path)
+    : path.join(PROJECT_ROOT, 'lib', 'scrcpy-adb', 'adb.exe')
+}
+
+/** 返回当前通过 USB 连接的设备 ID 列表(仅 status 为 device 且非 IP:port,排除无线设备) */
+function getConnectedDeviceIds(adbPath) {
+  const out = execSync(`"${adbPath}" devices`, { encoding: 'utf-8' })
+  return out
+    .split('\n')
+    .filter((line) => line.trim() && !line.startsWith('List') && line.includes('\tdevice'))
+    .map((line) => line.trim().split('\t')[0])
+    .filter((id) => id && !id.includes(':'))
+}
+
+/** 操作一:在 USB 设备上开启无线调试(settings adb_wifi_enabled 1) */
+function enableWirelessSetting(adbPath, deviceId) {
+  execSync(`"${adbPath}" -s ${deviceId} shell settings put global adb_wifi_enabled 1`, { encoding: 'utf-8' })
+}
+
+/** 操作二:在 USB 设备上激活 5555 端口(tcpip),用于无线连接 */
+function enableTcpipPort(adbPath, deviceId, port) {
+  return execSync(`"${adbPath}" -s ${deviceId} tcpip ${port}`, { encoding: 'utf-8' }).trim()
+}
+
+/** 主流程:取 USB 设备,依次执行「开启无线调试」「激活 5555 端口」 */
+function run() {
+  const adbPath = getAdbPath()
+  const devices = getConnectedDeviceIds(adbPath)
+  if (devices.length === 0) {
+    process.stderr.write('No devices found. Please connect a device via USB.\n')
+    process.exit(1)
+  }
+  const deviceId = devices[0]
+  enableWirelessSetting(adbPath, deviceId)
+  const tcpipOut = enableTcpipPort(adbPath, deviceId, TCPIP_PORT)
+  process.stdout.write(tcpipOut + '\n')
+  process.exit(0)
+}
+
+run()

+ 0 - 0
package/package-arm64.bat


+ 0 - 0
package/package-arm64.js


+ 0 - 0
package/package-x64.bat


+ 0 - 0
package/package-x64.js


binární
python/py/_asyncio.pyd


binární
python/py/_bz2.pyd


binární
python/py/_ctypes.pyd


binární
python/py/_decimal.pyd


binární
python/py/_elementtree.pyd


binární
python/py/_hashlib.pyd


binární
python/py/_lzma.pyd


binární
python/py/_msi.pyd


binární
python/py/_multiprocessing.pyd


binární
python/py/_overlapped.pyd


binární
python/py/_queue.pyd


binární
python/py/_socket.pyd


binární
python/py/_sqlite3.pyd


binární
python/py/_ssl.pyd


binární
python/py/_uuid.pyd


binární
python/py/_wmi.pyd


binární
python/py/_zoneinfo.pyd


binární
python/py/libcrypto-3-arm64.dll


binární
python/py/libffi-8.dll


binární
python/py/libssl-3-arm64.dll


binární
python/py/pyexpat.pyd


binární
python/py/python.cat


binární
python/py/python.exe


binární
python/py/python3.dll


+ 5 - 0
python/py/python312._pth

@@ -0,0 +1,5 @@
+python312.zip
+.
+
+# Uncomment to run site.main() automatically
+#import site

binární
python/py/python312.dll


binární
python/py/python312.zip


binární
python/py/pythonw.exe


binární
python/py/select.pyd


binární
python/py/sqlite3.dll


binární
python/py/unicodedata.pyd


binární
python/py/vcruntime140.dll


binární
python/py/vcruntime140_1.dll


binární
python/py/winsound.pyd


+ 23 - 11
src/page/device/connect-item/connect-item.js

@@ -11,7 +11,14 @@ class ConnectItemClass {
     }
     }
 
 
     async onPreview() {
     async onPreview() {
-        const result = await this.triggerPreview()
+        let result
+        try {
+            result = await this.triggerPreview()
+        } catch (err) {
+            console.warn('[ConnectItem] onPreview error:', err)
+            this.setIsPreviewing?.(false)
+            return
+        }
         if (!result.success) {
         if (!result.success) {
             return
             return
         }
         }
@@ -35,21 +42,26 @@ class ConnectItemClass {
     }
     }
 
 
     // 触发 scrcpy 预览(切换启动/停止状态)
     // 触发 scrcpy 预览(切换启动/停止状态)
+    // 主进程对 adb/screenshot 会提前 resolve,exitCode 可能为 null,需按成功处理
     async triggerPreview() {
     async triggerPreview() {
         const stopResult = await window.electronAPI.runNodejsScript('adb/screenshot', 'stop')
         const stopResult = await window.electronAPI.runNodejsScript('adb/screenshot', 'stop')
-
-        if (stopResult.exitCode === 0) {
-            const json = JSON.parse(stopResult.stdout)
-            if (json.success === true) {
-                return { action: 'stop', success: true }
-            }
+        const stopOk = stopResult.exitCode === 0 || stopResult.exitCode === null
+        if (stopOk && stopResult.stdout) {
+            try {
+                const json = JSON.parse(stopResult.stdout)
+                if (json.success === true) {
+                    return { action: 'stop', success: true }
+                }
+            } catch (_) {}
         }
         }
 
 
         const startResult = await window.electronAPI.runNodejsScript('adb/screenshot', 'start', this.ipAddress)
         const startResult = await window.electronAPI.runNodejsScript('adb/screenshot', 'start', this.ipAddress)
-
-        if (startResult.exitCode === 0) {
-            const json = JSON.parse(startResult.stdout)
-            return { action: 'start', success: json.success === true }
+        const startOk = startResult.exitCode === 0 || startResult.exitCode === null
+        if (startOk && startResult.stdout) {
+            try {
+                const json = JSON.parse(startResult.stdout)
+                return { action: 'start', success: json.success === true }
+            } catch (_) {}
         }
         }
 
 
         return { action: 'start', success: false }
         return { action: 'start', success: false }

+ 18 - 23
src/page/device/device.js

@@ -42,33 +42,28 @@ class DeviceClass {
         }
         }
     }
     }
 
 
-    async onRefresh(e, self) {
-        self.startAnimation()
-        this.count_ip_x = 2
-        this.count_ip_y = 1
-
-        let that = this;
-        this.scanDevice(() => {
-            self.stopAnimation()
-        }, that)
-    }
-
-    async scanDevice(callback, that) {
-        const basePrefix = this.inputValue?.trim() || ''
-        if (!basePrefix) {
-            callback()
+    /** 执行开启无线连接脚本并根据结果提示 */
+    async onEnableWirlessConnect() {
+        const result = await window.electronAPI.runNodejsScript('enable-wirless-connect')
+        const noDevice = (result.stderr || '').includes('No devices') || (result.stdout || '').includes('No devices')
+        if (result.exitCode === 0) {
+            hintView.setContent('开启手机无线连接成功')
+            hintView.show()
             return
             return
         }
         }
-        const result = await window.electronAPI.runNodejsScript('adb/scan-connect-ip', basePrefix, '5555')
-        if (result.exitCode === 0 && result.stdout) {
-            const ips = result.stdout.split(/\r?\n/).map(s => s.trim()).filter(Boolean)
-            if (ips.length) {
-                that.setDeviceList(prev => [...new Set([...(prev || []), ...ips])])
-            }
+        if (noDevice) {
+            hintView.setContent('未检测到设备,请先用 USB 连接手机')
+            hintView.show()
+            return
         }
         }
-        callback()
+        const raw = (result.stderr || result.stdout || '').trim().split('\n')[0] || '开启无线连接失败'
+        const msg = (raw === 'error: closed' || raw.includes('closed'))
+            ? 'ADB 连接已断开,请检查 USB 连接后重试'
+            : raw
+        hintView.setContent(msg)
+        hintView.show()
     }
     }
-
+    
     async onAddDevice() {
     async onAddDevice() {
         const ip = this.inputValue; 
         const ip = this.inputValue; 
         const ipList = await window.electronAPI.runNodejsScript('json-parser', 'read', 'device_list.json')
         const ipList = await window.electronAPI.runNodejsScript('json-parser', 'read', 'device_list.json')

+ 3 - 2
src/page/device/device.jsx

@@ -45,12 +45,13 @@ function Device({ show }) {
         {/* 更新设备列表 */}
         {/* 更新设备列表 */}
         <div className="device-update">
         <div className="device-update">
           <div className="device-update-title">设备列表</div>
           <div className="device-update-title">设备列表</div>
-          <div className="device-update-btn">
+          {/* <div className="device-update-btn">
             <UpdateBtn
             <UpdateBtn
               onClick={(e, self) => deviceClass.current?.onRefresh(e, self)}
               onClick={(e, self) => deviceClass.current?.onRefresh(e, self)}
               title="Refresh device list"
               title="Refresh device list"
             />
             />
-          </div>
+          </div> */}
+          <div className="enable-wirless-connect-btn" onClick={() => deviceClass.current?.onEnableWirlessConnect()}>激活</div>
         </div>
         </div>
 
 
         {/* 设备列表 */}
         {/* 设备列表 */}

+ 13 - 8
src/page/device/device.scss

@@ -20,16 +20,21 @@
       
       
       @include flex-center;
       @include flex-center;
     }
     }
-
-    .device-update-btn {
+    .enable-wirless-connect-btn {
       width: 30%;
       width: 30%;
-      height: 100%;
-      @include flex-center;
+      height: 50%;
+   
+      background-color: #000000;
+      border-radius: 10px;
+      font-size: 0.8rem;
+      color: #ffffff;
+      margin-right: 5%;
 
 
-      .update-btn {
-        width: 50% !important;
-        height: 50% !important;
-      }
+      cursor: pointer;
+      @include div-btn-hover-effect;
+      @include div-btn-pressed-effect;
+
+      @include flex-center;
     }
     }
 
 
     background-color: #efe8e88d;
     background-color: #efe8e88d;