From 3639aa9cbfc8b1a8f972c5dae5dfbc08a36e4079 Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Sun, 11 Oct 2026 18:48:48 +0900 Subject: [PATCH] =?UTF-8?q?APK=20=EA=B2=80=EC=82=AC:=20dex=20=EC=97=90=20G?= =?UTF-8?q?eneratedPluginRegistrant=20=EA=B0=80=20=EC=9E=88=EB=8A=94?= =?UTF-8?q?=EC=A7=80=20(tool/check=5Fapk.ps1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 묶음5 시험판 (a192ef6) 이 켜자마자 꺼졌다 ('JNI is not initialized … too early'). 생성 파일 GeneratedPluginRegistrant.java 를 지운 뒤 flutter build apk --no-pub 로 빌드해 플러그인 등록이 dex 에서 빠진 것 (버그 수정 - 빌드 절차). 빌드 뒤 이 검사로 막는다. Co-Authored-By: Claude Opus 5.5 --- tool/check_apk.ps1 | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tool/check_apk.ps1 diff --git a/tool/check_apk.ps1 b/tool/check_apk.ps1 new file mode 100644 index 0000000..3589bb3 --- /dev/null +++ b/tool/check_apk.ps1 @@ -0,0 +1,47 @@ +# APK 검사 (P0, 10/11): 플러그인 등록 (GeneratedPluginRegistrant) 이 dex 에 들어 있는지 본다. +# - 이 파일이 빠지면 플러그인이 하나도 등록되지 않아 켜자마자 꺼진다 ('JNI is not initialized … too early', 묶음5 a192ef6 시험판). +# - 원인: android\app\src\main\java\io\flutter\plugins\GeneratedPluginRegistrant.java (git 밖, 생성 파일) 를 지운 뒤 +# flutter build apk --no-pub 로 빌드하면 다시 만들어지지 않는다. 지웠으면 --no-pub 없이 빌드하거나 먼저 flutter pub get. +# 사용: powershell -ExecutionPolicy Bypass -File tool\check_apk.ps1 -Apk build\app\outputs\flutter-apk\app-release.apk +param( + [Parameter(Mandatory = $true)][string]$Apk +) +$ErrorActionPreference = 'Stop' +Add-Type -AssemblyName System.IO.Compression.FileSystem +$Apk = (Resolve-Path $Apk).Path +$want = [System.Text.Encoding]::ASCII.GetBytes('Lio/flutter/plugins/GeneratedPluginRegistrant;') + +# 바이트 배열 안에 [needle] 이 있는지 +function Test-Bytes([byte[]]$hay, [byte[]]$needle) { + $first = $needle[0] + $i = [Array]::IndexOf($hay, $first) + while ($i -ge 0 -and $i -le $hay.Length - $needle.Length) { + $ok = $true + for ($k = 1; $k -lt $needle.Length; $k++) { + if ($hay[$i + $k] -ne $needle[$k]) { $ok = $false; break } + } + if ($ok) { return $true } + $i = [Array]::IndexOf($hay, $first, $i + 1) + } + return $false +} + +$zip = [System.IO.Compression.ZipFile]::OpenRead($Apk) +try { + $dexes = @($zip.Entries | Where-Object { $_.FullName -match '^classes\d*\.dex$' }) + if ($dexes.Count -eq 0) { throw "dex 가 없습니다: $Apk" } + $found = $null + foreach ($e in $dexes) { + $s = $e.Open() + $ms = New-Object System.IO.MemoryStream + try { $s.CopyTo($ms) } finally { $s.Dispose() } + if (Test-Bytes $ms.ToArray() $want) { $found = $e.FullName; break } + } +} finally { + $zip.Dispose() +} +if (-not $found) { + Write-Host "실패: GeneratedPluginRegistrant 가 dex 에 없습니다 (켜자마자 꺼지는 APK). flutter pub get 뒤 --no-pub 없이 다시 빌드하세요." -ForegroundColor Red + exit 1 +} +Write-Host "통과: GeneratedPluginRegistrant 있음 ($found)"