chore(tools): 增加真机自检脚本 device-check.ps1
一键完成:安装 debug APK → 冷启动 → 抓 logcat → 校验单实例 (PlaybackService / serviceId / Player / MediaSession 各只允许 1 个), 并检查崩溃与 libmediakitandroidhelper.so 加载失败。
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
#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. 拖通知栏进度条,确认播放页进度跟着走'
|
||||
Reference in New Issue
Block a user