Skip to content

About

Create custom infrared (IR) remotes using hex codes, raw signals, or import Flipper Zero, LIRC, and IRPLUS files

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

SwiftRemote

SwiftRemote icon

SwiftRemote

Universal IR Remote for Android
SwiftRemote is an Android application for creating, managing, and transmitting infrared (IR) signals through multiple output methods, including a device’s built-in IR emitter, supported USB IR dongles, and audio-to-IR LED adapters.

The app enables users to build fully custom remotes, discover unknown IR codes through guided brute-force tools, and seamlessly manage IR configurations. It also supports importing IR signals from Flipper Zero .ir files, IRPLUS .irplus / XML files, and LIRC .conf / .cfg / .lirc files, making it easy to reuse and adapt existing IR libraries across devices.

It also lets you search ready-made remotes and import one without manually downloading and moving files first. For supported USB learning dongles, Learning Mode can capture a signal from a physical remote, preview it, and save it into a new or existing remote.

SwiftRemote is designed to be flexible, hardware-agnostic, and user-friendly, while remaining powerful enough for advanced users who need precise control over IR protocols and signal timing.

GitHub License Build APK Issues Latest release Android Version

SwiftRemote is a fork of IR Blaster by KaijinLab Inc. It is not published on Google Play or F-Droid — releases are the signed APKs attached to this repository, and installed builds update themselves from there.

Overview

  • Multiple transmit paths (no built‑in IR required):
    • Internal (ConsumerIrManager) when the device has a hardware IR emitter
    • USB IR dongle (with discovery, permission, and bulk transfers)
    • Audio IR (mono 1‑LED or stereo anti‑phase 2‑LED adapters)
  • Rich protocol support and a raw‑signal mode for precise mark/space patterns
  • Import/export of remotes, including Flipper Zero .ir, IRPLUS .irplus / XML, LIRC .conf / .cfg / .lirc files, .json remotes, JSON backups, and a built-in browser for ready-made remotes
  • Learning Mode for supported USB learning dongles, with capture, preview, replay, and save flows

Tip: At least one transmit path must be available (Internal, USB, or Audio). A built‑in IR blaster is not required if you use a USB dongle or audio adapter.

Features

  • Custom Remote Commands: Create and manage remotes using protocol encoders or raw IR patterns.
  • Signal Tester (IR Finder / Infrared Bruteforcer): Systematically try protocol/code variations to discover working signals.
  • Transmitter Selection & Auto Switch:
    • Choose Internal, USB, Audio (1 LED), or Audio (2 LEDs) under Settings > IR Transmitter.
    • Optional Auto Switch uses USB when a supported dongle is attached, otherwise Internal (disabled if Audio is selected).
  • Import/Export & Maintenance (Settings > Remotes):
    • Import JSON backups, Flipper Zero .ir, IRPLUS .irplus / XML (beta), LIRC .conf / .cfg / .lirc (beta), and .json remote files
    • Search and browse ready-made remotes and import one directly into the app
    • Export remotes to Downloads
    • Restore the built‑in demo remote
    • Delete all remotes
  • Learning Mode (Settings > Learning Mode):
    • Use a supported USB learning dongle to capture a button from a physical remote
    • Preview the learned signal, replay it, and save it into a new or existing remote
  • Import a remote: search or browse ready-made remotes and import one directly.

User‑facing

  • Transmitter selection card with live capability updates and USB permission request flow.
  • Learning Mode for supported USB learning dongles, with guided capture and save flow.
  • Import a remote: search or browse ready-made remotes and import one directly.
  • Signal Tester promoted as an IR bruteforcer (IR Finder) to help discover unknown codes.
  • Expanded import/export options and maintenance actions for remotes.

Technical/architectural

  • Multi‑transmitter architecture:
    • Internal: Android ConsumerIrManager
    • USB: Discovery, permission, endpoint selection, and framed/bulk protocol with RLE payloads
    • Audio: AudioTrack at 48 kHz with mono or stereo anti‑phase synthesis
  • Platform channels:
    • Method channel: com.github.shanjian.swiftremote/irtransmitter
    • Event channel: com.github.shanjian.swiftremote/irtransmitter_events
    • Methods: transmit, transmitRaw, hasIrEmitter, getTransmitterCapabilities, setTransmitterType, getTransmitterType, getPreferredTransmitterType, setPreferredTransmitterType, getAutoSwitchEnabled, setAutoSwitchEnabled, usbScanAndRequest, usbDescribe, getSupportedFrequencies
  • Protocol framework: IrProtocolDefinition + IrFieldDef drive UI/validation; encoders return frequency + microsecond patterns.
  • Raw signal encoder: Strict parsing, bounds checking, and safe trailing‑gap handling.
  • Persistent settings via SharedPreferences: active type, preferred UI type, auto‑switch flag.

