Android Question Script to check compatibility 16kb

MarcoRome

Expert
Licensed User
Longtime User
As the title suggests, here's a script to check 16kb compatibility (for those who don't use Android Studio's APK Analyzer).

The script analyzes apk, aar, aab or zip files.

You need to download and unzip android-ndk-r28c-windows.zip, which you can find at this link: ( https://developer.android.com/ndk/downloads?hl=en )
After unzipping it, you can modify the script with your own path.
The script runs in Windows PowerShell. So, after running the command cmd ... and typing PowerShell or
Shift+right-clicking in the folder → "Open PowerShell window here".
Type:

PS F:\downloadF> .\check-16kb.ps1 -ArchivePath "F:\DownloadF\testpdf\name.apk"

if your script is blocked you can execute this comand:

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
and repeat

PS F:\downloadF> .\check-16kb.ps1 -ArchivePath "F:\DownloadF\testpdf\name.apk"

The resul will be:

Negative (KO) if inside the arm64-v8a directory it will find libraries not aligned to 16kb
1756389097625.png

if the files arent aligned it will give their name ( look above )

or Positive (OK) if inside the arm64-v8a directory it will find libraries aligned to 16kb

1756389170002.png



(Of course, the path is yours, i.e., where the check-16kb.ps1 file was placed.)
Also inside the script insert your path (line 11)

This is the script:

B4X:
<# check-16kb-arm64.ps1
   Controlla SOLO le .so nella cartella arm64-v8a
   Verifica che TUTTI i segmenti PT_LOAD abbiano Alignment >= 16384 (16 KB).
#>

param(
  [Parameter(Mandatory = $true)]
  [Alias('ArchivePath')]
  [string]$Path,

  [string]$Readobj = "F:\android-ndk-r28c\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-readobj.exe",
  [string]$ReportPath,
  [int]$MinAlign = 16384
)

function Get-PtLoadAlignments {
  param([string]$SoPath, [string]$ReadobjExe)

  $result = New-Object PSObject -Property @{ Alignments = @(); Error = $null }

  $out = & $ReadobjExe --program-headers $SoPath 2>&1
  if ($LASTEXITCODE -ne 0) {
    $result.Error = ("llvm-readobj exit code {0}: {1}" -f $LASTEXITCODE, $SoPath)
    return $result
  }

  $reTypeLoad  = '^\s*Type:\s*(?:PT_)?LOAD\b'
  $reAnyType   = '^\s*Type:\s*\S+'
  $reAlignment = '^\s*Align(?:ment)?:\s*(0x[0-9A-Fa-f]+|\d+)'

  $inLoad = $false
  foreach ($line in ($out -split "`n")) {
    $l = $line.TrimEnd()

    if ($l -match $reTypeLoad) { $inLoad = $true; continue }
    if ($l -match $reAnyType)  { $inLoad = $false; continue }

    if ($inLoad -and ($l -match $reAlignment)) {
      $val = $Matches[1]
      if ($val -like '0x*') { $n = [Convert]::ToInt32($val,16) } else { $n = [int]$val }
      $result.Alignments += $n
    }
  }
  return $result
}

function Get-SoResult {
  param([string]$SoPath, [string]$ReadobjExe, [int]$MinAlign)

  $r = Get-PtLoadAlignments -SoPath $SoPath -ReadobjExe $ReadobjExe
  $aligns = $r.Alignments

  $ok = $true
  $reason = $null
  if ($r.Error) {
    $ok = $false; $reason = $r.Error
  } elseif ($aligns.Count -eq 0) {
    $ok = $false; $reason = "nessun segmento PT_LOAD trovato"
  } else {
    foreach ($a in $aligns) {
      if ($a -lt $MinAlign) { $ok = $false; $reason = ("PT_LOAD < {0}" -f $MinAlign); break }
    }
  }

  return New-Object PSObject -Property @{
    File       = $SoPath
    Alignments = $aligns
    OK         = $ok
    Reason     = $reason
  }
}

# --- Controlli preliminari ---
if (!(Test-Path -LiteralPath $Readobj)) { throw ("llvm-readobj.exe non trovato: {0}" -f $Readobj) }
if (!(Test-Path -LiteralPath $Path))    { throw ("Percorso non trovato: {0}" -f $Path) }

$AllLines = New-Object System.Collections.ArrayList
$FailList = New-Object System.Collections.ArrayList

# --- Determina i file da analizzare (SOLO arm64-v8a) ---
$TempRoot = $null
$soFiles = @()

if ((Get-Item -LiteralPath $Path).PSIsContainer) {
  $soFiles = Get-ChildItem -Recurse -Path $Path -Filter *.so | Where-Object { $_.FullName -match "arm64-v8a" } | Select-Object -Expand FullName
} else {
  $ext = [IO.Path]::GetExtension($Path).ToLower()
  if ($ext -eq ".so") {
    if ($Path -match "arm64-v8a") { $soFiles = ,(Resolve-Path -LiteralPath $Path).Path }
  } elseif ($ext -in @(".aar",".apk",".aab",".zip")) {
    $TempRoot = Join-Path $env:TEMP ("check16kb_" + (Get-Random))
    New-Item -ItemType Directory -Path $TempRoot | Out-Null
    $ZipCopy = Join-Path $TempRoot "archive.zip"
    Copy-Item -LiteralPath $Path -Destination $ZipCopy -Force
    Expand-Archive -LiteralPath $ZipCopy -DestinationPath $TempRoot -Force
    $soFiles = Get-ChildItem -Recurse -Path $TempRoot -Filter *.so | Where-Object { $_.FullName -match "arm64-v8a" } | Select-Object -Expand FullName
  } else {
    throw ("Estensione non supportata: {0}" -f $ext)
  }
}

if (!$soFiles -or $soFiles.Count -eq 0) {
  if ($TempRoot) { Remove-Item -Recurse -Force $TempRoot -ErrorAction SilentlyContinue }
  throw "Nessuna .so trovata nella cartella arm64-v8a."
}

# --- Analisi ---
foreach ($so in $soFiles) {
  $res = Get-SoResult -SoPath $so -ReadobjExe $Readobj -MinAlign $MinAlign

  [void]$AllLines.Add($res.File)
  [void]$AllLines.Add(("    PT_LOAD Alignments: {0}" -f $(if($res.Alignments){ ($res.Alignments -join ', ') }else{'<none>' })))
  if ($res.OK) {
    [void]$AllLines.Add(("    Risultato: OK (>= {0})" -f $MinAlign))
  } else {
    $msg = "    Risultato: NON allineato"
    if ($res.Reason) { $msg += " - " + $res.Reason }
    [void]$AllLines.Add($msg)
    [void]$FailList.Add($res.File)
  }
  [void]$AllLines.Add("")
}

# --- Pulizia e report ---
if ($TempRoot) { Remove-Item -Recurse -Force $TempRoot -ErrorAction SilentlyContinue }
if ($ReportPath) { $AllLines | Out-File -FilePath $ReportPath -Encoding UTF8 }

# --- Output finale ---
if ($FailList.Count -eq 0) {
  Write-Host ("OK: tutte le .so in arm64-v8a hanno PT_LOAD con Alignment >= {0}." -f $MinAlign)
  if ($ReportPath) { Write-Host ("Report salvato in: {0}" -f $ReportPath) }
  exit 0
} else {
  Write-Host ("KO: file arm64-v8a non conformi (almeno un PT_LOAD < {0}):" -f $MinAlign)
  $FailList | ForEach-Object { Write-Host (" - {0}" -f $_) }
  if ($ReportPath) { Write-Host ("Report completo in: {0}" -f $ReportPath) }
  exit 2
}

Save the same in a text file named check-16kb.ps1 ( in attachment if you want )
P.S.: Written with the help of chatgpt and after a few things to fix it works
Bye
 

Attachments

  • check-16kb.zip
    2 KB · Views: 32
Last edited:

Alex_197

Well-Known Member
Licensed User
Longtime User
To fix the blocked problem I ran this command
B4X:
 Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted
 
Upvote 0

Shelby

Well-Known Member
Licensed User
Longtime User
Do we put that script in a particular module? Do we make a new special module? Do we need to do this with each and every app? Maybe one App's use will spread the script throughout all IDEs for all apps of a developer?
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
Do we put that script in a particular module? Do we make a new special module? Do we need to do this with each and every app? Maybe one App's use will spread the script throughout all IDEs for all apps of a developer?
No, all you need is APK for your app. The scripts has to be installed on your computer and you will run them on the same computer.
 
Upvote 0

Shelby

Well-Known Member
Licensed User
Longtime User
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy UnrestricteI
[/QUOTE]

I guess that runs in a command prompt; I'll try it. Afterward I can't see if it had any effect.
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
Can you give some idea where on a person's computer the script has to be installed? Thanks
what I did - I created an empty folder, put my apk into, then downloaded check-16.zip and unpacked into the same folder and finally downloaded from this link https://developer.android.com/ndk/downloads?hl=en android-ndk-r28c-windows.zip, and also unpacked into the same folder
 

Attachments

  • screen1.png
    screen1.png
    9.4 KB · Views: 10
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy UnrestricteI

I guess that runs in a command prompt; I'll try it. Afterward I can't see if it had any effect.
[/QUOTE]
no, you need from the command prompt to start the PowerShell first and then from the PowerShell run this command
 
Upvote 0

Shelby

Well-Known Member
Licensed User
Longtime User
One of the experienced members here (Geoff T) had me get this file from Zetetic.net: "sqlcipher-android-4.10.0.aar" and place it in my additional libraries folder. I removed the old file like it and all seemed to be accepted by Google Play. So far so good and my app was described by a Google Play email as: Your update is live in the subject line.

Note that this allowed me to continue using SQLCipher in my SQLite app. We'll see if it holds in the coming days or months.
 
Last edited:
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
One of the experienced members here (Geoff T) had me get this file from Zetetic.net: "sqlcipher-android-4.10.0.aar" and place it in my additional libraries folder. I removed the old file like it and all seemed to be accepted by Google Play. So far so good and my app was described by a Google Play email as: Your update is live in the subject line.

Note that this allowed me to continue using SQLCipher in my SQLite app. We'll see if it holds in the coming days or months.
Great news - can you share this aar file with us? Also, what file did you replace with this sqlcipher-android-4.10.0.aar?

Thank you.
 
Upvote 0
Top