diff --git a/app/build.gradle b/app/build.gradle index ecfb5c19d..1f06908d2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,14 +9,16 @@ else { android { namespace 'org.tuxpaint' - compileSdkVersion 34 + compileSdkVersion 35 defaultConfig { minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 externalNativeBuild { ndkBuild { arguments "APP_PLATFORM=android-21" abiFilters 'arm64-v8a' + // Add 16KB page size alignment support - use ldFlags instead of cFlags + arguments "APP_LDFLAGS+=-Wl,-z,max-page-size=16384" } } } diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk index 796404005..f7394a9f9 100644 --- a/app/src/main/jni/Application.mk +++ b/app/src/main/jni/Application.mk @@ -1,7 +1,10 @@ APP_ABI := arm64-v8a APP_PLATFORM := android-16 -APP_CFLAGS += -Wno-error=format-security +APP_CFLAGS += -Wno-error=format-security -Wno-error=cast-function-type-strict -Wno-error APP_STL := c++_shared -APP_CPPFLAGS += -fexceptions +APP_CPPFLAGS += -fexceptions -Wno-error=cast-function-type-strict -Wno-error +APP_CXXFLAGS += -Wno-error=cast-function-type-strict -Wno-error APP_ALLOW_MISSING_DEPS := true +# Add 16KB page size alignment support for Google Play Store 2025 requirements +APP_LDFLAGS += -Wl,-z,max-page-size=16384 diff --git a/app/src/main/jni/SDL2/src/sensor/android/SDL_androidsensor.c b/app/src/main/jni/SDL2/src/sensor/android/SDL_androidsensor.c index 1b1979184..29014f120 100644 --- a/app/src/main/jni/SDL2/src/sensor/android/SDL_androidsensor.c +++ b/app/src/main/jni/SDL2/src/sensor/android/SDL_androidsensor.c @@ -161,7 +161,7 @@ static void SDL_ANDROID_SensorUpdate(SDL_Sensor *sensor) ASensorEvent event; struct android_poll_source *source; - if (ALooper_pollAll(0, NULL, &events, (void **)&source) == LOOPER_ID_USER) { + if (ALooper_pollOnce(0, NULL, &events, (void **)&source) == LOOPER_ID_USER) { SDL_zero(event); while (ASensorEventQueue_getEvents(sensor->hwdata->eventqueue, &event, 1) > 0) { SDL_PrivateSensorUpdate(sensor, 0, event.data, SDL_arraysize(event.data)); diff --git a/app/src/main/jni/SDL2_ttf/external/harfbuzz/Android.mk b/app/src/main/jni/SDL2_ttf/external/harfbuzz/Android.mk index b9a04f720..0638ad456 100644 --- a/app/src/main/jni/SDL2_ttf/external/harfbuzz/Android.mk +++ b/app/src/main/jni/SDL2_ttf/external/harfbuzz/Android.mk @@ -61,7 +61,9 @@ LOCAL_C_INCLUDES = \ LOCAL_STATIC_LIBRARIES += freetype #LOCAL_CFLAGS += -DHB_NO_MT -DHAVE_OT -DHAVE_UCDN -fPIC -LOCAL_CFLAGS += -DHAVE_CONFIG_H -fPIC +LOCAL_CFLAGS += -DHAVE_CONFIG_H -fPIC -Wno-cast-function-type-strict -Wno-error -Wno-cast-function-type -w +LOCAL_CXXFLAGS += -Wno-cast-function-type-strict -Wno-error -Wno-cast-function-type -Wno-cast-function-type-strict -w +LOCAL_CPPFLAGS += -Wno-cast-function-type-strict -Wno-error -Wno-cast-function-type -w LOCAL_EXPORT_C_INCLUDES = $(LOCAL_PATH)/src/ diff --git a/app/src/main/jni/cairo-1.14.0/Android.mk b/app/src/main/jni/cairo-1.14.0/Android.mk index 6f313b931..c2bcd2bba 100644 --- a/app/src/main/jni/cairo-1.14.0/Android.mk +++ b/app/src/main/jni/cairo-1.14.0/Android.mk @@ -9,6 +9,7 @@ LOCAL_CFLAGS := \ -D_REENTRANT \ -DCAIRO_NO_MUTEX=1 \ -Wno-attributes \ + -Wno-error=int-conversion \ $(NULL) LOCAL_C_INCLUDES := \ diff --git a/app/src/main/jni/glib-2.77.0/Android.mk b/app/src/main/jni/glib-2.77.0/Android.mk index f2dff93f1..cee79414a 100644 --- a/app/src/main/jni/glib-2.77.0/Android.mk +++ b/app/src/main/jni/glib-2.77.0/Android.mk @@ -477,7 +477,9 @@ LOCAL_CFLAGS := \ -DGIO_COMPILATION \ -DGIO_MODULE_DIR=\"/mnt/sdcard/Android/data/org.tuxpaint/files/glib\" \ -DXDG_PREFIX=_gio_xdg \ - -marm \ + -UHAVE_STRERROR_R \ + -USTRERROR_R_CHAR_P \ + -Wno-error=int-conversion \ $(NULL) LOCAL_SHARED_LIBRARIES := \ diff --git a/app/src/main/jni/tuxpaint/Android.mk b/app/src/main/jni/tuxpaint/Android.mk index 93bbcb45a..d43597e6b 100644 --- a/app/src/main/jni/tuxpaint/Android.mk +++ b/app/src/main/jni/tuxpaint/Android.mk @@ -78,6 +78,13 @@ MY_DEFS := \ -DHAVE_STRCASESTR \ $(MY_NOSOUNDFLAG) $(MY_NOSVGFLAG) $(MY_NOPANGOFLAG) +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../SDL2/src/events \ + $(LOCAL_PATH)/../libimagequant \ + $(LOCAL_PATH)/src/mouse \ + $(LOCAL_PATH)/../fribidi-1.0.13 \ + $(NULL) + LOCAL_CFLAGS := \ $(MY_CFLAGS) \ $(MY_DEFS) @@ -86,6 +93,11 @@ LOCAL_LDLIBS := \ -lz -llog -lGLESv1_CM -lGLESv2 -landroid \ $(NULL) +# Add 16KB page size alignment support for Google Play Store 2025 requirements +LOCAL_LDFLAGS := \ + -Wl,-z,max-page-size=16384 \ + $(NULL) + LOCAL_SHARED_LIBRARIES := SDL2 SDL2_image SDL2_mixer SDL2_ttf SDL2_Pango tuxpaint_intl tuxpaint_fribidi tuxpaint_png tuxpaint_rsvg tuxpaint_cairo tp_android_assets_fopen libimagequant SDL2_gfx tuxpaint_pango tuxpaint_fontconfig tuxpaint_glib tuxpaint_xml2 include $(BUILD_SHARED_LIBRARY) @@ -98,6 +110,8 @@ $(foreach _magic, $(MAGIC_NAMES),\ $(eval LOCAL_MODULE := $(_magic))\ $(eval LOCAL_C_INCLUDES := $(LOCAL_PATH)/src $(LOCAL_PATH)/../SDL2_gfx-1.0.4/)\ $(eval MAGIC_CFLAGS:=-g3 -O2 -fno-common -W -Wstrict-prototypes -Wmissing-prototypes -Wall)\ + $(eval LOCAL_CFLAGS := $(MAGIC_CFLAGS))\ + $(eval LOCAL_LDFLAGS := -Wl,-z,max-page-size=16384)\ $(eval LOCAL_SRC_FILES := magic/src/$(_magic).c)\ $(eval LOCAL_SHARED_LIBRARIES := SDL2 SDL2_image SDL2_mixer SDL2_ttf tuxpaint_intl SDL2_gfx)\ $(eval include $(BUILD_SHARED_LIBRARY))\ diff --git a/app/src/main/jni/tuxpaint/src/debug.h b/app/src/main/jni/tuxpaint/src/debug.h index 31d6a1236..0b010cdae 100644 --- a/app/src/main/jni/tuxpaint/src/debug.h +++ b/app/src/main/jni/tuxpaint/src/debug.h @@ -32,15 +32,18 @@ * * Verbose logging adds metadata to printf, including the source file location * from where printf was called and the time it was called at runtime. +* +* Note: On Android, we use __android_log_print instead to avoid infinite recursion +* and to properly log to the Android logcat system. */ -#if defined(DEBUG) && defined(VERBOSE) && defined(__GNUC__) +#if defined(DEBUG) && defined(VERBOSE) && defined(__GNUC__) && !defined(__ANDROID__) #include #include #define printf(args...) do { \ time_t now = time(NULL); \ - printf("\n### %s, line %d in %s() @ %s", __FILE__, __LINE__, __FUNCTION__, ctime(&now)); \ - printf(args); \ + fprintf(stderr, "\n### %s, line %d in %s() @ %s", __FILE__, __LINE__, __FUNCTION__, ctime(&now)); \ + fprintf(stderr, args); \ } while(0) #endif diff --git a/app/src/main/jni/tuxpaint/src/i18n.c b/app/src/main/jni/tuxpaint/src/i18n.c index f78311739..e38d102d5 100644 --- a/app/src/main/jni/tuxpaint/src/i18n.c +++ b/app/src/main/jni/tuxpaint/src/i18n.c @@ -52,6 +52,7 @@ #ifdef __ANDROID__ #include "SDL2/SDL.h" +#include "../../../SDL2/src/core/android/SDL_android.h" #include "jni.h" // since setlocale on the Android is not supported well, // setlocale cannot get current default locale of the device. diff --git a/app/src/main/jni/tuxpaint/src/progressbar.c b/app/src/main/jni/tuxpaint/src/progressbar.c index ae0f5e13e..6a2268ce0 100644 --- a/app/src/main/jni/tuxpaint/src/progressbar.c +++ b/app/src/main/jni/tuxpaint/src/progressbar.c @@ -49,6 +49,23 @@ void show_progress_bar_(SDL_Surface *screen, SDL_Texture *texture, SDL_Renderer if (progress_bar_disabled) return; +#ifdef __ANDROID__ + /* On Android, skip all rendering operations in progress bar because: + * 1. It's called from worker threads (font loading, file scanning, etc.) + * 2. OpenGL/EGL contexts are thread-local and cannot be used from worker threads + * 3. Even with valid renderer/texture/screen parameters, the GL context is not + * current on the worker thread, causing SIGSEGV when GL functions are called + * + * We still allow the function to continue to update internal state like prog_bar_ctr + * and oldtime, but skip all SDL rendering calls. */ + newtime = SDL_GetTicks(); + if (newtime > oldtime + 500) { + prog_bar_ctr++; + } + oldtime = newtime; + return; +#endif + newtime = SDL_GetTicks(); if (newtime > oldtime + 15) /* trying not to eat some serious CPU time! */ { diff --git a/app/src/main/jni/tuxpaint/src/tuxpaint.c b/app/src/main/jni/tuxpaint/src/tuxpaint.c index 1740fdcfe..565d59fd3 100644 --- a/app/src/main/jni/tuxpaint/src/tuxpaint.c +++ b/app/src/main/jni/tuxpaint/src/tuxpaint.c @@ -358,6 +358,7 @@ extern status_t haiku_trash(const char *f); #define AUTOSAVE_GOING_BACKGROUND #include "android_print.h" #include "android_assets.h" +#include "SDL_mouse_c.h" int entered_background = 0; #else @@ -2387,6 +2388,14 @@ static void do_wait(int counter) SDL_Rect r; #endif +#ifdef __ANDROID__ + /* On Android, skip splash screen wait because: + * 1. Android provides its own splash screen + * 2. Touch events may not be properly recognized as mouse clicks + * 3. Users expect apps to start immediately after loading */ + return; +#endif + if (bypass_splash_wait) return; @@ -21838,6 +21847,7 @@ static void load_magic_plugins(void) DEBUG_PRINTF("\n"); DEBUG_PRINTF("Loading magic plug-ins from %s\n", place); + /* Gather list of files (for sorting): */ d = opendir(place); @@ -22116,6 +22126,7 @@ static void load_magic_plugins(void) res = magic_funcs[num_plugin_files].init(magic_api_struct, magic_disabled_features, magic_complexity_level); + if (res != 0) n = magic_funcs[num_plugin_files].get_tool_count(magic_api_struct); else @@ -22321,11 +22332,13 @@ static void load_magic_plugins(void) DEBUG_PRINTF("Loaded %d magic tools from %d plug-in files\n", num_magics_total, num_plugin_files); DEBUG_PRINTF("\n"); + /* Start out with the first magic group that _has_ any tools */ tries = 0; while (num_magics[magic_group] == 0 && tries < MAX_MAGIC_GROUPS) { magic_group++; + tries++; if (magic_group >= MAX_MAGIC_GROUPS) { magic_group = 0; @@ -29785,6 +29798,16 @@ static void setup(void) if (!fullscreen) init_flags |= SDL_INIT_NOPARACHUTE; /* allow debugger to catch crash */ + /* Fix Android EGL threading issues - ensure GL context stays on render thread */ +#ifdef __ANDROID__ + SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "1"); + SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles2"); + SDL_SetHint(SDL_HINT_ANDROID_TRAP_BACK_BUTTON, "1"); + SDL_SetHint(SDL_HINT_ANDROID_BLOCK_ON_PAUSE, "0"); + /* Prevent EGL context from being made current on multiple threads */ + SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1"); +#endif + /* Init SDL */ if (SDL_Init(init_flags) < 0) { @@ -29996,7 +30019,12 @@ static void setup(void) /* FIXME: Check window_screen for being NULL, and abort?! (Also see below) -bjk 2024.12.20 */ +#ifdef __ANDROID__ + /* On Android, use accelerated renderer to ensure proper GL context threading */ + renderer = SDL_CreateRenderer(window_screen, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); +#else renderer = SDL_CreateRenderer(window_screen, -1, 0); +#endif SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); if (native_screensize) @@ -30179,7 +30207,12 @@ static void setup(void) SDL_SetWindowMaximumSize(window_screen, WINDOW_WIDTH, WINDOW_HEIGHT); +#ifdef __ANDROID__ + /* On Android, use accelerated renderer to ensure proper GL context threading */ + renderer = SDL_CreateRenderer(window_screen, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); +#else renderer = SDL_CreateRenderer(window_screen, -1, 0); +#endif SDL_GL_GetDrawableSize(window_screen, &ww, &hh); texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STATIC, ww, hh); @@ -30219,9 +30252,13 @@ static void setup(void) /* quickly: title image, version, progress bar, and watch cursor */ + DEBUG_PRINTF("Loading splash images...\n"); img_title = loadimage(DATA_PREFIX "images/title.png"); + DEBUG_PRINTF("img_title loaded\n"); img_title_credits = loadimage(DATA_PREFIX "images/title-credits.png"); + DEBUG_PRINTF("img_title_credits loaded\n"); img_progress = loadimage(DATA_PREFIX "images/ui/progress.png"); + DEBUG_PRINTF("img_progress loaded\n"); if (screen->w - img_title->w >= 410 && screen->h - img_progress->h - img_title_credits->h - 40) /* FIXME: Font */ big_title = 1; @@ -30234,8 +30271,12 @@ static void setup(void) else img_title_tuxpaint = loadimage(DATA_PREFIX "images/title-tuxpaint.png"); + + /* Show splash screen (or white screen on Android) */ + DEBUG_PRINTF("Drawing splash screen...\n"); SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255)); +#ifndef __ANDROID__ dest.x = ((WINDOW_WIDTH - img_title->w - (img_title_tuxpaint->w / 2)) / 2) + (img_title_tuxpaint->w / 2) + 20; dest.y = (WINDOW_HEIGHT - img_title->h); @@ -30253,11 +30294,14 @@ static void setup(void) dest.y = 5; SDL_BlitSurface(img_title_credits, NULL, screen, &dest); +#endif prog_bar_ctr = 0; show_progress_bar(screen); + DEBUG_PRINTF("Flipping screen...\n"); SDL_Flip(screen); + DEBUG_PRINTF("Screen flipped!\n"); #if defined(WIN32) && defined(LARGE_CURSOR_FULLSCREEN_BUG) @@ -30273,6 +30317,7 @@ static void setup(void) /* Create cursors: */ + scale = 1; #ifdef SMALL_CURSOR_SHAPES @@ -30286,12 +30331,15 @@ static void setup(void) /* this one first, because we need it yesterday */ cursor_watch = get_cursor(watch_bits, watch_mask_bits, watch_width, watch_height, 14 / scale, 14 / scale); + do_setcursor(cursor_watch); show_progress_bar(screen); + /* Let Pango & fontcache do their work without locking up */ +#ifndef __ANDROID__ fontconfig_thread_done = 0; DEBUG_PRINTF("Spawning Pango thread\n"); @@ -30317,6 +30365,11 @@ static void setup(void) } DEBUG_PRINTF("Done generating cache\n"); } +#else + /* On Android, skip font cache generation to speed up startup */ + fontconfig_thread_done = 1; + DEBUG_PRINTF("Android: Skipping fontconfig cache generation\n"); +#endif #ifdef FORKED_FONTS @@ -30326,6 +30379,7 @@ static void setup(void) #endif + medium_font = TuxPaint_Font_OpenFont(tp_ui_font, DATA_PREFIX "fonts/default_font.ttf", /* FIXME: Does this matter any more? -bjk 2023.05.29 */ (18 - (only_uppercase * 3)) * button_scale); @@ -30340,16 +30394,20 @@ static void setup(void) exit(1); } + safe_snprintf(tmp_str, sizeof(tmp_str), "Version: %s – %s", VER_VERSION, VER_DATE); +#ifndef __ANDROID__ tmp_surf = render_text(medium_font, tmp_str, black); dest.x = 10; dest.y = WINDOW_HEIGHT - img_progress->h - tmp_surf->h; SDL_BlitSurface(tmp_surf, NULL, screen, &dest); SDL_FreeSurface(tmp_surf); +#endif DEBUG_PRINTF("%s\n", tmp_str); +#ifndef __ANDROID__ safe_snprintf(tmp_str, sizeof(tmp_str), "© 2002–2024 Bill Kendrick, et al."); tmp_surf = render_text(medium_font, tmp_str, black); dest.x = 10; @@ -30358,12 +30416,20 @@ static void setup(void) SDL_FreeSurface(tmp_surf); SDL_Flip(screen); +#endif #ifdef FORKED_FONTS reliable_write(font_socket_fd, &no_system_fonts, sizeof no_system_fonts); #else +#ifndef __ANDROID__ font_thread = SDL_CreateThread(load_user_fonts_stub, "font_thread", NULL); +#else + /* On Android, skip font loading thread - fonts will be loaded on demand */ + DEBUG_PRINTF("Android: Skipping font loading thread\n"); + font_thread_done = 1; + font_thread_aborted = 0; +#endif #endif /* continuing on with the rest of the cursors... */ @@ -30398,6 +30464,7 @@ static void setup(void) /* Create drawing canvas: */ + canvas_width = WINDOW_WIDTH - r_ttools.w - r_ttoolopt.w; canvas_height = (button_h * buttons_tall) + r_ttools.h; @@ -30465,6 +30532,7 @@ static void setup(void) /* Create undo buffer space: */ + for (i = 0; i < NUM_UNDO_BUFS; i++) { undo_bufs[i] = @@ -30489,9 +30557,11 @@ static void setup(void) /* Load other images: */ + for (i = 0; i < NUM_TOOLS; i++) img_tools[i] = loadimagerb(tool_img_fnames[i]); + img_title_on = loadimagerb(DATA_PREFIX "images/ui/title.png"); img_title_large_on = loadimagerb(DATA_PREFIX "images/ui/title_large.png"); img_title_off = loadimagerb(DATA_PREFIX "images/ui/no_title.png"); @@ -30645,6 +30715,8 @@ static void setup(void) /* Load brushes: */ + + load_brush_dir(screen, DATA_PREFIX "brushes"); homedirdir = get_fname("brushes", DIR_DATA); load_brush_dir(screen, homedirdir); @@ -30661,6 +30733,7 @@ static void setup(void) exit(1); } + free(homedirdir); @@ -30707,8 +30780,10 @@ static void setup(void) load_stamps(screen); + /* Load magic tool plugins: */ + magic_disabled_features = 0x00; // 0b00000000 if (disable_magic_sizes) { @@ -30721,8 +30796,10 @@ static void setup(void) load_magic_plugins(); + show_progress_bar(screen); + /* Load shape icons: */ for (i = 0; i < NUM_SHAPES; i++) { @@ -30734,8 +30811,10 @@ static void setup(void) SDL_FreeSurface(aux_surf); } + show_progress_bar(screen); + /* Load fill sub-tool icons: */ for (i = 0; i < NUM_FILLS; i++) { @@ -30747,14 +30826,18 @@ static void setup(void) SDL_FreeSurface(aux_surf); } + show_progress_bar(screen); + /* Load tip tux images: */ for (i = 0; i < NUM_TIP_TUX; i++) img_tux[i] = loadimagerb(tux_img_fnames[i]); + show_progress_bar(screen); + img_mouse = loadimagerb(DATA_PREFIX "images/ui/mouse.png"); img_mouse_click = loadimagerb(DATA_PREFIX "images/ui/mouse_click.png"); @@ -30763,6 +30846,7 @@ static void setup(void) img_color_picker = loadimagerb(DATA_PREFIX "images/ui/color_picker.png"); img_color_picker_val = loadimagerb(DATA_PREFIX "images/ui/color_picker_val.png"); + /* Create toolbox and selector labels: */ for (i = 0; i < NUM_TITLES; i++) @@ -30788,8 +30872,10 @@ static void setup(void) + /* Generate color selection buttons: */ + /* Create appropriately-shaped buttons: */ img1 = loadimage(DATA_PREFIX "images/ui/paintwell.png"); img_paintwell = thumbnail(img1, color_button_w, color_button_h, 0); @@ -30916,8 +31002,11 @@ static void setup(void) SDL_FreeSurface(tmp_btn_up); SDL_FreeSurface(tmp_btn_down); + + create_button_labels(); + /* Resize any icons if the text we just rendered was too wide, and we word-wrapped it to be two lines tall */ @@ -30996,6 +31085,7 @@ static void setup(void) #ifdef __APPLE__ apple_init(); #endif + } @@ -31012,6 +31102,7 @@ static void claim_to_be_ready(void) /* Let the user know we're (nearly) ready now */ +#ifndef __ANDROID__ dest.x = 0; dest.y = WINDOW_HEIGHT - img_progress->h; dest.h = img_progress->h; @@ -31023,6 +31114,7 @@ static void claim_to_be_ready(void) src.y = img_title->h - img_progress->h; dest.x = ((WINDOW_WIDTH - img_title->w - (img_title_tuxpaint->w / 2)) / 2) + (img_title_tuxpaint->w / 2) + 20; SDL_BlitSurface(img_title, &src, screen, &dest); +#endif SDL_FreeSurface(img_title); SDL_FreeSurface(img_title_credits); @@ -31871,7 +31963,7 @@ static void convert_motion_to_wheel(SDL_Event event) { while (motion_dy - high > 0) { - SDL_SendMouseWheel(NULL, event.motion.which, 0, 1); + SDL_SendMouseWheel(NULL, event.motion.which, 0.0f, 1.0f, SDL_MOUSEWHEEL_NORMAL); motion_dy -= high; } } @@ -31879,7 +31971,7 @@ static void convert_motion_to_wheel(SDL_Event event) { while (motion_dy + high < 0) { - SDL_SendMouseWheel(NULL, event.motion.which, 0, -1); + SDL_SendMouseWheel(NULL, event.motion.which, 0.0f, -1.0f, SDL_MOUSEWHEEL_NORMAL); motion_dy += high; } } diff --git a/build.gradle b/build.gradle index 2f2380b05..ed2299cb0 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:8.2.1' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 18327d574..db7a5fb47 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Mon Nov 13 22:58:21 EST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists