Files
QingTing-Player/tools/device-check.ps1
T
lxh2875931338 6445ee94bf fix(playback): 播放中不再向系统上报 idle,修复播放设备页显示未在播放
audio_service 把 idle 映射成 PlaybackState.STATE_NONE,之前用 duration>0 判断,
时长尚未解析出来时会一直上报 NONE。改为 playing || duration>0 即视为 ready。

设备验证(MEIZU 21 Pro / Android 16):
  播放 -> state=PLAYING(3),暂停 -> state=PAUSED(2),不再出现 NONE(0)。

同时加固 device-check.ps1:确认进程真正退出后再抓冷启动日志,最多重试两次。
2026-10-22 22:57:34 +08:00

134 lines
6.5 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 '冷启动并抓取日志'
$logPath = Join-Path $root 'build\device-check-last.log'
$creates = 0
# Flyme 有时不会立刻杀掉带前台服务的进程,导致抓不到启动日志:确认进程消失 + 最多重试两次
for ($attempt = 1; $attempt -le 2; $attempt++) {
& adb -s $DeviceId shell am force-stop $pkg | Out-Null
$deadline = (Get-Date).AddSeconds(6)
while ((& adb -s $DeviceId shell pidof $pkg) -and (Get-Date) -lt $deadline) {
Start-Sleep -Milliseconds 300
}
& adb -s $DeviceId logcat -c
& adb -s $DeviceId shell am start -W -n "$pkg/.MainActivity" 2>&1 | Out-Null
Start-Sleep -Seconds $WaitSeconds
& adb -s $DeviceId logcat -d -v time > $logPath
# 注意:PS 5.1 的 > 重定向写出的是 UTF-16LE(带 BOM),读取时不要强制 utf8
$log = Get-Content $logPath
$text = $log -join "`n"
$creates = ([regex]::Matches($text, '\[PlaybackService\] 单例创建')).Count
if ($creates -ge 1) { break }
Write-Host " (第 $attempt 次没抓到冷启动日志,进程可能没退干净,重试)" -ForegroundColor DarkYellow
}
# ---------- 判定 ----------
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)
$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. 拖通知栏进度条,确认播放页进度跟着走'