A simple, polished Android IR remote app without any ads.
The app is designed for phones with a built-in infrared blaster. It provides a clean touch interface for controlling the Logitech Z607 5.1 Surround System. Feel free to create a merge request to add support for more devices!
The physical Logitech controller kept getting broken and I got tired of using apps with annoying ads (each time I want to control the volume of my TV!) so I reverse engineer the IR codes with the help of my crustacean friend 🦞.
This project is independent and is not affiliated with, endorsed by, or sponsored by any device manufacturer.
- Power, mute, volume up/down
- Bluetooth, FM Radio, AUX, RCA, and SD/USB input controls
- Playback controls: previous, play/pause, next
- 5.1 / 2.1 mode and channel level controls
- Clean dark UI optimized for one-handed use
- Profile-based IR architecture for adding more controllers later
| Device | Type | Profile |
|---|---|---|
| Logitech Z607 | 5.1 speaker system | Z607SpeakerProfile |
More devices can be added through the profile system — see Adding a new IR controller.
- Android 7.0+ / API 24+
- A device with a built-in IR emitter/blaster
- Android SDK 35 for building
- Java 17
app/src/main/java/com/ricardomaltez/irremote/
├── MainActivity.kt
└── ir/
├── model/
│ ├── CommandIds.kt
│ ├── IrCommand.kt
│ └── IrControllerProfile.kt
├── profiles/
│ ├── ControllerProfiles.kt
│ └── Z607SpeakerProfile.kt
└── protocol/
├── IrProtocol.kt
└── NecProtocol.kt
The app separates UI code from IR command data:
MainActivityowns the Android UI and sends commands.IrControllerProfiledescribes one supported remote/controller.IrCommandstores stable command IDs, display labels, and encoded IR payloads.IrProtocolconverts protocol-specific payloads into Android IR transmit patterns.NecProtocolcurrently handles NEC 38 kHz encoding.ControllerProfilesis the registry for bundled controller profiles.
This makes new controllers easier to add without rewriting the activity.
- Add command IDs to
CommandIds.ktif the new controller needs buttons the app does not already know about. - Create a new profile in
ir/profiles/, for example:
object MySpeakerProfile : IrControllerProfile {
override val id = "my_speaker"
override val displayName = "My Speaker"
override val protocol = NecProtocol
override val commands = listOf(
IrCommand(CommandIds.POWER, "Power", "00000000"),
IrCommand(CommandIds.VOLUME_UP, "Volume +", "00000000"),
).associateBy { it.id }
}- Register the profile in
ControllerProfiles.kt. - Add or update tests under
app/src/test/. - Run the test/build gate:
./gradlew testDebugUnitTest assembleDebugFrom the repository root:
./gradlew assembleDebugThe debug APK will be created at:
app/build/outputs/apk/debug/app-debug.apk
Run unit tests:
./gradlew testDebugUnitTestRun tests and build a debug APK:
./gradlew testDebugUnitTest assembleDebugCurrent tests cover:
- NEC protocol pattern generation
- Invalid NEC payload validation
- Z607 profile command completeness
- Controller registry sanity checks
The app does not need internet access and does not collect user data. It only uses Android's TRANSMIT_IR permission to send infrared commands from supported devices.
This project is licensed under the GNU General Public License v3.0 (GPL-3.0).
Copyright (C) 2026 Ricardo Maltez
The full license text is available in the LICENSE file and at https://www.gnu.org/licenses/gpl-3.0.html.
In short, you are free to use, modify, and distribute this software — including commercially — provided that any derivative work is also released under the GPL-3.0 and the source code (including modifications) is made available to users. There is no warranty; see the license for the full terms.
