Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental Android support for eframe #5318

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

parasyte
Copy link
Contributor

@parasyte parasyte commented Oct 28, 2024

Android support is "almost there". This PR pushes it just a bit further by allowing eframe to be used on Android. It works by smuggling the AndroidApp required by winit through NativeOptions.

The example isn't great because it doesn't leave space on the display for Android's top status bar or the lower navigation bar. I don't know what to do about that, yet. This is as far as I've managed to get it working.

Another problem is that the development environment setup is completely awful for Android unless you happen to already be a full-time Android developer with everything configured on your build host. As a Rustacean, this makes me very sad.

I've had some luck moving all of that mess to a container, adapted from https://github.com/SergioRibera/docker-rust-android. It takes care of all of the build dependencies, Android SDK, and the cargo-apk patches for bugs that I hit while getting the example to work on my device. (I also had to install an adb driver on my host and downloaded the Android platform-tools to get access to adb. An alternative is exposing the USB device to Docker. On Windows hosts, that means installing usbipd. A second alternative is using an mtp client to upload the APK as a file with USB file transfer enabled, then manually install it through the device's file manager.)

I'm not including the docker stuff in this PR, but here are the files and instructions for future reference (and it will probably simplify manual testing and CI, FWIW!)

Dockerfile
FROM rust:1.76.0-slim

# Variable arguments
ARG JAVA_VERSION=17
ARG NDK_VERSION=25.1.8937393
ARG BUILDTOOLS_VERSION=30.0.0
ARG PLATFORM_VERSION=android-30
ARG CLITOOLS_VERSION=8512546_latest

# Install Android requirements
RUN apt-get update -yqq && \
    apt-get install -y --no-install-recommends \
    libcurl4-openssl-dev libssl-dev pkg-config build-essential git python3 wget zip unzip openjdk-${JAVA_VERSION}-jdk && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# Install android targets
RUN rustup target add armv7-linux-androideabi aarch64-linux-android

# Install cargo-apk
RUN git clone -b fix/bin-targets-workspace-members https://github.com/parasyte/cargo-apk.git /tmp/cargo-apk && \
    cargo install --path /tmp/cargo-apk/cargo-apk

# Generate Environment Variables
ENV JAVA_VERSION=${JAVA_VERSION}
ENV ANDROID_HOME=/opt/Android
ENV NDK_HOME=/opt/Android/ndk/${NDK_VERSION}
ENV ANDROID_NDK_ROOT=${NDK_HOME}
ENV PATH=$PATH:${ANDROID_HOME}:${ANDROID_NDK_ROOT}:${ANDROID_HOME}/build-tools/${BUILDTOOLS_VERSION}:${ANDROID_HOME}/cmdline-tools/bin

# Install command line tools
RUN mkdir -p ${ANDROID_HOME}/cmdline-tools && \
    wget -qc "https://dl.google.com/android/repository/commandlinetools-linux-${CLITOOLS_VERSION}.zip" -P /tmp && \
    unzip -d ${ANDROID_HOME} /tmp/commandlinetools-linux-${CLITOOLS_VERSION}.zip && \
    rm -fr /tmp/commandlinetools-linux-${CLITOOLS_VERSION}.zip
# Install sdk requirements
RUN echo y | sdkmanager --sdk_root=${ANDROID_HOME} --install \
    "build-tools;${BUILDTOOLS_VERSION}" "ndk;${NDK_VERSION}" "platforms;${PLATFORM_VERSION}"

# Create APK keystore for debug profile
# Adapted from https://github.com/rust-mobile/cargo-apk/blob/caa806283dc26733ad8232dce1fa4896c566f7b8/ndk-build/src/ndk.rs#L393-L423
RUN keytool -genkey -v -keystore ${HOME}/.android/debug.keystore -storepass android -alias androiddebugkey \
    -keypass android -dname 'CN=Android Debug,O=Android,C=US' -keyalg RSA -keysize 2048 -validity 10000

# Cleanup
RUN rm -rf /tmp/*

WORKDIR /src

ENTRYPOINT [ "cargo", "apk", "build" ]
.dockerignore
# Ignore everything, only the Dockerfile is needed to build the container
*
docker build -t rust-android:latest .
docker run --rm -it -v "$PWD:/src" rust-android:latest -p hello_android
adb install target/debug/apk/hello_android.apk

Copy link

Preview available at https://egui-pr-preview.github.io/pr/5318-feature/android-eframe
Note that it might take a couple seconds for the update to show up after the preview_build workflow has completed.

@parasyte
Copy link
Contributor Author

The display safe area problem is tracked upstream at rust-windowing/winit#3910

@emilk emilk added the android label Oct 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants