# AirPlay Receiver for Android: an open source screen mirror built on UxPlay

> The android-airplay-server project turns an Android phone or TV into an AirPlay receiver, using the C library UxPlay behind a JNI bridge and handling video and audio with MediaCodec and ExoPlayer. It is distributed as an app, it exposes a settings interface over ADB for headless devices, and DRM content is out of reach.

**jqssun/android-airplay-server** — First open-source AirPlay receiver implementation for Android with mirroring, video and audio support

- Repository: https://github.com/jqssun/android-airplay-server
- Website: https://f-droid.org/packages/io.github.jqssun.airplay/
- Stars: 779 · Forks: 120
- Language: Kotlin
- License: GPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/jqssun-android-airplay-server

## A receiver, not a sender

The project is described as a fully featured free and open-source implementation of AirPlay for Android that turns the device into an AirPlay-compatible display and speaker, based on UxPlay. The README says it is the first open-source AirPlay 2 receiver for Android and Android TV, and that it works with iOS and iPadOS devices, macOS devices, as well as other sender implementations.

So the direction of the traffic is what defines the project. Most people meet AirPlay as a sender, and this is the receiving end, which is the harder half to get right and the half vendors rarely give away. A receiver has to advertise itself, accept the pairing and licensing handshake, decode whatever the sender pushes, and present it convincingly enough that the sender keeps sending.

The compatibility statement is specific about the conditions: Android 7.0 and later, including Android TV, with AirPlay devices on the same subnet. Same subnet is a hard requirement rather than a preference, since discovery in AirPlay is a local network mechanism, and the implementation section confirms that the stack includes mDNS.

The disclaimer at the end of the README is worth repeating as a matter of expectation setting. This project is not affiliated with Apple Inc., which is normal for a receiver implementation and also a reminder that the protocol is being implemented from documentation and observed behaviour rather than from a published specification.

## UxPlay in C, a JNI bridge, and the Android media stack

The implementation section is the most useful paragraph in the README, because it tells you exactly what is doing the work.

The protocol side is entirely UxPlay, the C library that implements the AirPlay and RAOP protocol, and the Android application layer talks to it through a JNI bridge. Inside the UxPlay layer sit RAOP for audio, mDNS for discovery, FairPlay handling for the licensing handshake and HLS for video sessions.

Above that, the Android side does the media work. Mirroring video is decoded via MediaCodec and rendered to a SurfaceView, so the pipeline is the platform decoder into a platform surface, with no custom rendering. Audio can be decoded via MediaCodec or through a software ALAC decoder, which the credits attribute to FFmpeg for the lossless audio decoder. HLS sessions are served through a local playlist proxy, and the video player is credited to Next Player.

The architecture diagram in the README shows the same three stages: an Apple device as sender, the UxPlay C and JNI layer handling RAOP, mDNS, FairPlay and HLS, and the Android receiver using MediaCodec, AudioTrack and ExoPlayer.

One structural consequence is worth stating. Because the protocol implementation is a separate upstream C project vendored as a submodule, the receiver inherits that project's maturity and its release cadence, and the native code is built with CMake under app/src/main/cpp. The Android layer is a comparatively thin wrapper.

The FairPlay component deserves a note for anyone thinking about what an AirPlay receiver implies. The pairing and licensing handshake is part of the protocol, so a receiver implements it, and that is a category of cryptography you are choosing to run on your own device.

## Mirroring, streaming and the Android TV details

The feature list is long, and a few items are more than marketing.

Screen mirroring handles H.264 and H.265, which is HEVC, video decoding. Audio streaming covers AAC-ELD, AAC-LC and ALAC. Video playback supports HLS, downloads and remote controls, so the receiver is not limited to live mirroring, and music playback comes with track information, cover art and remote controls, which is the set of metadata a sender pushes along with the audio.

The Android TV support is specific: directional pad navigation and seeking controls. That is the difference between a receiver you can browse with and one you can only watch, and it is the item that makes the project interesting for a TV rather than a phone.

There is also Picture-in-Picture support, automatic resolution and mode switching, optional PIN authentication, and controls for video resolution, overscan and frame rate. Audio latency control is there, together with support for software decoder fallback, which is the escape hatch when the hardware decoder is unavailable or misbehaves on a particular device.

Two operational features are worth singling out. A debug overlay gives real-time statistics, and the list is specific: FPS, bitrate, codec, resolution, frame count and audio volume. When a receiver is stuttering on a particular phone, those numbers are how you tell a decode problem from a network problem. There is also Android native media session integration with notification controls, so the audio continues to be controllable from the shade.

The last feature on the list is unusual: a wired secondary display for macOS and iPadOS devices over USB tethering, which is a separate path from the wireless one.

## DRM is the wall, and the README says so up front

The README carries an explicit warning that DRM content, for example from the Apple TV application, is not supported. It sits in a callout rather than in a footnote, which is the right place for it, because it is the difference between a receiver that works for most sends and one that works for all of them.

The reason is structural. Protected content is encrypted, and the receiver has to participate in the licensing exchange to decrypt it. The UxPlay layer does handle FairPlay as part of the protocol, and the FairPlay component appears in the architecture diagram, but the README's warning stands: content from the Apple TV application is out of scope for this implementation.

