Files
QingTing-Player/tools/device-check.ps1
T
lxh2875931338 6f9fe6262d chore(tools): 增加真机自检脚本 device-check.ps1
一键完成:安装 debug APK → 冷启动 → 抓 logcat → 校验单实例
(PlaybackService / serviceId / Player / MediaSession 各只允许 1 个),
并检查崩溃与 libmediakitandroidhelper.so 加载失败。
2026-10-22 22:46:51 +08:00

125 lines
6.0 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#Requires -Version 5.1
<#
.SYNOPSIS
清听真机自检:安装最新 debug APK,冷启动,抓 logcat,校验 libmpv 是否只有单实例。
.DESCRIPTION
判定依据:
- 冷启动后 "PlaybackService 单例创建" 只出现一次;
- 日志里出现过的 serviceId 只有 1 个;
- media_kit Player 的 hashCode 只有 1 个。
.EXAMPLE
powershell -ExecutionPolicy Bypass -File tools\device-check.ps1
powershell -ExecutionPolicy Bypass -File tools\device-check.ps1 -DeviceId 192.168.3.2:36569
#>
[CmdletBinding()]
param(
[string]$DeviceId = '',
[string]$Apk = '',
[int]$WaitSeconds = 12
)
$ErrorActionPreference = 'Continue' # adb 会往 stderr 写正常提示,用 Stop 会误判
$root = Split-Path -Parent $PSScriptRoot
if (-not $Apk) { $Apk = Join-Path $root 'build\app\outputs\flutter-apk\app-debug.apk' }
$pkg = 'com.lxh.qingting_player'
function Write-Step($msg) { Write-Host "==> $msg" -ForegroundColor Cyan }
function Write-Ok($msg) { Write-Host " OK $msg" -ForegroundColor Green }
function Write-Bad($msg) { Write-Host " !! $msg" -ForegroundColor Red }
if (-not (Get-Command adb -ErrorAction SilentlyContinue)) {
throw '未找到 adb,请把 platform-tools 加入 PATH'
}
if (-not (Test-Path $Apk)) {
throw "APK 不存在:$Apk(先执行 gradlew assembleDebug)"
}
# ---------- 选择设备 ----------
# 同一台手机可能同时存在多条 adb 通道(如无线调试 + mDNS),按 serialno 去重
$devices = @(adb devices | Select-Object -Skip 1 | Where-Object { $_ -match '\sdevice$' } | ForEach-Object { ($_ -split '\s+')[0] })
if ($DeviceId) {
if ($devices -notcontains $DeviceId) { throw "设备 $DeviceId 不在线,当前:$($devices -join ', ')" }
} elseif ($devices.Count -eq 0) {
throw '没有在线设备,请先连接手机并授权 USB/无线调试'
} elseif ($devices.Count -eq 1) {
$DeviceId = $devices[0]
} else {
$bySerial = @{}
foreach ($entry in $devices) {
$serial = (& adb -s $entry shell getprop ro.serialno 2>$null | Out-String).Trim()
if ($serial) { $bySerial[$serial] = $entry }
}
if ($bySerial.Count -eq 1) {
$DeviceId = @($bySerial.Values)[0]
Write-Host " (同一设备的多条 adb 通道,使用 $DeviceId)" -ForegroundColor DarkGray
} else {
throw "检测到多台设备,请用 -DeviceId 指定:$($devices -join ', ')"
}
}
$adb = { param($args) & adb -s $DeviceId @args }
$model = (& adb -s $DeviceId shell getprop ro.product.model).Trim()
$android = (& adb -s $DeviceId shell getprop ro.build.version.release).Trim()
Write-Step "设备 $model (Android $android) [$DeviceId]"
# ---------- 安装 ----------
Write-Step "安装 $([IO.Path]::GetFileName($Apk))"
$install = & adb -s $DeviceId install -r $Apk 2>&1
if (($install -join "`n") -notmatch 'Success') { Write-Bad ($install -join "`n"); exit 1 }
Write-Ok '安装成功'
# ---------- 冷启动 ----------
Write-Step '冷启动并抓取日志'
& adb -s $DeviceId shell am force-stop $pkg | Out-Null
& adb -s $DeviceId logcat -c
& adb -s $DeviceId shell monkey -p $pkg -c android.intent.category.LAUNCHER 1 2>&1 | Out-Null
Start-Sleep -Seconds $WaitSeconds
& adb -s $DeviceId logcat -d -v time > (Join-Path $root 'build\device-check-last.log')
$logPath = Join-Path $root 'build\device-check-last.log'
# 注意:PS 5.1 的 > 重定向写出的是 UTF-16LE(带 BOM),这里不要强制 utf8
$log = Get-Content $logPath
$text = $log -join "`n"
# ---------- 判定 ----------
Write-Step '实例检查'
$serviceIds = @([regex]::Matches($text, 'serviceId=(\d+)') | ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique)
$players = @([regex]::Matches($text, 'Player 已创建.*?player=(\d+)') | ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique)
$creates = ([regex]::Matches($text, '\[PlaybackService\] 单例创建')).Count
$failed = $false
if ($creates -eq 1) { Write-Ok "PlaybackService 单例创建 x$creates" } else { Write-Bad "PlaybackService 单例创建 x$creates(应为 1)"; $failed = $true }
if ($serviceIds.Count -eq 1) { Write-Ok "serviceId 唯一:$($serviceIds[0])" } else { Write-Bad "出现 $($serviceIds.Count) 个 serviceId:$($serviceIds -join ', ')"; $failed = $true }
if ($players.Count -eq 1) { Write-Ok "Player 唯一:$($players[0])" } else { Write-Bad "出现 $($players.Count) 个 Player:$($players -join ', ')"; $failed = $true }
# ---------- 系统侧 ----------
Write-Step '系统 MediaSession'
$sessionIds = @(& adb -s $DeviceId shell dumpsys media_session 2>&1 |
Select-String 'media-session com\.lxh\.qingting_player/media-session/(\d+)' |
ForEach-Object { $_.Matches[0].Groups[1].Value } | Sort-Object -Unique)
if ($sessionIds.Count -eq 1) { Write-Ok "MediaSession 唯一:$($sessionIds[0])" }
elseif ($sessionIds.Count -eq 0) { Write-Host ' -- 还没有 MediaSession(未开始播放,属正常)' -ForegroundColor DarkGray }
else { Write-Bad "出现 $($sessionIds.Count) 个 MediaSession:$($sessionIds -join ', ')"; $failed = $true }
# ---------- 崩溃 / 加载失败 ----------
Write-Step '崩溃与原生库'
$bad = $log | Select-String 'FATAL EXCEPTION|UnsatisfiedLinkError|Cannot load MediaKitAndroidHelper|Could not load'
if ($bad) { $bad | Select-Object -First 5 | ForEach-Object { Write-Bad $_.Line.Trim() }; $failed = $true } else { Write-Ok '无崩溃、无 so 加载失败' }
# ---------- 结果 ----------
Write-Host ''
if ($failed) {
Write-Host 'RESULT: FAIL —— 仍存在多实例或异常,完整日志:' -ForegroundColor Red
Write-Host " $logPath"
exit 1
}
Write-Host 'RESULT: PASS —— 单引擎单实例' -ForegroundColor Green
Write-Host "日志:$logPath"
Write-Host ''
Write-Host '还需要你手动确认(脚本无法代替耳朵和眼睛):' -ForegroundColor Yellow
Write-Host ' 1. 放一首歌,确认只有一路声音(没有重影/叠音)'
Write-Host ' 2. 按通知栏暂停/播放,确认播放页状态同步变化'
Write-Host ' 3. 拖通知栏进度条,确认播放页进度跟着走'