Transmitters and Hardware Support

Configure under Settings > IR Transmitter.

  • Internal IR (built‑in)
    • Uses ConsumerIrManager when available, with optional carrier frequency range reporting.
  • USB IR Dongle
    • Supported device filter: Vendor IDs 0x10C4 or 0x045E, Product ID 0x8468; requires one interface with bulk IN/OUT endpoints.
    • Permission & discovery: Scans supported devices, requests permission via a mutable PendingIntent (Android 12+), reacts to attach/detach.
    • Framing & transfer: Handshake on open, RLE‑encoded mark/space payloads fragmented into 56‑byte chunks over bulk OUT; background reader drains bulk IN briefly.
    • Tail safety: Adjusts the last gap for even‑length patterns to accommodate device expectations.
  • Audio IR
    • Modes: Audio (1 LED, mono) and Audio (2 LEDs, stereo anti‑phase).
    • Implementation: 48 kHz PCM (16‑bit). Marks are synthesized tone windows; spaces are silence.
    • Usage: Requires a compatible audio‑to‑IR LED adapter and maximum media volume.

Auto Switch

  • When enabled and if the device has Internal IR, the app prefers USB when a permitted dongle is attached, otherwise Internal.
  • Selecting either Audio mode or changing type manually disables Auto Switch.

Signal Tester (IR Finder / Infrared Bruteforcer)

The Signal Tester is designed to help discover unknown working IR commands.

What it does

  • Iterates over valid protocol/code combinations to discover a working signal for your target device.
  • Sends test patterns using the currently selected transmitter path (Internal, USB, or Audio).
  • Surfaces parsing errors and invalid inputs early to avoid spurious transmissions.

Inputs & constraints

  • Protocol selection and parameter fields are derived from IrProtocolDefinition and IrFieldDef.
  • Hex prefix constraints are parsed and normalized via lib/ir_finder/ir_prefix.dart:
    • Accepts inputs like AA, AA BB, 0xAABB, AA:BB:CC (spaces/colons allowed; case‑insensitive).
    • Enforces even number of hex digits; clamps to a maximum byte count; returns normalized uppercase hex.
    • Provides structured error messages when parsing fails.

How it works (high‑level)

  • Builds candidate payloads within protocol‑specific bounds, honoring any prefix constraint.
  • Encodes each candidate using the selected protocol encoder into a (frequency, mark/space) pattern.
  • Transmits the pattern through the active transmitter (Internal, USB, or Audio).
  • Provides progress/run status in the UI and allows the session to be stopped.
  • Input validation: Every protocol encoder checks hex length/format and throws on invalid values.
  • Raw signal guardrails (when testing raw):
    • Limits entries (4096), enforces positive durations, clamps frequency (10–100 kHz),
    • Auto‑pads a trailing space if the pattern ends with a mark (odd length) to complete the frame.
  • USB path normalizes the final tail gap for even‑length patterns to improve dongle compatibility.

Practical tips

  • Start with the correct protocol family if known (e.g., NEC/Sony) and add a narrow hex prefix to reduce the search space.
  • Prefer Internal or USB for consistent timing; use Audio with max media volume and a known‑good adapter.
  • Stop the run as soon as your device reacts and save that code into a remote button.

Implementation references: lib/widgets/ir_finder_screen.dart, lib/ir_finder/ir_prefix.dart, lib/ir_finder/irblaster_db.dart, lib/ir_finder/ir_finder_models.dart, lib/ledger_db/.

The IR code database

The Signal Tester's database mode reads its codes from Remote Ledger's IR code database, published as static files under https://remote-ledger.github.io/app/v1/. The app does not bundle a copy.

  • The first time you open a brand its files are downloaded (a few kilobytes for most brands, a few megabytes for the largest) and kept on the device, in the app's support directory rather than the cache that Android may clear. From then on that brand works offline; anything not downloaded yet needs a connection, and the app says so with a Retry.
  • The ledger's manifest is checked at most every 12 hours. When it reports new data, the small files (the brand list, a brand's models, a protocol's signals) are fetched again as they are used, and a brand's key file only if its content changed. A key file that fails its hash is rejected and fetched once more, and whatever is on the device is used when the network fails. The copy is capped at 40 MB; the brands used longest ago are dropped first.
  • Brands and models are listed in the order the old database listed them (ASCII case-insensitive), and a brand's keys appear once each rather than once per model.
  • Ten protocols (Sony 12, 15 and 20, Pioneer, JVC, Sharp, Denon, Thomson7, Proton and RCC2026) have database codes the app's own hex decoding reads differently from the wire. For those the app plays the ledger's compiled signal (one download per protocol), never its own decoding, and blocks the send with a message if the signal cannot be loaded. Which protocols these are comes from the database's manifest, not from a list in the app.
  • The ledger could not represent 2,066 of the old database's keys, so they are no longer offered (a few brands and models that only they made up are gone with them).

