mirror of
https://github.com/Genymobile/scrcpy.git
synced 2026-03-27 06:24:29 +01:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ad2edc2d8 | ||
|
|
dee1fd46a6 | ||
|
|
a90a039f50 | ||
|
|
ab04e0348d | ||
|
|
99b955f390 | ||
|
|
bbb855b5b0 | ||
|
|
4879950a06 | ||
|
|
170b7a02e7 | ||
|
|
9f1aac41a6 |
38
.github/workflows/release.yml
vendored
38
.github/workflows/release.yml
vendored
@@ -72,16 +72,30 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Same as build-linux-x86_64
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y meson ninja-build nasm ffmpeg libsdl2-2.0-0 \
|
||||
libsdl2-dev libavcodec-dev libavdevice-dev libavformat-dev \
|
||||
libavutil-dev libswresample-dev libusb-1.0-0 libusb-1.0-0-dev \
|
||||
libv4l-dev
|
||||
sudo apt install -y meson ninja-build nasm ffmpeg libavcodec-dev \
|
||||
libavdevice-dev libavformat-dev libavutil-dev libswresample-dev \
|
||||
libusb-1.0-0 libusb-1.0-0-dev libv4l-dev \
|
||||
libasound2-dev libpulse-dev \
|
||||
libaudio-dev libfribidi-dev libjack-dev libsndio-dev libx11-dev libxext-dev \
|
||||
libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev \
|
||||
libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
|
||||
libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev libthai-dev \
|
||||
libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev
|
||||
|
||||
# SDL3 is not available in Ubuntu yet
|
||||
- name: Install SDL3
|
||||
run: |
|
||||
app/deps/sdl.sh linux native shared
|
||||
|
||||
- name: Test
|
||||
run: release/test_client.sh
|
||||
run: |
|
||||
export PKG_CONFIG_PATH="$PWD"/app/deps/work/install/linux-native-shared/lib/pkgconfig
|
||||
export LD_LIBRARY_PATH="$PWD"/app/deps/work/install/linux-native-shared/lib
|
||||
release/test_client.sh
|
||||
|
||||
build-linux-x86_64:
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -98,13 +112,19 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# https://wiki.libsdl.org/SDL3/README-linux#build-dependencies
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y meson ninja-build nasm ffmpeg libsdl2-2.0-0 \
|
||||
libsdl2-dev libavcodec-dev libavdevice-dev libavformat-dev \
|
||||
libavutil-dev libswresample-dev libusb-1.0-0 libusb-1.0-0-dev \
|
||||
libv4l-dev
|
||||
sudo apt install -y meson ninja-build nasm ffmpeg libavcodec-dev \
|
||||
libavdevice-dev libavformat-dev libavutil-dev libswresample-dev \
|
||||
libusb-1.0-0 libusb-1.0-0-dev libv4l-dev \
|
||||
libasound2-dev libpulse-dev \
|
||||
libaudio-dev libfribidi-dev libjack-dev libsndio-dev libx11-dev libxext-dev \
|
||||
libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev \
|
||||
libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
|
||||
libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev libthai-dev \
|
||||
libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev
|
||||
|
||||
- name: Build
|
||||
run: release/build_linux.sh x86_64
|
||||
|
||||
@@ -3,9 +3,9 @@ set -ex
|
||||
. $(dirname ${BASH_SOURCE[0]})/_init
|
||||
process_args "$@"
|
||||
|
||||
VERSION=2.32.8
|
||||
VERSION=3.4.0
|
||||
URL="https://github.com/libsdl-org/SDL/archive/refs/tags/release-$VERSION.tar.gz"
|
||||
SHA256SUM=dd35e05644ae527848d02433bec24dd0ea65db59faecf1a0e5d1880c533dac2c
|
||||
SHA256SUM=9614b9696abc4597ffce6b888829dc6537ae500423474c342ac4a67222c5654c
|
||||
|
||||
PROJECT_DIR="sdl-$VERSION"
|
||||
FILENAME="$PROJECT_DIR.tar.gz"
|
||||
@@ -36,45 +36,49 @@ else
|
||||
cd "$DIRNAME"
|
||||
|
||||
conf=(
|
||||
--prefix="$INSTALL_DIR/$DIRNAME"
|
||||
-DCMAKE_INSTALL_PREFIX="$INSTALL_DIR/$DIRNAME"
|
||||
-DSDL_TESTS=OFF
|
||||
)
|
||||
|
||||
if [[ "$HOST" == linux ]]
|
||||
then
|
||||
conf+=(
|
||||
--enable-video-wayland
|
||||
--enable-video-x11
|
||||
-DSDL_WAYLAND=ON
|
||||
-DSDL_X11=ON
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ "$LINK_TYPE" == static ]]
|
||||
then
|
||||
conf+=(
|
||||
--enable-static
|
||||
--disable-shared
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
)
|
||||
else
|
||||
conf+=(
|
||||
--disable-static
|
||||
--enable-shared
|
||||
-DBUILD_SHARED_LIBS=ON
|
||||
)
|
||||
fi
|
||||
|
||||
if [[ "$BUILD_TYPE" == cross ]]
|
||||
then
|
||||
if [[ "$HOST" = win32 ]]
|
||||
then
|
||||
TOOLCHAIN_FILENAME="cmake-toolchain-mingw64-i686.cmake"
|
||||
elif [[ "$HOST" = win64 ]]
|
||||
then
|
||||
TOOLCHAIN_FILENAME="cmake-toolchain-mingw64-x86_64.cmake"
|
||||
else
|
||||
echo "Unsupported cross-build to host: $HOST" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
conf+=(
|
||||
--host="$HOST_TRIPLET"
|
||||
-DCMAKE_TOOLCHAIN_FILE="$SOURCES_DIR/$PROJECT_DIR/build-scripts/$TOOLCHAIN_FILENAME"
|
||||
)
|
||||
fi
|
||||
|
||||
"$SOURCES_DIR/$PROJECT_DIR"/configure "${conf[@]}"
|
||||
cmake "$SOURCES_DIR/$PROJECT_DIR" "${conf[@]}"
|
||||
fi
|
||||
|
||||
make -j
|
||||
# There is no "make install-strip"
|
||||
make install
|
||||
# Strip manually
|
||||
if [[ "$LINK_TYPE" == shared && "$HOST" == win* ]]
|
||||
then
|
||||
${HOST_TRIPLET}-strip "$INSTALL_DIR/$DIRNAME/bin/SDL2.dll"
|
||||
fi
|
||||
cmake --build .
|
||||
cmake --install .
|
||||
|
||||
@@ -135,6 +135,7 @@ sc_display_to_sdl_color_space(enum AVColorSpace color_space,
|
||||
|
||||
switch (color_space) {
|
||||
case AVCOL_SPC_BT709:
|
||||
case AVCOL_SPC_RGB:
|
||||
return full_range ? SDL_COLORSPACE_BT709_FULL
|
||||
: SDL_COLORSPACE_BT709_LIMITED;
|
||||
case AVCOL_SPC_BT470BG:
|
||||
|
||||
@@ -81,24 +81,6 @@ sc_mouse_capture_handle_event(struct sc_mouse_capture *mc,
|
||||
|
||||
void
|
||||
sc_mouse_capture_set_active(struct sc_mouse_capture *mc, bool capture) {
|
||||
#ifdef __APPLE__
|
||||
// Workaround for SDL bug on macOS:
|
||||
// <https://github.com/libsdl-org/SDL/issues/5340>
|
||||
if (capture) {
|
||||
float mouse_x, mouse_y;
|
||||
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
|
||||
|
||||
int x, y, w, h;
|
||||
SDL_GetWindowPosition(mc->window, &x, &y);
|
||||
SDL_GetWindowSize(mc->window, &w, &h);
|
||||
|
||||
bool outside_window = mouse_x < x || mouse_x >= x + w
|
||||
|| mouse_y < y || mouse_y >= y + h;
|
||||
if (outside_window) {
|
||||
SDL_WarpMouseInWindow(mc->window, w / 2, h / 2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
bool ok = SDL_SetWindowRelativeMouseMode(mc->window, capture);
|
||||
if (!ok) {
|
||||
LOGE("Could not set relative mouse mode to %s: %s",
|
||||
|
||||
@@ -27,12 +27,11 @@ get_oriented_size(struct sc_size size, enum sc_orientation orientation) {
|
||||
return oriented_size;
|
||||
}
|
||||
|
||||
static inline void
|
||||
assert_not_fullscreen(struct sc_screen *screen) {
|
||||
(void) screen;
|
||||
assert(!screen->fullscreen);
|
||||
assert(!screen->maximized);
|
||||
assert(!screen->minimized);
|
||||
static inline bool
|
||||
is_windowed(struct sc_screen *screen) {
|
||||
return !(SDL_GetWindowFlags(screen->window) & (SDL_WINDOW_FULLSCREEN
|
||||
| SDL_WINDOW_MINIMIZED
|
||||
| SDL_WINDOW_MAXIMIZED));
|
||||
}
|
||||
|
||||
// get the preferred display bounds (i.e. the screen bounds with some margins)
|
||||
@@ -296,9 +295,6 @@ sc_screen_init(struct sc_screen *screen,
|
||||
screen->resize_pending = false;
|
||||
screen->has_frame = false;
|
||||
screen->has_video_window = false;
|
||||
screen->fullscreen = false;
|
||||
screen->maximized = false;
|
||||
screen->minimized = false;
|
||||
screen->paused = false;
|
||||
screen->resume_frame = NULL;
|
||||
screen->orientation = SC_ORIENTATION_0;
|
||||
@@ -481,7 +477,7 @@ sc_screen_show_initial_window(struct sc_screen *screen) {
|
||||
get_initial_optimal_size(screen->content_size, screen->req.width,
|
||||
screen->req.height);
|
||||
|
||||
assert_not_fullscreen(screen);
|
||||
assert(is_windowed(screen));
|
||||
sc_sdl_set_window_size(screen->window, window_size);
|
||||
sc_sdl_set_window_position(screen->window, position);
|
||||
|
||||
@@ -537,7 +533,7 @@ resize_for_content(struct sc_screen *screen, struct sc_size old_content_size,
|
||||
/ old_content_size.height,
|
||||
};
|
||||
target_size = get_optimal_size(target_size, new_content_size, true);
|
||||
assert_not_fullscreen(screen);
|
||||
assert(is_windowed(screen));
|
||||
sc_sdl_set_window_size(screen->window, target_size);
|
||||
}
|
||||
|
||||
@@ -545,7 +541,7 @@ static void
|
||||
set_content_size(struct sc_screen *screen, struct sc_size new_content_size) {
|
||||
assert(screen->video);
|
||||
|
||||
if (!screen->fullscreen && !screen->maximized && !screen->minimized) {
|
||||
if (is_windowed(screen)) {
|
||||
resize_for_content(screen, screen->content_size, new_content_size);
|
||||
} else if (!screen->resize_pending) {
|
||||
// Store the windowed size to be able to compute the optimal size once
|
||||
@@ -561,9 +557,7 @@ static void
|
||||
apply_pending_resize(struct sc_screen *screen) {
|
||||
assert(screen->video);
|
||||
|
||||
assert(!screen->fullscreen);
|
||||
assert(!screen->maximized);
|
||||
assert(!screen->minimized);
|
||||
assert(is_windowed(screen));
|
||||
if (screen->resize_pending) {
|
||||
resize_for_content(screen, screen->windowed_content_size,
|
||||
screen->content_size);
|
||||
@@ -711,26 +705,23 @@ void
|
||||
sc_screen_toggle_fullscreen(struct sc_screen *screen) {
|
||||
assert(screen->video);
|
||||
|
||||
bool ok = SDL_SetWindowFullscreen(screen->window, !screen->fullscreen);
|
||||
bool req_fullscreen =
|
||||
!(SDL_GetWindowFlags(screen->window) & SDL_WINDOW_FULLSCREEN);
|
||||
|
||||
bool ok = SDL_SetWindowFullscreen(screen->window, req_fullscreen);
|
||||
if (!ok) {
|
||||
LOGW("Could not switch fullscreen mode: %s", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
screen->fullscreen = !screen->fullscreen;
|
||||
if (!screen->fullscreen && !screen->maximized && !screen->minimized) {
|
||||
apply_pending_resize(screen);
|
||||
}
|
||||
|
||||
LOGD("Switched to %s mode", screen->fullscreen ? "fullscreen" : "windowed");
|
||||
sc_screen_render(screen, true);
|
||||
LOGD("Requested %s mode", req_fullscreen ? "fullscreen" : "windowed");
|
||||
}
|
||||
|
||||
void
|
||||
sc_screen_resize_to_fit(struct sc_screen *screen) {
|
||||
assert(screen->video);
|
||||
|
||||
if (screen->fullscreen || screen->maximized || screen->minimized) {
|
||||
if (!is_windowed(screen)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -759,15 +750,10 @@ void
|
||||
sc_screen_resize_to_pixel_perfect(struct sc_screen *screen) {
|
||||
assert(screen->video);
|
||||
|
||||
if (screen->fullscreen || screen->minimized) {
|
||||
if (!is_windowed(screen)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (screen->maximized) {
|
||||
sc_sdl_restore_window(screen->window);
|
||||
screen->maximized = false;
|
||||
}
|
||||
|
||||
struct sc_size content_size = screen->content_size;
|
||||
sc_sdl_set_window_size(screen->window, content_size);
|
||||
LOGD("Resized to pixel-perfect: %ux%u", content_size.width,
|
||||
@@ -799,24 +785,20 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
||||
sc_screen_render(screen, true);
|
||||
}
|
||||
return true;
|
||||
case SDL_EVENT_WINDOW_MAXIMIZED:
|
||||
screen->maximized = true;
|
||||
return true;
|
||||
case SDL_EVENT_WINDOW_MINIMIZED:
|
||||
screen->minimized = true;
|
||||
return true;
|
||||
case SDL_EVENT_WINDOW_RESTORED:
|
||||
if (screen->fullscreen) {
|
||||
// On Windows, in maximized+fullscreen, disabling
|
||||
// fullscreen mode unexpectedly triggers the "restored"
|
||||
// then "maximized" events, leaving the window in a
|
||||
// weird state (maximized according to the events, but
|
||||
// not maximized visually).
|
||||
return true;
|
||||
if (screen->has_video_window && is_windowed(screen)) {
|
||||
apply_pending_resize(screen);
|
||||
sc_screen_render(screen, true);
|
||||
}
|
||||
screen->maximized = false;
|
||||
screen->minimized = false;
|
||||
if (screen->has_video_window) {
|
||||
return true;
|
||||
case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
|
||||
LOGD("Switched to fullscreen mode");
|
||||
assert(screen->has_video_window);
|
||||
return true;
|
||||
case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
|
||||
LOGD("Switched to windowed mode");
|
||||
assert(screen->has_video_window);
|
||||
if (is_windowed(screen)) {
|
||||
apply_pending_resize(screen);
|
||||
sc_screen_render(screen, true);
|
||||
}
|
||||
|
||||
@@ -62,9 +62,6 @@ struct sc_screen {
|
||||
struct SDL_Rect rect;
|
||||
bool has_frame;
|
||||
bool has_video_window;
|
||||
bool fullscreen;
|
||||
bool maximized;
|
||||
bool minimized;
|
||||
|
||||
AVFrame *frame;
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#include "sdl.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
SDL_Window *
|
||||
sc_sdl_create_window(const char *title, int64_t x, int64_t y, int64_t width,
|
||||
int64_t height, int64_t flags) {
|
||||
@@ -36,7 +41,13 @@ struct sc_size
|
||||
sc_sdl_get_window_size(SDL_Window *window) {
|
||||
int width;
|
||||
int height;
|
||||
SDL_GetWindowSize(window, &width, &height);
|
||||
bool ok = SDL_GetWindowSize(window, &width, &height);
|
||||
if (!ok) {
|
||||
LOGE("Could not get window size: %s", SDL_GetError());
|
||||
LOGE("Please report the error");
|
||||
// fatal error
|
||||
abort();
|
||||
}
|
||||
|
||||
struct sc_size size = {
|
||||
.width = width,
|
||||
@@ -49,7 +60,13 @@ struct sc_size
|
||||
sc_sdl_get_window_size_in_pixels(SDL_Window *window) {
|
||||
int width;
|
||||
int height;
|
||||
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||
bool ok = SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||
if (!ok) {
|
||||
LOGE("Could not get window size: %s", SDL_GetError());
|
||||
LOGE("Please report the error");
|
||||
// fatal error
|
||||
abort();
|
||||
}
|
||||
|
||||
struct sc_size size = {
|
||||
.width = width,
|
||||
@@ -60,14 +77,24 @@ sc_sdl_get_window_size_in_pixels(SDL_Window *window) {
|
||||
|
||||
void
|
||||
sc_sdl_set_window_size(SDL_Window *window, struct sc_size size) {
|
||||
SDL_SetWindowSize(window, size.width, size.height);
|
||||
bool ok = SDL_SetWindowSize(window, size.width, size.height);
|
||||
if (!ok) {
|
||||
LOGE("Could not set window size: %s", SDL_GetError());
|
||||
assert(!"unexpected");
|
||||
}
|
||||
}
|
||||
|
||||
struct sc_point
|
||||
sc_sdl_get_window_position(SDL_Window *window) {
|
||||
int x;
|
||||
int y;
|
||||
SDL_GetWindowPosition(window, &x, &y);
|
||||
bool ok = SDL_GetWindowPosition(window, &x, &y);
|
||||
if (!ok) {
|
||||
LOGE("Could not get window position: %s", SDL_GetError());
|
||||
LOGE("Please report the error");
|
||||
// fatal error
|
||||
abort();
|
||||
}
|
||||
|
||||
struct sc_point point = {
|
||||
.x = x,
|
||||
@@ -78,30 +105,45 @@ sc_sdl_get_window_position(SDL_Window *window) {
|
||||
|
||||
void
|
||||
sc_sdl_set_window_position(SDL_Window *window, struct sc_point point) {
|
||||
SDL_SetWindowPosition(window, point.x, point.y);
|
||||
bool ok = SDL_SetWindowPosition(window, point.x, point.y);
|
||||
if (!ok) {
|
||||
LOGE("Could not set window position: %s", SDL_GetError());
|
||||
assert(!"unexpected");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_sdl_show_window(SDL_Window *window) {
|
||||
SDL_ShowWindow(window);
|
||||
bool ok = SDL_ShowWindow(window);
|
||||
if (!ok) {
|
||||
LOGE("Could not show window: %s", SDL_GetError());
|
||||
assert(!"unexpected");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_sdl_hide_window(SDL_Window *window) {
|
||||
SDL_HideWindow(window);
|
||||
}
|
||||
|
||||
void
|
||||
sc_sdl_restore_window(SDL_Window *window) {
|
||||
SDL_RestoreWindow(window);
|
||||
bool ok = SDL_HideWindow(window);
|
||||
if (!ok) {
|
||||
LOGE("Could not hide window: %s", SDL_GetError());
|
||||
assert(!"unexpected");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
sc_sdl_render_clear(SDL_Renderer *renderer) {
|
||||
return SDL_RenderClear(renderer);
|
||||
bool ok = SDL_RenderClear(renderer);
|
||||
if (!ok) {
|
||||
LOGW("Could not clear rendering: %s", SDL_GetError());
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void
|
||||
sc_sdl_render_present(SDL_Renderer *renderer) {
|
||||
SDL_RenderPresent(renderer);
|
||||
bool ok = SDL_RenderPresent(renderer);
|
||||
if (!ok) {
|
||||
LOGE("Could not render: %s", SDL_GetError());
|
||||
assert(!"unexpected");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,9 +34,6 @@ sc_sdl_show_window(SDL_Window *window);
|
||||
void
|
||||
sc_sdl_hide_window(SDL_Window *window);
|
||||
|
||||
void
|
||||
sc_sdl_restore_window(SDL_Window *window);
|
||||
|
||||
bool
|
||||
sc_sdl_render_clear(SDL_Renderer *renderer);
|
||||
|
||||
|
||||
73
container/Dockerfile
Normal file
73
container/Dockerfile
Normal file
@@ -0,0 +1,73 @@
|
||||
# Build with:
|
||||
# podman build -t scrcpy-builder .
|
||||
#
|
||||
# Run with:
|
||||
# podman run \
|
||||
# -v PATH_TO_SCRCPY:/home/debian/scrcpy \
|
||||
# --userns=keep-id \
|
||||
# -it scrcpy-builder \
|
||||
# bash
|
||||
|
||||
FROM debian:trixie
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
sudo wget unzip gcc git pkg-config meson ninja-build cmake \
|
||||
libsdl3-dev libavcodec-dev libavdevice-dev libavformat-dev libavutil-dev \
|
||||
libswresample-dev libusb-1.0-0-dev openjdk-21-jdk \
|
||||
mingw-w64 mingw-w64-tools libz-mingw-w64-dev
|
||||
|
||||
RUN groupadd -g 1000 debian \
|
||||
&& useradd -m -u 1000 -g 1000 -s /bin/bash debian
|
||||
RUN echo "debian ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
|
||||
|
||||
ENV ANDROID_HOME=/opt/android/sdk
|
||||
RUN mkdir -p "$ANDROID_HOME" \
|
||||
&& chown debian:debian "$ANDROID_HOME"
|
||||
|
||||
USER debian
|
||||
WORKDIR /home/debian
|
||||
|
||||
ENV CMDLINETOOLS_URL=https://dl.google.com/android/repository/commandlinetools-linux-13114758_latest.zip
|
||||
ENV CMDLINETOOLS_SHA256=7ec965280a073311c339e571cd5de778b9975026cfcbe79f2b1cdcb1e15317ee
|
||||
|
||||
RUN wget -q "$CMDLINETOOLS_URL" -O cmdlinetools.zip \
|
||||
&& echo "$CMDLINETOOLS_SHA256 cmdlinetools.zip" | sha256sum -c
|
||||
|
||||
RUN mkdir tmp \
|
||||
&& unzip -q cmdlinetools.zip -d tmp \
|
||||
&& mkdir -p "$ANDROID_HOME/cmdline-tools" \
|
||||
&& mv tmp/cmdline-tools "$ANDROID_HOME/cmdline-tools/latest" \
|
||||
&& rmdir tmp \
|
||||
&& rm cmdlinetools.zip
|
||||
# To get the licence hash, run manually: "$ANDROID_HOME"/cmdline-tools/latest/bin/sdkmanager --licenses
|
||||
# Build-tools 35 is still needed for the current AGP version
|
||||
RUN mkdir -p "$ANDROID_HOME/licenses" \
|
||||
&& echo 24333f8a63b6825ea9c5514f83c2829b004d1fee > "$ANDROID_HOME/licenses/android-sdk-license" \
|
||||
&& $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "platform-tools" "platforms;android-36" "build-tools;35.0.0" "build-tools;36.0.0"
|
||||
|
||||
# For scrcpy build scripts
|
||||
ENV GRADLE_VERSION=8.14.3
|
||||
ENV GRADLE_HOME=/opt/gradle-$GRADLE_VERSION
|
||||
ENV GRADLE_URL=https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip
|
||||
ENV GRADLE_SHA256=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531
|
||||
ENV GRADLE=gradle
|
||||
ENV PATH=$GRADLE_HOME/bin:$PATH
|
||||
|
||||
USER root
|
||||
RUN wget -q "$GRADLE_URL" -O gradle.zip \
|
||||
&& echo "$GRADLE_SHA256 gradle.zip" | sha256sum -c
|
||||
RUN unzip -q gradle.zip -d /opt \
|
||||
&& rm gradle.zip
|
||||
|
||||
USER debian
|
||||
|
||||
# Pre-download gradle dependencies for scrcpy
|
||||
RUN mkdir -p /home/debian/fake-scrcpy/app
|
||||
COPY fake.gradle /home/debian/fake-scrcpy/build.gradle
|
||||
COPY fake_app.gradle /home/debian/fake-scrcpy/app/build.gradle
|
||||
RUN echo "include ':app'" > /home/debian/fake-scrcpy/settings.gradle \
|
||||
&& gradle -p /home/debian/fake-scrcpy dependencies androidDependencies --no-daemon \
|
||||
&& rm -rf /home/debian/fake-scrcpy
|
||||
17
container/fake.gradle
Normal file
17
container/fake.gradle
Normal file
@@ -0,0 +1,17 @@
|
||||
// Fake build.gradle to pre-download gradle dependencies
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.13.0'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
21
container/fake_app.gradle
Normal file
21
container/fake_app.gradle
Normal file
@@ -0,0 +1,21 @@
|
||||
// Fake app/build.gradle to pre-download gradle dependencies
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'checkstyle'
|
||||
|
||||
android {
|
||||
buildToolsVersion = "36.0.0"
|
||||
namespace = "com.genymobile.scrcpy"
|
||||
compileSdk 36
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 36
|
||||
}
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = '10.12.5'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
}
|
||||
Reference in New Issue
Block a user