That is the case where this is the wrong tool, and it is worth being clear about it before you deploy the receiver as a presentation setup. A sender streaming from a video app that uses DRM will not produce a picture, and no amount of configuration on the receiver side will change that.

The second boundary is more mundane. The same subnet requirement means the receiver will not appear to a sender on a different network, and with mDNS involved there is a class of networks, commonly guest WiFi in hotels and venues, where broadcast and multicast traffic is filtered and discovery simply fails. The receiver is on the same subnet as the sender, and the network has to permit the discovery traffic, and neither of those is under the project's control.

## Configuring a receiver with no screen, over ADB

This is the part of the project that goes beyond being a media receiver. On devices without a display, the README says settings can also be changed over ADB.

The mechanism is a broadcast to the app's own SettingsReceiver, and the reason it is safe is stated: the receiver is protected by the android.permission.DUMP permission, so regular installed apps cannot change the settings. The values are passed as text using the --es argument. To set a value, you export the key and the value and send the broadcast:

```bash
export KEY="server_name" VALUE="Speaker"
am broadcast -n io.github.jqssun.airplay/.SettingsReceiver -a io.github.jqssun.airplay.SET_SETTING --es key "$KEY" --es value "$VALUE"
```

And to list every setting with its current value as JSON, you start the main activity and send the listing broadcast:

```bash
am start -n io.github.jqssun.airplay/.MainActivity
am broadcast -n io.github.jqssun.airplay/.SettingsReceiver -a io.github.jqssun.airplay.LIST_SETTINGS
```

The package name io.github.jqssun.airplay is the same one used in the F-Droid and Google Play links, so the component names in those commands are the app's real components rather than placeholders.

For a headless device, for example an old phone or a spare handset wired to a screen, this is what makes the receiver usable at all. The device needs the DUMP permission granted, which in practice means an adb connection with sufficient privileges, and the interface is deliberately text so that it can be scripted.

## Building from source, and a release cadence measured in hours

The build is a Gradle project with native components, and the README gives the two commands that matter. CMake is used for the native C and C++ components under app/src/main/cpp, and submodules must be initialized before building, because the UxPlay sources and the native pieces arrive that way:

```bash
git submodule update --init --recursive
./gradlew assembleDebug
```

The README points at the CI workflow for details on reproducible builds, and the repository root shows the standard Android layout: build.gradle.kts, settings.gradle.kts, gradle.properties, the gradle directory and the gradlew wrappers, an app module, a fastlane directory for store metadata, and a .gitmodules file for the submodules.

The release history is worth noting because it says something about the state of the project. The three most recent tags are v0.0.36, v0.0.35 and v0.0.34, all on 2026-10-19, the same day, and the last push to the repository was on 2026-10-19 as well. A version number at 0.0.36 says the project treats itself as pre-1.0, and shipping three tags in one day suggests the releases follow the work rather than precede it.

Distribution runs through the usual channels: the Google Play listing, F-Droid at the package io.github.jqssun.airplay, and GitHub releases, with the F-Droid page linked as the project homepage. The licence is GPL-3.0 with the file at the repository root, which is the one licence decision to think about before you install it on a device that matters.

## Conclusion

Adopt android-airplay-server if you need an AirPlay receiver on an Android phone or Android TV that you control, especially on a device with no display or with a locked down firmware where a prebuilt receiver is not an option, and you are comfortable with the FairPlay handling that AirPlay implies. Do not adopt it for content from the Apple TV application or any other DRM protected source, since the README states plainly that DRM content is not supported, and do not expect an Apple silicon or iOS device to be able to send to it without the same subnet conditions. Verify first that your sender and the receiver can see each other on the same subnet, that your device runs Android 7.0 or later, and which codec path is used, since audio can fall back to a software decoder and mirroring video is decoded through MediaCodec onto a SurfaceView.

## FAQ

### What is the AirPlay Receiver for Android project?

It is a free and open-source AirPlay receiver for Android and Android TV that turns the device into an AirPlay-compatible display and speaker, built on the UxPlay C library. The README calls it the first open-source AirPlay 2 receiver for Android.

### Does the AirPlay Receiver for Android support DRM content?

No. The README carries an explicit warning that DRM content, for example from the Apple TV application, is not supported, so protected streams will not play on the receiver.

### How do I change settings on a headless AirPlay receiver?

The README says settings can be changed over ADB on devices without a display, by broadcasting to the app's SettingsReceiver with the io.github.jqssun.airplay.SET_SETTING action and the key and value passed as text using --es. The receiver is protected by the android.permission.DUMP permission so regular installed apps cannot change the settings.

### How is the AirPlay Receiver for Android built from source?

Submodules must be initialized first with git submodule update --init --recursive, then ./gradlew assembleDebug builds the debug APK. CMake handles the native C and C++ components under app/src/main/cpp, and the README points to the CI workflow for reproducible build details.

## Sources

- [jqssun/android-airplay-server on GitHub](https://github.com/jqssun/android-airplay-server)
- [License: GPL-3.0](https://github.com/jqssun/android-airplay-server/blob/main/LICENSE)
- [Project website](https://f-droid.org/packages/io.github.jqssun.airplay/)
- [README](https://github.com/jqssun/android-airplay-server/blob/main/README.md)
- [Releases](https://github.com/jqssun/android-airplay-server/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jqssun-android-airplay-server
