The Android companion app for the CrownOS phone bridge — clipboard sync, notification sync, call bridging, OTP sync and file sharing between your phone and a CrownOS desktop.
Status: Skeleton. This is currently an unmodified Android Studio "Compose + Navigation Suite" template with the app renamed. It has no networking code and no network permission, so it cannot talk to the desktop at all.
| AGP | 8.13.1 |
| Kotlin | 2.0.21 |
| compileSdk / targetSdk | 36 |
| minSdk | 29 |
| JVM target | 11 |
| Compose BOM | 2024.09.00 |
| UI | material3 + material3-adaptive-navigation-suite |
| Application ID | com.crownos.crate |
Requires JDK 17 or newer — AGP 8.13.1 refuses to run Gradle on anything
older. The jvmTarget = "11" above is the output bytecode level, not the JDK
you build with. The Gradle wrapper is committed.
This is the only thing between a clean machine and a green build, and nothing else documents it. Install the SDK, then point Gradle at it:
export ANDROID_HOME="$HOME/Android/Sdk"
sdkmanager --install "platforms;android-36" "build-tools;36.0.0" "platform-tools"
yes | sdkmanager --licensesANDROID_HOME in the environment is the portable option. Alternatively write the
path into an untracked local.properties:
echo "sdk.dir=$HOME/Android/Sdk" > local.propertiesWithout one of the two, the build fails with "SDK location not found".
./gradlew assembleDebug
./gradlew installDebug # to a connected device or emulator
./gradlew testThere is no ktlint plugin configured, so
./gradlew ktlintCheckandktlintFormatdo not exist and will fail with "task not found". Follow the official Kotlin coding conventions by hand. Adding the plugin would be a welcomechorePR.
The desktop side already defines the contract. To make the two halves talk:
1. Permissions. The manifest currently has zero <uses-permission>
entries. At minimum INTERNET; then
BIND_NOTIFICATION_LISTENER_SERVICE for notification sync,
READ_PHONE_STATE / ANSWER_PHONE_CALLS for the call bridge, and clipboard
access.
2. A TCP client to <desktop>:5252, holding the connection open for the
session.
3. CBOR framing of the message shape the daemon expects:
Message { client: Ipv4Addr, method: Actions, body: Map<String, String> }
Actions: CLIPBOARD | MEDIA | OPEN | OTPSYNC | MONITOR | VOLUME | SHUTDOWN
4. Discovery. The desktop binds UDP :5253 for this, but its discovery
function is a stub — so the protocol is undefined on both sides and needs
designing.
5. Pairing and encryption. Neither side has any. The desktop currently accepts unauthenticated commands including remote shutdown, which is not acceptable to ship.
Protocol detail:
IPC and protocols.
Server:
crowncrate-linux.
AndroidManifest.xmldeclares zero<uses-permission>entries — not evenINTERNET. The app therefore cannot open a socket, which is the one thing a phone bridge exists to do. This is the first thing to fix.- There is no networking code at all, only the Compose template's screens.
- No pairing or encryption, on either side of the bridge.
.gitignoreis the stock Android Studio list, but.idea/is only partially ignored and eight.idea/*.xmlfiles are committed. The Gradle wrapper jar is conventional; the IDE files are not.
See the organization-wide
contribution guide.
Default branch here is main.
Licensed under the MIT License.