Updating from a build that bundled the database deletes the unused copy of it, and drops any saved Signal Tester session that was counting keys in its order.

Remotes Management

  • Import remotes: JSON backups and Flipper Zero .ir files (Settings > Remotes > Import remotes).
  • Import a remote: Search or browse ready-made remotes and import one into your remote library with one tap.
  • Export remotes: Save a JSON backup to Downloads.
  • Restore Demo Remote: Reset to a built‑in demo configuration.
  • Delete all remotes: Clear the entire list from this device.

Learning Mode

  • Open Settings > Learning Mode to capture a button from a physical remote with a supported USB learning dongle.
  • Review the learned signal, replay it to confirm the target device reacts, then save it into a new or existing remote.
  • Learning Mode is designed for compatible USB learning receivers such as supported Tiqiaa, ZaZa, or ElkSmart-style dongles.

Supported Infrared Protocols

Protocol Input format Carrier (Hz) Frame structure / timing summary Notes
Raw Signal pattern (µs), optional frequencyHz 10,000–100,000 (default 38,000) Alternating mark/space durations starting with mark; tokens can be decimal/hex; comments supported; auto-append 45ms trailing space if odd length Max 4096 entries, positive durations only; strict parsing and bounds
Denon 4 hex > 13-bit frame 38,000 Send the normal 13-bit frame, an inverted-command frame, then the normal frame again; mark=280, spaces 860/1720, gap=43,560µs Strict 4 hex digits; canonical Denon repeat sequence
F12_relaxed up to 3 hex > 12 bits 38,000 Map 0 > [422,1266], 1 > [1266,422]; adjust the final slot to make the frame total 54,000µs Values are left-padded to 12 bits
JVC 4 hex (16 bits LSB-first) 38,000 Preamble 8400/4200; each bit mark=525, space=525 (0) or 1575 (1); trailing 525 + 21000 gap Strict 4 hex digits
NEC up to 8 hex (left-padded) > 32 bits 38,222 Preamble 9000/4500; bit mark=562 + space 562 (0) or 1687 (1); trailing mark 562; pad final gap to 108,800µs Preserves legacy MSB and byte-swap modes; True LSB sends each byte LSB-first
NEC2 up to 8 hex (left-padded) > 32 bits 38,222 Same construction as NEC in this implementation Accepts 1–8 hex; normalized to 8
NECx1 up to 8 hex (left-padded) > 32 bits 38,400 Preamble 4500/4500; bit mark=562 + space 562/1687; trailing 562; pad to 108,800µs Optional helper for toggle frame
NECx2 up to 8 hex (left-padded) > 32 bits 38,400 Single NECx-like frame padded to 108,800µs; then duplicate the whole frame back-to-back Output is two identical frames
NRC17 4 hex (CCAS) 38,000 Synchronization frame, command frame, and termination frame; command(8) + address(4) + subcode(4) are sent LSB-first in 1ms bi-phase cells Packed as command(2 hex) + address(1 hex) + subcode(1 hex)
Pioneer address + command (1 byte each), optional secondary pair 40,000 Preamble 8500/4225; payload address + ~address + command + ~command, LSB-first per byte; mark=500, spaces 500/1500, gap=26,000µs Primary frame repeats unless a secondary address and command define a two-part command
Proton 4 hex (16 bits) 38,500 Header 8000/4000; send last 8 bits; separator 500/4000; then first 8 bits; final 500; pad to 63,000µs Bit mark=500; 0=500; 1=1500; strict 4 hex
RC5 address (5-bit) + command (7-bit) 36,000 RC5 bi-phase coding, unit ≈889µs; start bit, field bit, toggle, address(5), and command(6 low bits) MSB-first; rapid same-key repeats keep the toggle, new presses flip it; frame gap padded to 114,000µs Supports commands 00–7F; legacy packed 3-hex payloads remain compatible
RC6 hex (last 4 hex used > 16-bit payload) 36,000 Leader 2664/888; 1 = mark/space, 0 = space/mark; Mode 0 layout is start 1 + mode 000 + double-width toggle + 16-bit payload (addr+cmd) MSB-first using T=444; includes the required 6t trailing silence Uses last 4 hex digits as payload; rapid same-key repeats keep the same toggle, new presses flip it
RCA_38 address (1 hex) + command (2 hex) 38,700 Preamble 3680/3680; payload = address(4) + command(8) + ~address(4) + ~command(8), sent MSB-first; bit mark=460 and space=920 (0) or 1840 (1); trailer 460/7360 24-bit RCA frame
RCC0082 3 hex (nibbles) 30,300 Prefix 22 ints [BIT=528,GAP=2640,BIT×19,END=21120], then [BIT,GAP,BIT,BIT]; build 10-bit: "0" + n0(last3) + n1(all4) + n2(first2); transition-based emission; parity-based tail then suffix (same 22) Tail even=111,408, odd=110,880
RCC2026 11 hex > 42 bits (from 44 padded) 38,222 Header 8800/4400; bit mark=550 + space 550 (0) or 1650 (1); final mark 550 + 23100; then tail [8800, 4400, 550, 90750] Strict 11 hex; takes last 42 bits
REC80 12 hex > 48 bits (32 + 16) 37,000 Header 3456/1728; bit1 432/1296; bit0 432/432; tail 432/74736 Strict 12 hex
RECS80 3 hex 38,000 Toggle flips each encode; bit string: "1" + toggle + n0(first3) + n0(last1) + n1(all4) + n2(first1); each bit mark=158 + space 7426 (1) or 4898 (0); end 158/45000 Internal toggle maintained
RECS80_L 3 hex 33,300 Same bit string as RECS80; bit1 180/8460; bit0 180/5580; end is 180 then pad to 138,000µs Low-frequency variant; fixed frame length
Samsung32 address + command (1 byte each) 38,000 Preamble 4500/4500; each bit mark≈550 + space≈550 (0) or ≈1650 (1); 32-bit payload sent LSB-first Payload layout is Address + Address + Command + ~Command
Samsung36 7 hex > 36 bits (A8+B8+C4+D8+~D8) 38,000 Start 4500/4500; first 16 bits use 500/500 or 500/1500; 500/4500 separator; last 20 bits same; final 500/59000 Strict 7 hex; includes ~D
Sharp 4 hex packed as address(5) + command(8) 38,000 Send normal, inverted-command, then normal 13-bit frames, LSB-first; timing uses 280/860 for 0 and 280/1720 for 1 with protocol tail blocks between frames Strict 4 hex; packed 13-bit payload
SONY12 address (5-bit) + command (7-bit) 40,000 Header 2400/600; payload command(7) + address(5), LSB-first; 0=600/600, 1=1200/600; pad to 45,000µs 12-bit frame sent three times; packed imports use 3 hex digits
SONY15 address (8-bit) + command (7-bit) 40,000 Same timings and bit order as SONY12 with a 15-bit payload; pad to 45,000µs Frame sent three times; packed imports use 4 hex digits
SONY20 address (13-bit) + command (7-bit) 40,000 Same timings and bit order as SONY12 with a 20-bit payload; pad to 45,000µs Frame sent three times; packed imports use 5 hex digits
Thomson7 3 hex (int) 33,000 Mask 0xF7F; 12 bits = last4 + toggle + first7; 0=[460,2000]; 1=[460,4600]; append 460; pad to 80,000µs; duplicate frame Toggle maintained; hex int input with min/max
XSAT (Mitsubishi) address + command (1 byte each) 38,000 Header 8000/4000; address(8) then command(8), both LSB-first; each bit mark=526 + space=474 (0) or 1474 (1); inserts 4000µs separator between address and command; trailing gap sized for ~60ms repeat cadence Packed imports are split into address and command fields
Kaseikyo (Panasonic) address (4 bytes) + command (4 bytes) 37,000 Header 3456/1728; 48-bit frame sent LSB-first per byte; includes vendor parity, genre, 10-bit command, ID, and XOR; bit mark=432, spaces 432/1296 Each field accepts 8 compact hex digits or four space-separated bytes

