Skip to content

Instantly share code, notes, and snippets.

@samuelcaldas
Created November 17, 2025 13:44
Show Gist options
  • Select an option

  • Save samuelcaldas/58abc3fdd350b82dba11bc7cdd11b569 to your computer and use it in GitHub Desktop.

Select an option

Save samuelcaldas/58abc3fdd350b82dba11bc7cdd11b569 to your computer and use it in GitHub Desktop.
<#
.SYNOPSIS
Script PowerShell para duplicar aplicativos instalados em dispositivos Samsung Android usando segundo usuário.
.DESCRIPTION
Este script permite instalar uma cópia de aplicativos já instalados no dispositivo Android
em um segundo usuário, incluindo suporte para split APKs.
.NOTES
Autor: Script gerado para duplicação de apps Android
Requisitos: ADB no PATH do sistema
#>
# Configurações de cores e interface
$Host.UI.RawUI.WindowTitle = "Android App Duplicator"
$ErrorActionPreference = "Stop"
# Função para verificar se ADB está disponível
function Test-AdbAvailable {
try {
$adbVersion = adb version 2>&1
return $true
}
catch {
Write-Host "`n[ERRO] ADB não encontrado no PATH do sistema." -ForegroundColor Red
Write-Host "Por favor, instale o ADB e adicione ao PATH." -ForegroundColor Yellow
return $false
}
}
# Função para listar dispositivos conectados
function Get-AdbDevices {
$devices = adb devices | Select-Object -Skip 1 | Where-Object { $_ -match "\t" }
$deviceList = @()
foreach ($device in $devices) {
if ($device -match "^([^\s]+)\s+device") {
$deviceList += $matches[1]
}
}
return $deviceList
}
# Função para selecionar dispositivo
function Select-AdbDevice {
param (
[string[]]$Devices
)
if ($Devices.Count -eq 0) {
Write-Host "`n[ERRO] Nenhum dispositivo Android conectado." -ForegroundColor Red
Write-Host "Por favor, conecte um dispositivo com USB Debugging habilitado." -ForegroundColor Yellow
return $null
}
if ($Devices.Count -eq 1) {
Write-Host "`n[INFO] Dispositivo detectado: $($Devices[0])" -ForegroundColor Cyan
return $Devices[0]
}
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host " MÚLTIPLOS DISPOSITIVOS DETECTADOS" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
for ($i = 0; $i -lt $Devices.Count; $i++) {
Write-Host " [$($i + 1)] $($Devices[$i])" -ForegroundColor White
}
Write-Host " [0] Cancelar" -ForegroundColor Yellow
Write-Host ""
do {
$selection = Read-Host "Selecione o dispositivo (0-$($Devices.Count))"
$selectionNum = 0
$validInput = [int]::TryParse($selection, [ref]$selectionNum)
} while (-not $validInput -or $selectionNum -lt 0 -or $selectionNum -gt $Devices.Count)
if ($selectionNum -eq 0) {
return $null
}
return $Devices[$selectionNum - 1]
}
# Função para obter usuários disponíveis no dispositivo
function Get-AndroidUsers {
param (
[string]$DeviceSerial
)
try {
$usersOutput = adb -s $DeviceSerial shell pm list users 2>&1
$users = @()
foreach ($line in $usersOutput) {
if ($line -match "UserInfo\{(\d+):[^:]+:") {
$userId = $matches[1]
$users += [PSCustomObject]@{
Id = [int]$userId
Info = $line
}
}
}
return $users
}
catch {
Write-Host "`n[ERRO] Falha ao listar usuários: $($_.Exception.Message)" -ForegroundColor Red
return @()
}
}
# Função para selecionar usuário secundário automaticamente
function Select-SecondaryUser {
param (
[string]$DeviceSerial
)
$users = Get-AndroidUsers -DeviceSerial $DeviceSerial
if ($users.Count -eq 0) {
Write-Host "`n[ERRO] Não foi possível listar usuários do dispositivo." -ForegroundColor Red
return $null
}
# Filtra usuários secundários (ID > 0)
$secondaryUsers = $users | Where-Object { $_.Id -gt 0 }
if ($secondaryUsers.Count -eq 0) {
Write-Host "`n[AVISO] Nenhum usuário secundário encontrado no dispositivo." -ForegroundColor Yellow
Write-Host "Por favor, crie um segundo usuário nas configurações do Android." -ForegroundColor Yellow
return $null
}
Write-Host "`n[INFO] Usuários encontrados:" -ForegroundColor Cyan
foreach ($user in $users) {
$userType = if ($user.Id -eq 0) { "Principal" } else { "Secundário" }
Write-Host " - $($user.Info) [$userType]" -ForegroundColor White
}
# Seleciona automaticamente o primeiro usuário secundário
$selectedUser = $secondaryUsers[0]
Write-Host "`n[INFO] Usuário secundário selecionado: ID $($selectedUser.Id)" -ForegroundColor Green
return $selectedUser.Id
}
# Função para obter lista de aplicativos com nomes amigáveis
function Get-InstalledApps {
param (
[string]$DeviceSerial
)
Write-Host "`n[INFO] Carregando lista de aplicativos instalados..." -ForegroundColor Cyan
try {
# Lista pacotes de terceiros com paths
$packagesOutput = adb -s $DeviceSerial shell pm list packages -3 -f --user 0 2>&1
$apps = @()
foreach ($line in $packagesOutput) {
if ($line -match "package:(.+)=(.+)$") {
$apkPath = $matches[1]
$packageName = $matches[2]
# Tenta obter o nome amigável usando dumpsys
$appLabel = $null
try {
$dumpsysOutput = adb -s $DeviceSerial shell "dumpsys package $packageName | grep -A 1 'labelRes='" 2>&1
# Fallback: usa o nome do pacote
$appLabel = $packageName
# Se não conseguir o nome amigável, usa o nome do pacote
if ([string]::IsNullOrWhiteSpace($appLabel) -or $appLabel -eq $packageName) {
# Tenta extrair o último componente do pacote como nome
$parts = $packageName -split "\."
if ($parts.Count -gt 0) {
$appLabel = $parts[-1]
}
}
}
catch {
$appLabel = $packageName
}
$apps += [PSCustomObject]@{
Index = $apps.Count + 1
Label = $appLabel
Package = $packageName
BasePath = $apkPath
}
}
}
return $apps | Sort-Object -Property Label
}
catch {
Write-Host "`n[ERRO] Falha ao listar aplicativos: $($_.Exception.Message)" -ForegroundColor Red
return @()
}
}
# Função para exibir menu de seleção de app
function Show-AppSelectionMenu {
param (
[array]$Apps
)
$pageSize = 15
$currentPage = 0
$totalPages = [Math]::Ceiling($Apps.Count / $pageSize)
while ($true) {
Clear-Host
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host " SELECIONE O APLICATIVO PARA DUPLICAR" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " Página $($currentPage + 1) de $totalPages" -ForegroundColor Yellow
Write-Host ""
$startIndex = $currentPage * $pageSize
$endIndex = [Math]::Min($startIndex + $pageSize, $Apps.Count)
for ($i = $startIndex; $i -lt $endIndex; $i++) {
Write-Host " [$($i + 1)] $($Apps[$i].Label)" -ForegroundColor White
Write-Host " Pacote: $($Apps[$i].Package)" -ForegroundColor DarkGray
}
Write-Host ""
Write-Host " [N] Próxima página [P] Página anterior [0] Cancelar" -ForegroundColor Yellow
Write-Host ""
$selection = Read-Host "Selecione uma opção"
if ($selection -eq "0") {
return $null
}
elseif ($selection -eq "N" -or $selection -eq "n") {
if ($currentPage -lt $totalPages - 1) {
$currentPage++
}
continue
}
elseif ($selection -eq "P" -or $selection -eq "p") {
if ($currentPage -gt 0) {
$currentPage--
}
continue
}
else {
$selectionNum = 0
$validInput = [int]::TryParse($selection, [ref]$selectionNum)
if ($validInput -and $selectionNum -gt 0 -and $selectionNum -le $Apps.Count) {
return $Apps[$selectionNum - 1]
}
else {
Write-Host "`n[ERRO] Seleção inválida. Pressione Enter para continuar..." -ForegroundColor Red
Read-Host
}
}
}
}
# Função para obter todos os APKs (base + splits)
function Get-AppApkPaths {
param (
[string]$DeviceSerial,
[string]$PackageName
)
Write-Host "`n[INFO] Obtendo caminhos dos APKs..." -ForegroundColor Cyan
try {
$pathOutput = adb -s $DeviceSerial shell pm path $PackageName 2>&1
$apkPaths = @()
foreach ($line in $pathOutput) {
if ($line -match "package:(.+)$") {
$apkPaths += $matches[1].Trim()
}
}
if ($apkPaths.Count -eq 0) {
Write-Host "[ERRO] Nenhum APK encontrado para o pacote." -ForegroundColor Red
return $null
}
Write-Host "[INFO] Encontrados $($apkPaths.Count) arquivo(s) APK:" -ForegroundColor Green
foreach ($path in $apkPaths) {
$fileName = Split-Path -Leaf $path
Write-Host " - $fileName" -ForegroundColor White
}
return $apkPaths
}
catch {
Write-Host "`n[ERRO] Falha ao obter caminhos dos APKs: $($_.Exception.Message)" -ForegroundColor Red
return $null
}
}
# Função para instalar app no usuário secundário
function Install-AppForUser {
param (
[string]$DeviceSerial,
[int]$UserId,
[string[]]$ApkPaths
)
Write-Host "`n[INFO] Iniciando instalação no usuário $UserId..." -ForegroundColor Cyan
try {
# Monta o comando de instalação
$installCmd = "adb -s $DeviceSerial shell pm install --user $UserId"
foreach ($apk in $ApkPaths) {
$installCmd += " `"$apk`""
}
Write-Host "[INFO] Executando instalação..." -ForegroundColor Cyan
# Executa a instalação
$result = Invoke-Expression $installCmd 2>&1
# Verifica o resultado
$success = $false
foreach ($line in $result) {
if ($line -match "Success") {
$success = $true
break
}
}
if ($success) {
Write-Host "`n[SUCESSO] Aplicativo instalado com sucesso no usuário secundário!" -ForegroundColor Green
return $true
}
else {
Write-Host "`n[ERRO] Falha na instalação." -ForegroundColor Red
Write-Host "Detalhes: $result" -ForegroundColor Yellow
return $false
}
}
catch {
Write-Host "`n[ERRO] Exceção durante instalação: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
# Função principal
function Main {
Clear-Host
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " ANDROID APP DUPLICATOR" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
# Verifica se ADB está disponível
if (-not (Test-AdbAvailable)) {
Read-Host "`nPressione Enter para sair"
exit 1
}
# Lista e seleciona dispositivo
Write-Host "`n[INFO] Verificando dispositivos conectados..." -ForegroundColor Cyan
$devices = Get-AdbDevices
$selectedDevice = Select-AdbDevice -Devices $devices
if ($null -eq $selectedDevice) {
Write-Host "`nOperação cancelada pelo usuário." -ForegroundColor Yellow
Read-Host "`nPressione Enter para sair"
exit 0
}
# Seleciona usuário secundário
$secondaryUser = Select-SecondaryUser -DeviceSerial $selectedDevice
if ($null -eq $secondaryUser) {
Read-Host "`nPressione Enter para sair"
exit 1
}
# Lista aplicativos instalados
$apps = Get-InstalledApps -DeviceSerial $selectedDevice
if ($apps.Count -eq 0) {
Write-Host "`n[ERRO] Nenhum aplicativo encontrado." -ForegroundColor Red
Read-Host "`nPressione Enter para sair"
exit 1
}
Write-Host "[SUCESSO] $($apps.Count) aplicativo(s) encontrado(s)." -ForegroundColor Green
Read-Host "`nPressione Enter para continuar"
# Exibe menu de seleção
$selectedApp = Show-AppSelectionMenu -Apps $apps
if ($null -eq $selectedApp) {
Write-Host "`nOperação cancelada pelo usuário." -ForegroundColor Yellow
Read-Host "`nPressione Enter para sair"
exit 0
}
Clear-Host
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host " INSTALANDO APLICATIVO" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " App: $($selectedApp.Label)" -ForegroundColor White
Write-Host " Pacote: $($selectedApp.Package)" -ForegroundColor White
Write-Host " Usuário: $secondaryUser" -ForegroundColor White
Write-Host ""
# Obtém caminhos dos APKs (incluindo splits)
$apkPaths = Get-AppApkPaths -DeviceSerial $selectedDevice -PackageName $selectedApp.Package
if ($null -eq $apkPaths) {
Read-Host "`nPressione Enter para sair"
exit 1
}
# Instala o aplicativo
$installSuccess = Install-AppForUser -DeviceSerial $selectedDevice -UserId $secondaryUser -ApkPaths $apkPaths
if ($installSuccess) {
Write-Host "`n========================================" -ForegroundColor Green
Write-Host " INSTALAÇÃO CONCLUÍDA!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host "`nO aplicativo foi duplicado para o usuário secundário." -ForegroundColor White
Write-Host "Troque para o usuário secundário no dispositivo para acessar." -ForegroundColor Yellow
}
else {
Write-Host "`n========================================" -ForegroundColor Red
Write-Host " INSTALAÇÃO FALHOU" -ForegroundColor Red
Write-Host "========================================" -ForegroundColor Red
Write-Host "`nVerifique as mensagens de erro acima." -ForegroundColor Yellow
}
Read-Host "`nPressione Enter para sair"
}
# Executa a função principal
Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment