rclone to 1.73 and ndk to 29, Internxt, Drime support#394
Conversation
Internxt requires interactive authentication to connect to their API and retrieve a mnemonic during config. This change adds internxt to the list of providers that use the OAuth-style ConfigCreate flow, enabling proper authentication handling.
…logging - Add internxt to OAuth-style providers list for interactive multi-step auth - Internxt requires connecting to their API to get mnemonic and handle 2FA - Add error logging to RemoteConfigHelper to capture rclone stderr on failure - This helps debug authentication issues with new backends
- Add InternxtTwoFactorStep and InternxtTwoFactorAction to OauthHelper.java - Shows dialog for 2FA code input, blocks until user enters code - Add InternxtFinishStep to handle config completion - Update ConfigCreate.kt to detect Internxt and use InteractiveRunner - Pass provider type from DynamicRemoteConfigFragment to ConfigCreate - Uses CountDownLatch for thread synchronization with UI dialog
- Process all rclone log lines for stats/progress, not just error/warning - Notification now updates with transfer progress, speed, ETA during sync - Speed indication was already implemented in StatusObject, just not being used - Add signing config passwords for release builds
…agement Implements proactive session healing for OAuth-enabled remotes (Internxt, etc.) Phase 1 - Go Backend: - Replace boolean authFailed with stateful authFailCount/nextAuthAllowed - Add TOTP time window retries (T, T-1, T+1) for clock skew handling - Implement exponential backoff: 1m, 5m, 15m, 1h, 1h with ±10% jitter - Max 5 failures before requiring manual re-auth - Reset authFailCount to 0 on successful operations Phase 2 - Android WorkManager: - Create SessionGuardianWorker for 8-hour periodic health checks - Discover OAuth remotes via config dump (token/access_token/totp_secret) - Lightweight health probe using rclone lsd --max-depth 1 - Silent healing via Go backend during probe - Add SessionGuardianScheduler with network/battery constraints Phase 3 - Android UI: - Add "Re-authenticate" menu item to remote options - Manual re-auth triggers existing RemoteConfig with CONFIG_EDIT_TARGET - Leverages existing OAuth flow and Internxt 2FA UI Phase 4 - Failsafe Notifications: - Detect "auth exceeded max retries" error from Go backend - Show notification with deep-link to Remotes view - Added checkAndNotifyAuthError() helper for easy integration This moves from "Hard Fail" to "Resilient Background Healing" model, preventing silent session drops after 2FA failures or clock skew. Resolves: Sessions dropping silently for 2FA-enabled remotes after few days
- Enable CGO_ENABLED=1 for Android ARM builds (was disabled) - Add CC environment variable pointing to NDK cross-compilers - Support ARM64 Linux as build host (os.arch detection) - Fixes cross-compilation on ARM64 build machines Note: This enables native builds on ARM64 Linux hosts when using the Android NDK with x86_64 toolchains via QEMU or native compilers.
- Skip cross-compiler (CC env var) on Windows builds - Let Go handle CGO natively on Windows (Go 1.25.6 supports this) - Only use cross-compiler when available (Linux/Mac builds) Fixes build failures on Windows AMD64 systems where getCC() returned null and caused Go build to fail with empty CC environment variable. Tested on: Windows 10 (amd64) / AMD Ryzen 8845HS
- Document GitHub Actions workflow usage (already working) - Provide multiple build options (GitHub Actions, MinGW, Docker, skip) - Include download instructions for APK artifacts - Explain current Session Guardian implementation status This helps users on Windows build APKs using CI/CD workflow
- Complete rewrite of android.yml workflow - Added detailed comments explaining Session Guardian features - Documented each build step - Added conditional uploads based on build success - Included build summary with download instructions - Added workflow_dispatch for manual triggering This workflow builds all APK architectures including arm64-v8a needed for Pixel 9 and other devices.
- Fix line 320: use mrand.Int63n instead of rand.Int63n (import alias) - Fix line 400: rename offset to truncationOffset to avoid variable shadowing These errors were preventing rclone compilation in GitHub Actions due to CGO cross-compilation issues.
- Set CGO_ENABLED=0 to avoid cross-compilation issues - Session Guardian code uses only standard Go libraries, no CGO needed - Fixes build failures on GitHub Actions due to missing standard library packages
- Re-enabled CGO (required for Android ARM builds) - Added go install std step before rclone build to prepare Android std lib - This should resolve 'could not import' errors when cross-compiling - Cleaned up duplicate steps in GitHub Actions workflow
- Removed duplicate/corrupted section from buildRclone function - File had duplicate lines from previous edit - Now build.gradle has correct structure with std lib build step
- Removed 'android' tag from Go build command - The android tag was causing import issues with CGO cross-compilation - Keeping 'noselfupdate' tag to exclude update checking - This should allow Go to find the standard library packages
- Reverted to CGO_ENABLED=0 (no CGO required for GitHub Actions) - Removed CC compiler environment variable - Restored 'android' build tag - This matches the working configuration before Session Guardian changes - CGO changes were intended for ARM64 Linux hosts, not CI/CD
- Changed GOOS from 'android' to 'linux' to bypass CGO requirement - Removed 'android' build tag since we're targeting linux now - This allows building without CGO, avoiding standard library issues - Linux ARM binaries should still work on Android (Android is Linux-based)
- Changed Go version from 1.24 to 1.19.8 - This matches the configuration that was working before Session Guardian - Go 1.24 may have compatibility issues with cross-compilation - Using proven Go version that was successfully building earlier
- Added build-windows.ps1 - PowerShell build script with menu - Added build.bat - Simple batch file launcher - Added WINDOWS_BUILD_GUIDE.md - Detailed build instructions - Added BUILD_CHECKLIST.md - Environment verification checklist These files help users build Session Guardian APK locally on Windows (Ryzen 8845HS) to work around GitHub Actions CGO issues.
- Removed incorrect -x flags (were excluding tasks instead of running) - Changed to use module-specific task :app:assembleOssDebugArm64-v8a - Added proper error checking with LASTEXITCODE - Shows BUILD FAILED message when build exits with error - Added safety check to verify APK was actually created This fixes the issue where ARM64 build was failing due to incorrect Gradle syntax.
- Migrate package namespace from de.felixnuesse.extract to de.schuelken.cloudbridge - Update display names across localized string resources - Generate and apply padded launcher icons from new CloudBridge logo - Adjust theme colors for new branding - Update GitHub download URL for automatic updates - Clean up outdated badges and standardize version bumping rules
…oudBridge This release completes the transformation from Round Sync to CloudBridge. Key Changes: - App Identity: Renamed application ID to de.schuelken.cloudbridge and built as CloudBridge 1.0.0 (versionCode 10). - Package Structure: Fully migrated and renamed the java/kotlin packages from de.felixnuesse.extract to de.schuelken.cloudbridge. - Visual Assets: Regenerated and integrated all new Android launcher icons and adaptive foregrounds, fully padded for proper rendering inside circular masks. Updated colors.xml to the new blueish primary palette. - UI Strings & Localization: Rewrote all legacy project references to CloudBridge across English, German, Catalan, and Simplified Chinese localizations. - Documentation & Build Pipelines: Cleaned up README.md badges, specified new GitHub source URLs (thies2005/CloudBridge) for automatic app updates, and set up the documentation domain to cloudbridge.schuelken.uk.
…custom DNS resolver - Switch rclone source to thies2005/rclone fork which includes Android DNS override - Add getDnsServers() to Rclone.java and RcloneRcd.java using ConnectivityManager - Pass detected DNS servers via RCLONE_DNS_SERVERS env var to rclone process - Falls back to Google DNS (8.8.8.8, 8.8.4.4) if detection fails
Property names were renamed from de.felixnuesse.extract.* to de.schuelken.cloudbridge.* but the CI workflow still grepped for the old names, causing NDK version to be empty.
- Switch from debug to release builds with the in-repo keystore - Auto-tag as v<version>-beta.<short-sha> on every master push - Attach all ABI APKs to a prerelease GitHub release - Clean up old beta releases before creating new one
|
Hi! |
SessionGuardianWorker was treating ANY non-zero rclone exit code as a session expiration, including DNS/network failures. This caused false 'Session expired' notifications when the device had intermittent connectivity (e.g. DNS resolver not ready on wake). Changes: - Rclone.listDirectories() now returns DirectoryProbeResult with both exit code and stderr output - DirectoryProbeResult.isNetworkError() detects transient network issues (DNS failure, connection refused, timeout, etc.) - SessionGuardianWorker skips notification for network errors, only notifies on genuine auth/session failures
|
Hi, When I first found your app I was very happy to finally find a good and reliable rclone syncing for my media and different backups. Then I saw that it hadn't been updated in a while, and with AI I updated the rclone and opened this merge request. As some time passed, I needed rclone to re-auth Internxt on my server so I could reliably run my Immich server with it while still using 2FA. So I decided to fork rclone/rclone and implement the changes there, so I could then use my custom fork on the server and in the app. Due to the license, I saw I needed to change the name and so on of the app, and I started doing so but haven't migrated it completely. I am a medical student and don't have too much time. I guess when merging you don't want the custom rclone ? Also, I wanted to ask if I can publish my app on the Play Store for easier access? I would credit you and the previous fork and link to the source code. What do you think? |
|
Ah, the license is more for "republishing". If you use the app only for yourself, even a fork, you do not need to change the name. That part is only if you "publish" it officialy, like on github releases or google play. The reason for the long time without updates is twofold:
But a rewrite is extremely time consuming. Regarding the appstore: i won't stop you.
What i instead suggest you to do is to either use fdroid (which is more complicated) or the far easier variant by using obtainium and there you add your own fork from github. (Note: if that is your goal, the name-change stuff also does not apply. its really just if you want to long-term maintain your own fork) Now to this pr: |
…iles - Add project-specific agent guidelines (AGENTS.md) covering core rules, rclone upgradeability policy, build/verification commands, and conventions. - Remove obsolete build logs, patches, and temporary planning docs that are not relevant to the project going forward.
|
Hi, |
…grity) Phase 1 (critical bugs + security + build unblocking): - RC-9/11/12/17/18: add return after finish(), null-guard rclone stdout/config - RC-23/25: null-check Thumbnails remote; fix inverted getDisplayNameCompat - RC-2: allowBackup=false; RC-4: unexport app-private components - RC-5: serve() requires creds for remote bind; ServeDialog enforces non-empty - RC-6/7/8: fix dependencies.yml globs/prefix, SDK 34->35, pin rclone ref (SHA) - Guard pre-existing NewApi (destroyForcibly/waitFor) for API < 26 in InternxtReauth Phase 2 (correctness + resource hygiene): - RC-13: scoped WorkManager cancellation (replace cancelAllWork) across 3 managers - RC-22: UpdateWorker -> CoroutineWorker, returns real result - RC-15/16: RcdService thread-safety (final lock, volatile bool, sync spawn) - RC-10/20/26: drop leaked probe process, guard exitValue, try-with-resources - RC-21: rewrite update download (GitHub metadata, SHA-256/size verify, WorkManager) - RC-27: remove duplicate FileProvider - RC-30: VCP remotes/remotes dedup + main-thread-safe getDocumentType; real upload FileItem - RC-24: Log2File rotation 10GB->10MB + null ext-dir guard - RC-3: add credential-storage ADR (design gate) Phase 0 (RC-1 signing key rotation) intentionally SKIPPED to preserve the existing GitHub release signature, per constraint. Verification: ./gradlew testOssDebugUnitTest + lint + assembleOssDebug all green. Checkpoint: pushing to resume Phase 3 (UI/UX) and later phases on a cloud instance.
Phase 3 — UI/UX, Accessibility & Dark-Mode: - RC-34: add values-night/colors.xml + values-night-v31 overrides so the convenience color aliases (cardColor, iconTint, dividerColor, text*, fabOverlay) resolve to dark tokens instead of light. SecondaryCardStyle no longer uses the M3-1.2-only colorSurfaceBright (swapped to colorSurfaceVariant). - RC-33: actionBarSize 12dp -> 56dp (typo). MainViewToolbar contrast fixed (colorOnSecondary -> colorOnPrimary); overflow/dialog parents repointed to M3. - UI-028: wire core-splashscreen (Theme.App.Starting + installSplashScreen in MainActivity). - RC-32: extract every hardcoded UI literal to @string (Run on Failure/Success, "Switch preference" placeholder, task id/path placeholders -> tools:text, 7 Toast/setTitle literals). - RC-40: add Locale.ROOT to all 14 DefaultLocale toLowerCase() sites. - RC-35/36: contentDescription on interactive icons, importantForAccessibility on decorative settings icons, labelFor on 8 EditTexts, paddingStart/End, 48dp tap targets, SwitchPreference -> SwitchPreferenceCompat (12 sites). - RC-37: delete now shows an undo Snackbar; the destructive WorkManager enqueue is deferred until the undo window elapses. - RC-38: cache rclone config-dump JSON in Rclone.getRemotes() (invalidated on config()/deleteRemote()); pin state still re-applied fresh each call. - UI-020/021: fragment_logs empty state; FileExplorerFragment keeps the current listing on a transient rclone error instead of blanking. Phase 4 — Architecture & Tech-Debt: - RC-28: add RemoteItem INTERNXT/DRIME types + getTypeFromString cases (were falling through to -1 / generic icon and colliding in equals/hashCode); add RemoteItemTest covering type resolution and distinctness. - 4B: delete dead rclone/patches/internxt/ Go source (fork already contains it), remove no-op fileTree('libs') + dead VERSION_11 ext, drop commented Intent blocks and literal-"TAG" logs, fix SyncService "SYNC_SERCVICE" typo. - RC-31: align okhttp logging-interceptor to 4.12.0; remove unused Glide annotationProcessor (no @GlideModule). NOTE: Jackson, legacy-support-v4 and streamsupport are KEPT — they are actually imported (the prior audit verdict that streamsupport was unused was wrong: java9.util.* is used in 3 files). - 4D: add kotlinx-coroutines-android + lifecycle-runtime-ktx infrastructure and migrate MarkdownView.LoadMarkdownAsset off AsyncTask (executor + View.post). The remaining ~26 AsyncTask / 3 IntentService migrations are intentionally staged file-by-file per the plan (each its own PR); doing them blind in one commit without a compiler was deemed too risky. Phase 5 — CI, Polish & Docs: - BUILD-008/009: SHA-pin every uses: across all 4 workflows; replace the compromised tj-actions/changed-files@v44 with a post-fix v46 SHA and fabasoad/translation-action@main with a pinned tag; add a PR-gated ./gradlew testOssDebugUnitTest step to lint.yml. - BUILD-019: rclone/build.gradle Go-version check now throws GradleException instead of logger.error. - BUILD-021..024, CQ-010/011: fix Go version (1.20/1.19.8 -> 1.25), license URL, assembleDebug -> assembleOssDebug, drop fictional usePrebuiltRclone section, APK glob roundsync_v -> cloudbridge_v, AGENTS.md CI description (release, not debug). - CQ-021: rename BootReciever/TriggerReciever/ClearReportBroadcastReciever -> *Receiver (classes, manifest, imports, Intent refs). Deferred (documented): full CardView -> MaterialCardView migration (cosmetic), ListAdapter+DiffUtil migration, edge-to-edge, tablet layouts, and the remaining AsyncTask -> coroutines migrations — all lower-risk to land with CI feedback. No build toolchain was available locally; verified via static checks (XML/YAML parse, import/reference consistency, subagent code review) and CI is the gate.
The Phase 3-5 commit was authored without a build toolchain ('verified via
static checks'). Three independently-fatal build errors slipped through:
1. Duplicate string resources: values/strings.xml redefined internxt_2fa_title
and internxt_2fa_message (RC-32 extraction collided with the pre-existing
canonical strings already referenced by OauthHelper/InternxtReauth/ConfigCreate).
-> mergeOssDebugResources: 'Found item more than one time'. Removed the dupes.
2. Corrupted ConstraintLayout attribute: an a11y edit in fragment_log_item.xml
mangled the adjacent attribute layout_constraintTop_toTopOf into the invalid
layout_constraintTopToTopOf (dropped underscore).
-> AAPT: 'attribute layout_constraintTopToTopOf not found'. Restored the name.
3. Over-strict Go-version gate: BUILD-019 made checkoutRclone throw on mismatch,
but the check used contains("1.25.0") which rejects compatible patches like
1.25.11. -> Replaced with a proper major.minor comparison that accepts any
patch of the required minor and any newer minor, while still failing fast on
an genuinely incompatible toolchain (BUILD-019 intent preserved).
Verification: ./gradlew testOssDebugUnitTest, lint -x :rclone:buildAll, and
assembleOssDebug all BUILD SUCCESSFUL after these fixes (5 ABI APKs produced).
Release signing key rotation (P0): the committed roundsync.keystore plus the hardcoded 'android'/'android' passwords in app/build.gradle compromised the signing identity. Generated a new RSA-4096 key (CN=CloudBridge Release, 25y), moved credentials into a git-ignored keystore.properties (local) / CB_* env vars (CI), removed the old keystore from the repo, and added .gitignore rules. android.yml now decodes the keystore from GitHub Secrets before signing. NOTE: existing installs signed with the old key cannot be updated in place (signature mismatch) and need a one-time reinstall. Correctness fixes: - UpdateDownloadWorker.sha256(): signed-Byte sign-extension made every digest wrong, so in-app updates with a published digest never verified. Mask to unsigned (it.toInt() and 0xFF). - Rclone getRemotes() cache: now volatile and validated against the rclone.conf mtime/length on every read, so per-instance caches self-invalidate when another Rclone instance (e.g. a config dialog) mutates the config; also fixes the cross-thread visibility race. synchronized the fetch to avoid duplicate rclone processes. - UpdateUserchoiceReceiver: enqueueUniqueWork(KEEP) so multiple Download taps no longer run concurrent workers writing the same APK. - RcdService.waitOnline(): stop using a synthetic NullPointerException for control flow; real NPEs inside isOnline() are no longer masked as 'not online'. - EphemeralWorker: recycle the Parcel on the read paths (matches the write side). - MarkdownView: ioExecutor threads are now daemons (no per-View thread leak). Security fixes: - UpdateUserchoiceReceiver + SyncService set exported=false (no callers relied on them being exported; closes an arbitrary-sync-trigger surface). - SafDAVServer: stop logging the local Authorization header on the not-implemented path. Lint: Locale.ROOT for stderr lowercasing; ellipsis char in internxt_reauth_progress. Verification: testOssDebugUnitTest, lint, assembleOssDebug, assembleOssRelease all green; release APK verified signed with the new key.
Upstream iBotPeaches/Apktool removed scripts/linux/apktool from master, so the wget 404'd and the non-FOSS library scan never ran. Inline a minimal wrapper that invokes apktool.jar from its own directory instead of fetching the fragile external script.
Targeting SDK 35 enforces edge-to-edge, so toolbar/content rendered behind the status bar (text invisible). Explicitly opt out per activity via WindowCompat.setDecorFitsSystemWindows(window, true), restoring the pre-35 fit-to-system-bars behavior. OnboardingActivity is left on edge-to-edge by design.
Replace the hardcoded rclone --transfers 1 with a configurable value. Adds a ListPreference (1/2/4/8, default 1) under Settings > Background Work, read by Rclone for sync/download/upload. Persisted through the JSON settings backup/restore.
setDecorFitsSystemWindows(true) per activity was not reliably keeping content below the status bar (e.g. the RemoteConfig search bar still sat under the status line). Add android:windowOptOutEdgeToEdgeEnforcement to AppTheme (light/night) and the splash Theme.App.Starting so every window is created with the legacy fit-to-system-bars behavior. The attribute is API 35+ only and a no-op below that (tools:ignore=NewApi).
Update rCloneRef to the latest thies2005/rclone master and align the informational rCloneVersion. Verified to cross-compile for all ABIs.
Beta APKs all shared versionCode 20 / versionName 1.0.1, so they were
never real updates and installs stalled. CI now derives versionCode from
the git commit count (*10; ABI offsets use 6-9) and versionName as
<base>-beta.<short-sha>, passed to Gradle via CB_VERSION_CODE /
CB_VERSION_NAME env vars (matching the existing RCX_BUILD_CLI pattern).
Also fix the delete-previous-betas step: it grabbed the release title's
first word ("Beta") instead of the tag, so old betas accumulated and the
newest no longer sorted to the top. Now lists tags via --json and deletes
by the real tag, keeping only the latest beta.
- Add optional per-task --transfers override (DB v7 migration adding task_transfers column, Task.transfers field, TaskActivity spinner with 'Use global setting'/1/2/4/8) that falls back to the global pref when unset. Plumb SyncWorker -> Rclone.sync() 8-arg overload. - Fix silent-success bug for unsupported sync directions: SyncWorker now validates the direction and reports a clear UNSUPPORTED_DIRECTION failure instead of treating a null rclone process as success. Affects legacy/imported bisync (direction 5/6) tasks.
actions/checkout defaults to a shallow depth-1 clone, so 'git rev-list --count HEAD' returned 1 and every beta APK was built with versionCode 10. Android then refuses the update because the new APK is not newer than the installed one. Set fetch-depth: '0' so the full commit count (e.g. 1604 -> versionCode 16040) is used, making each beta a real, installable update.
Implements the transmission-speed audit findings (P0-P2): - Raise default --transfers from 1 to 4 (rclone upstream default) - Hold PARTIAL_WAKE_LOCK + high-perf WifiLock for the duration of transfers (EphemeralWorker, SyncWorker, RcdService) so the device does not stall in Doze with the screen off; add WAKE_LOCK perm - Throttle EphemeralWorker notification rebuilds to >=500ms and only when content changed (previously rebuilt on every stderr line) - Add CloudBridgeApp Configuration.Provider (setMaxSchedulerLimit=50) and disable the default WorkManager initializer - Bump safdav SAF write buffer 1KB->64KB and write directly through ContentResolver (DocumentsContractAccess.writeFile) - Bump VirtualContentProvider pipe buffer 4KB->128KB - Add --transfers/--buffer-size/--multi-thread-streams and --vfs-read-chunk-size* flags to serve and rcd - Move DownloadAndOpen AsyncTask off the shared serial executor - Speed up share-intent staging copy (64KB + BufferedOutputStream) - Fix VirtualContentProvider MaxWait reporting success before rcd jobs complete (await returns completion state; longer timeouts) - Parallelize rcd job-status polling over a small executor with synchronized access to lastStatus/jobsHandlers
TransferLocks.acquire used a multi-catch on SecurityException and RuntimeException, which is illegal (SecurityException subclasses RuntimeException) and broke compilation. Collapse to RuntimeException. Also align the 'transfers' default in SharedPreferencesBackup from '1' to '4' so all call sites match the new rclone upstream default introduced in the perf commit.
The 'Session expired' notification previously launched MainActivity generically and required the user to find and long-press the remote to re-authenticate. It now deep-links into the InternxtReauth flow for the named remote. - AppErrorNotificationManager: notification intent now carries the MAIN_ACTIVITY_START_REAUTH action + remote name; request code varies per remote with FLAG_UPDATE_CURRENT so distinct remotes don't alias. - MainActivity: add onNewIntent (required by singleTop launch mode so a foreground tap is not dropped) and a handleReauthIntent branch that resolves the remote and launches InternxtReauth directly. - InternxtReauth: capture secret-filtered rclone stderr and surface it in the failure toast instead of a generic 'error creating remote'. - Bump rCloneRef to the fork commit that restores the auth circuit breaker and TOTP clock-skew retry (see rclone fork 94f543c9d).
Adds remote-to-remote sync (direction 7) and copy (direction 8) so tasks can transfer data between two cloud remotes without a local hop. rclone performs a server-side copy where the backend pair supports it. - SyncDirectionObject: new SYNC_REMOTE_TO_REMOTE/COPY_REMOTE_TO_REMOTE constants and explicit spinner<->direction mapping (the spinner array is sparse, so position can't be derived from the constant value). - Task: add remoteId2/remoteType2/remotePath2 destination fields plus matching DB columns (DatabaseHandler/DatabaseInfo schema bump). - TaskActivity: destination-remote UI card shown only for cloud-to-cloud directions, with validation rejecting identical source/dest paths. - Rclone.sync: new overload taking a second remote; routes local<->remote vs remote-to-remote based on the direction. - SyncWorker/TasksRecyclerViewAdapter: plumb the new directions through. - gitignore: ignore stray node_modules/, package*.json and .zcode/.
Changes: * New Providers: * Added explicit support for Drime cloud storage. * Added support for Internxt decentralized cloud storage, including a new flow for handling Two-Factor Authentication (2FA). * UI Enhancements: * Updated transfer notifications to display real-time Upload and Download speeds. * Added session statistics to track total data Uploaded and Downloaded. * Documentation: * Updated README.md to reflect the newly supported providers. bumped rclone to 1.73 and ndk to 29