Notes:

  • Protocol identifiers and display names are maintained in lib/ir/ir_protocol_registry.dart.
  • Encoders validate inputs and produce an explicit frequency (Hz) and alternating mark/space durations (µs).

Developer Notes

Platform channels

  • Method Channel: com.github.shanjian.swiftremote/irtransmitter
    • transmit: Send encoder‑generated patterns at the encoder’s frequency.
    • transmitRaw: Send a raw microsecond pattern at a specified frequency.
    • hasIrEmitter: True if any path is available (internal, USB present, or audio available).
    • getTransmitterCapabilities: Returns hasInternal, hasUsb, usbOpened, hasAudio, currentType, usbDevices[], autoSwitchEnabled.
    • setTransmitterType / getTransmitterType
    • getPreferredTransmitterType / setPreferredTransmitterType
    • getAutoSwitchEnabled / setAutoSwitchEnabled
    • usbScanAndRequest
    • getSupportedFrequencies
    • usbDescribe
  • Event Channel: com.github.shanjian.swiftremote/irtransmitter_events
    • Emits capability snapshots on attach/detach, permission responses, and type changes.

Audio path

  • AudioIrTransmitter + AudioPcmBuilder synthesize PCM from mark/space patterns (mono or stereo anti‑phase).

USB path

  • UsbDiscoveryManager filters, opens, and claims interfaces; UsbProtocolFormatter handles handshake, RLE body, fragmentation, and tail adjustments; UsbIrTransmitter performs bulk I/O and runs a short‑lived background reader.

