lame

Android Support

This document explains how Android support works in Lame, why the app prefers MTP, and how the new ADB fallback behaves when MTP cannot enumerate the device.


Summary

Lame now has two Android backends:

The UI still exposes a single Android device row. AndroidDeviceManager chooses the backend at runtime and updates the row label to show whether the current session is using MTP or ADB.


Why Android Needs A Fallback

On macOS, Android support is fundamentally different from iPhone support:

MTP works well when the phone is unlocked and set to File Transfer, but in practice it can fail for reasons outside the app’s control:

ADB is not a replacement for the normal Android path. It is a recovery path when the user already has USB Debugging enabled and the phone has authorized the Mac.


Backend Choice

Preferred path: MTP

Lame first tries the existing libmtp flow:

  1. detect Android presence via ioreg
  2. confirm device identity via mtp-detect
  3. enumerate via mtp-files
  4. use mtp-thumb, mtp-getfile, and mtp-delfile for operations

This is still the best default because it matches the standard Android user flow and does not require Developer Options.

Fallback path: ADB

If MTP enumeration fails and adb is installed, Lame tries the ADB backend:

  1. detect an authorized device with adb devices -l
  2. recursively walk /sdcard with adb shell find
  3. fetch file metadata with stat when available
  4. use adb pull for copy and thumbnail fallback
  5. use adb shell rm -rf -- <path> for delete

This fallback is intentionally scoped to /sdcard, not the full device filesystem. That keeps the implementation focused on the user-visible shared storage area the app is meant to browse.


Runtime Flow

flowchart TD
    A[Poll via ioreg] --> B{Android device visible?}
    B -- No --> A
    B -- Yes --> C[Try mtp-detect]
    C --> D[User selects Android row]
    D --> E[Try mtp-files]
    E --> F{Enumeration succeeded?}
    F -- Yes --> G[Use MTP backend]
    F -- No --> H{ADB installed and authorized?}
    H -- No --> I[Show retryable error]
    H -- Yes --> J[Walk /sdcard over ADB]
    J --> K[Use ADB backend]

Supported Operations

Both Android backends support the same user-visible surfaces:

The implementation differs by backend.

MTP operations

ADB operations


Data Model Impact

To support both backends without duplicating UI code, AndroidMediaFile now wraps a backend-neutral location:

The UI selects rows using a stable string selectionID, so MTP object IDs and ADB paths can both participate in selection, navigation, copy, and delete flows through the same views.


Limitations

MTP remains the better path

ADB fallback is useful, but it has tradeoffs:

ADB metadata depends on the device shell

Lame tries to recover file size and modified date with stat, but shell capabilities vary across Android builds. When metadata is unavailable, the app still browses the file tree and shows unknown size/date where needed.

Tool installation is still required

Android support now works with either of these setups:

If neither toolchain is installed, the sidebar shows a single install hint covering both.


Files Involved

The fallback touches these core files:


Setup Notes

For normal Android usage:

For fallback usage:

If both are installed, Lame will prefer MTP and only fall back to ADB when MTP enumeration fails.