南锋

南奔万里空,脱死锋镝余

如何判断自己的apk是否支持16KB

前言

自 2025年11月1日起,提交到Google Play且以Android 15及更高版本为目标平台的所有新应用和现有应用更新都必须在 64 位设备上支持 16 KB 页面大小。

判断方法

判断应用是否含有native代码

直接查看APK内容

  1. 找到APK文件,将apk改名为.zip,并解压
  2. 打开解压后的文件夹,看是否有类似于下面的路径
    1
    2
    lib\arm64-v8a\libcocos.so
    lib\arm64-v8a\libswappy.so
  3. 如果没有.so文件,说明支持16K,不需要做任何处理
  4. 如果有.so文件,则需要判断是否支持16K

判断.so是否支持16K页面大小

Google官方要求.so文件的ELF段对齐必须支持16KB(16384字节)。也就是说:

  • ELF文件的p_align字段(Program Header中)必须是0x4000或其倍数
  1. 使用readelf命令查看
    如果你有Android NDK,可以执行命名:
    1
    readelf -l yourlib.so 
    这里是readllef 是 readelf.exe文件,具体位置在:
    ..\ndk\21.1.6352462\toolchains\llvm\prebuilt\windows-x86_64\aarch64-linux-android\bin\readelf.exe,具体看你自己的ndk文件位置。
    输入如下:
    输出示意图
    看LOAD后面数字的最后一列:
  • 如果是 1000 → 表示对齐 4K ❌(不兼容 16K)
  • 如果是 4000 或更大 → ✅ 支持 16K
    👉 如果所有 LOAD 段都是 4000 或更大,则该 .so 文件兼容 16K。
    我这里说明apk不支持16KB
  1. 使用脚本批量扫描apk中的.so文件
    复制下面脚本,保存为check_so_align.ps1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    param(
    [string]$ApkPath = "apk路径",
    [string]$ReadElfPath = "readelf.exe路径" # 上面有给出路径地址
    )

    # 临时解压目录
    $tempDir = Join-Path $env:TEMP ("apk_extract_" + [System.Guid]::NewGuid().ToString())
    Write-Host "Extracting APK to temporary directory: $tempDir"

    # 使用 .NET 方法解压 APK
    Add-Type -AssemblyName System.IO.Compression.FileSystem
    try {
    [System.IO.Compression.ZipFile]::ExtractToDirectory($ApkPath, $tempDir)
    } catch {
    Write-Host "Failed to extract APK. Make sure the file exists and is not corrupted." -ForegroundColor Red
    exit
    }

    # 查找 .so 文件
    $soFiles = Get-ChildItem -Path $tempDir -Recurse -Include *.so
    if ($soFiles.Count -eq 0) {
    Write-Host "No .so files found. Please check if the APK contains native libraries."
    Remove-Item -Path $tempDir -Recurse -Force
    exit
    }

    Write-Host "Checking LOAD segments for 16KB alignment..."

    $notAligned = @()

    foreach ($file in $soFiles) {
    $output = & $ReadElfPath -l $file.FullName 2>$null
    if ($LASTEXITCODE -ne 0) {
    Write-Host "Cannot read $($file.Name), skipping."
    continue
    }

    $fileAligned = $true
    foreach ($line in $output) {
    # 只检查 LOAD 段
    if ($line -match "LOAD\s+.*\s+(\S+)$") {
    $alignHex = $matches[1]
    $alignValue = 0
    try { $alignValue = [Convert]::ToInt32($alignHex,16) } catch {}
    if ($alignValue -lt 0x4000) {
    $fileAligned = $false
    break
    }
    }
    }

    if (-not $fileAligned) {
    $notAligned += $file
    }
    }

    if ($notAligned.Count -eq 0) {
    Write-Host "All .so files meet 16KB LOAD segment alignment!" -ForegroundColor Green
    } else {
    Write-Host "The following .so files are NOT aligned to 16KB in LOAD segments:" -ForegroundColor Red
    foreach ($f in $notAligned) { Write-Host " - $($f.FullName)" }
    }

    # 删除临时目录
    Remove-Item -Path $tempDir -Recurse -Force

    打开终端,直接执行
    1
    .\check_so_align.ps1
    输出结果如下:
    输出示意图
+