Persistence

  • tx_type, ui_tx_type, auto_switch in the swiftremote_prefs SharedPreferences file persist user choices and auto behavior.

Requirements

  • One of the following transmit paths:
    • Built‑in IR blaster (Internal)
    • Supported USB IR dongle (VID 0x10C4 or 0x045E, PID 0x8468)
    • Audio‑to‑IR LED adapter (Audio modes)
  • Android 11+

Installation

  1. Download the APK attached to the latest release.

  2. Install the Application:

    • Enable installation from unknown sources if needed.
    • Follow the on‑screen instructions.
  3. Later updates install themselves: Settings > About > Updates checks this repository, downloads the APK, and hands it to the system installer. Every release is signed with the same key, so an update installs over the build you already have.

  4. Launch and Configure:

    • Open SwiftRemote.
    • Choose your transmitter (Settings > IR Transmitter).
    • Create remotes or import a Flipper Zero .ir file.

Usage

Creating Custom Remotes

  1. Open the Remotes tab.
  2. Create a remote and add buttons using protocol encoders, raw patterns, or an imported ready-made remote.
  3. Save and test your buttons from the Remote view.

Importing a ready-made remote

  1. Open the Remotes tab and create or edit a remote, then tap Import a remote (also in the Add button sheet).
  2. The screen opens on the app's collection of ready-made remotes. Search by the device you want to control, the remote's model or the maker (BDP-S185, dx3 pro, sony); spaces and punctuation are ignored. Or choose Browse by folder to browse by manufacturer and model. Nothing is fetched until you search or browse.
  3. Tap a remote to import it as a new remote. It imports each key's most trusted code, repeated as many times as its protocol needs; there is no file preview step.
  4. Choose Open remote to use it now, or Keep browsing.

Using the Signal Tester (IR Finder)

  1. Open the "Signal Tester" tab.
  2. Provide protocol parameters and optional hex prefix constraints.
  3. Start testing; the bruteforcer will try variations to identify working signals via your selected transmitter.

Using Learning Mode

  1. Connect a supported USB learning dongle and grant USB permission if Android asks.
  2. Open Settings > Learning Mode.
  3. Capture one button from the original remote, replay it if needed, then save it into your library.

USB Notes

  • When a supported USB dongle is attached, use "Request USB permission" if prompted.
  • Auto Switch prefers USB when available; disable it for manual selection or Audio use.

Audio Notes

  • Use maximum media volume when transmitting via audio.
  • Requires a compatible audio‑to‑IR LED adapter (mono or stereo anti‑phase).

ScreenShots

1 2 4 5 6




TapDucky Banner App

Contributing

Contributions are welcome! If you'd like to help improve SwiftRemote: Please do not submit pull requests that only modify translation or localization files in lib/l10n/*.arb. Translation contributions are not being accepted through PRs.

  1. Fork the repository.
  2. Create a new branch for your feature or bug fix.
  3. Submit a pull request with your proposed changes.

License

This project is licensed under the GNU GPLv3 License.

Support

If you encounter any issues or have questions, please open an issue on the GitHub repository or contact the maintainer.

Acknowledgments

SwiftRemote is a fork of IR Blaster by KaijinLab Inc., which is itself a fork of osram-remote. Special thanks to KaijinLab and to TalkingPanda0 for the foundational work.

About

Create custom infrared (IR) remotes using hex codes, raw signals, or import Flipper Zero, LIRC, and IRPLUS files

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages