Skip to main content

Overview

Custom device naming allows you to assign friendly, memorable names to your Android devices instead of seeing serial numbers or auto-detected model names. Names are persistent across sessions and shared between the web interface and CLI tool.

Why Custom Names?

Device identifiers can be hard to remember:
  • Serial numbers: R58N123456A (cryptic)
  • IP addresses: 192.168.1.100:5555 (changes with network)
  • Auto-detected names: Samsung SM-G991B (technical model codes)
Custom names solve this:
  • Personal devices: “My Phone”, “Work Phone”
  • Testing devices: “Test Device - Android 13”, “QA Phone”
  • Family devices: “Dad’s Tablet”, “Kids’ Phone”
Custom names appear throughout the interface, in device lists, dropdowns, and connection dialogs.

Setting Device Names

Via Web Interface

  1. Open device list in the web interface
  2. Click the device you want to rename
  3. Click the pencil/edit icon next to the device name
  4. Enter your custom name in the modal dialog
  5. Click Save - the name appears instantly

Via CLI

The batch script (apk-downloader.bat) includes a device naming menu:
1) Listar dispositivos conectados
2) Ver información del dispositivo
3) Conectar dispositivo por WiFi
4) Listar aplicaciones
5) Extraer APK
6) Compilar XAPK
7) Asignar nombre personalizado al dispositivo
8) Salir
Select option 7 to assign a custom name to any connected device.

Storage System

Custom names are stored in device-names.json in the application root:
{
  "R58N123456A": "My Galaxy S21",
  "192.168.1.100:5555": "Office Test Device",
  "adb-ABC123._adb-tls-connect._tcp": "Wireless Debug Phone"
}

Storage Format

  • Key: Device serial number (USB) or connection string (WiFi)
  • Value: Custom name string
  • Encoding: UTF-8 JSON with pretty-printing (2-space indent)
The serial number is the unique identifier, even if the device connects via different methods (USB vs WiFi).

API Implementation

Get All Device Names

app.get('/api/device-names', (req, res) => {
  res.json({ names: loadDeviceNames() });
});

function loadDeviceNames() {
  if (_deviceNamesCache) return _deviceNamesCache;
  try {
    if (fs.existsSync(NAMES_FILE)) {
      _deviceNamesCache = JSON.parse(fs.readFileSync(NAMES_FILE, 'utf8'));
      return _deviceNamesCache;
    }
  } catch { }
  _deviceNamesCache = {};
  return _deviceNamesCache;
}

Set Device Name

app.put('/api/device-names/:serial', (req, res) => {
  const serial = decodeURIComponent(req.params.serial);
  const { name } = req.body;
  
  if (!name || !name.trim()) {
    return res.status(400).json({ error: 'El nombre es requerido' });
  }
  
  const names = loadDeviceNames();
  names[serial] = name.trim();
  writeDeviceNames(names);
  
  res.json({ ok: true });
});

Delete Device Name

app.delete('/api/device-names/:serial', (req, res) => {
  const serial = decodeURIComponent(req.params.serial);
  const names = loadDeviceNames();
  delete names[serial];
  writeDeviceNames(names);
  res.json({ ok: true });
});
curl http://localhost:3000/api/device-names

Display Priority

When displaying devices, APK Extractor follows this priority order:
  1. Custom Name (if set)
  2. Auto-detected Label (brand + model)
  3. Serial Number (fallback)
const customName = deviceNames[serial] || null;
return { 
  serial, 
  status: 'device', 
  label,  // Auto-detected brand + model
  ip, 
  wireless: isWireless, 
  customName  // Takes priority in UI
};

Display Examples

Custom NameAuto-detectedSerialDisplay
”My Phone”Samsung Galaxy S21R58N123456AMy Phone
nullSamsung Galaxy S21R58N123456ASamsung Galaxy S21
nullnullR58N123456AR58N123456A
""Samsung Galaxy S21R58N123456ASamsung Galaxy S21
Custom names always appear first when set, with the technical details shown as secondary information.

Shared Across Interfaces

The device-names.json file is shared between:
  • Web interface (server.js + public/app.js)
  • CLI tool (apk-downloader.bat)
Changes made in either interface immediately affect the other:
REM CLI batch script reads the same JSON file
if exist "%NAMES_FILE%" (
    REM Load custom names
    for /f "tokens=1,2 delims=:" %%a in (%NAMES_FILE%) do (
        if "%%a"=="%SERIAL%" set CUSTOM_NAME=%%b
    )
)

Synchronization

  • No polling needed: Both interfaces read from same file
  • Instant updates: Changes persist immediately to disk
  • Cache invalidation: In-memory cache updates on write
  • Crash-safe: JSON written atomically with pretty-printing

Caching Strategy

APK Extractor caches device names in memory for performance:
let _deviceNamesCache = null;  // In-memory cache

function loadDeviceNames() {
  if (_deviceNamesCache) return _deviceNamesCache;
  // Load from disk
  _deviceNamesCache = JSON.parse(fs.readFileSync(NAMES_FILE, 'utf8'));
  return _deviceNamesCache;
}

function writeDeviceNames(names) {
  _deviceNamesCache = names;  // Update cache
  fs.writeFileSync(NAMES_FILE, JSON.stringify(names, null, 2), 'utf8');
}

Cache Benefits

  • Fast reads: No disk I/O after first load
  • Instant updates: Cache updates on every write
  • Low memory: Single object, minimal footprint
  • No stale data: Write-through caching ensures consistency

Use Cases

{
  "R58N123456A": "Daily Driver (S21)",
  "192.168.1.100:5555": "Old Backup Phone",
  "emulator-5554": "Android Emulator - Pixel 6"
}
Keep track of multiple personal devices for app testing and data transfer.
{
  "R58N123456A": "QA - Android 13 - Sprint",
  "R58N789012B": "QA - Android 11 - Verizon",
  "R58N345678C": "QA - Android 14 Beta",
  "192.168.1.50:5555": "CI/CD Test Device"
}
Identify test devices by Android version, carrier, or purpose.
{
  "R58N123456A": "Dad's Work Phone",
  "R58N789012B": "Mom's Galaxy",
  "R58N345678C": "Kids' Tablet",
  "R58N901234D": "Guest Phone"
}
Manage app extraction for multiple family members’ devices.

Validation

The API validates custom names:
if (!name || !name.trim()) {
  return res.status(400).json({ error: 'El nombre es requerido' });
}

Validation Rules

  • Required: Name cannot be empty or whitespace-only
  • Trimmed: Leading/trailing whitespace removed automatically
  • No length limit: Any length accepted (reasonable names recommended)
  • Unicode support: Full UTF-8 character support (emojis, special chars)
Empty strings are rejected, but deleting a name (DELETE request) is allowed and removes the custom name entirely.

Best Practices

  1. Be descriptive: Include device model or purpose
  2. Keep it short: Long names may truncate in narrow UI
  3. Use consistent naming: Apply a naming scheme across devices
  4. Avoid special characters: Stick to alphanumeric for compatibility
  5. Update when needed: Change names as device purposes change

Good Examples

  • “My Phone”
  • “Test Device - Android 13”
  • “Office Galaxy S21”
  • “Dev Phone (Rooted)“

Avoid

  • "" (empty)
  • “Device” (too generic)
  • “192.168.1.100:5555” (defeats the purpose)
  • Very long names that describe entire device specs

Build docs developers (and LLMs) love