You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Persistent Background TV File Sharing — Added persistent background TV file sharing service on Android TV / Fire TV, allowing paired mobile devices to browse TV storage even when UFM is closed on TV. Automatically starts when paired devices exist and stops when all are removed, with an on/off toggle in TV Settings (enabled by default).
Expanded Video & Image Media Format Support — Added comprehensive support for viewing, managing, and routing previously unlisted video, Camera RAW, modern HDR stills, and graphic design/texture formats across Local, Network (SMB, SFTP, FTP, NFS, WebDAV, DLNA), and Cloud storage (Google Drive, OneDrive, Dropbox, S3) on Mobile and Android TV.
Video Formats: Motion JPEG (.mjpeg, .mjpg, .mjp), Apple video (.m4v, .qt, .3g2, .3gp2), Transport Streams (.m2ts, .mts, .m2t, .tp, .trp), DVD & MPEG streams (.vob, .evo, .mpg, .mpeg, .mpe, .m1v, .m2v, .mpv), Flash video (.f4v), Ogg media (.ogv, .ogm), RealMedia & Windows Media (.rm, .rmvb, .asf, .wm), and professional video (.mxf, .dv, .divx, .xvid, .mk3d).
Camera RAW & Photos: Comprehensive camera RAW photo support (.cr3, .crw, .raf, .rw2, .orf, .pef, .ptx, .nrw, .srw, .srf, .sr2, .x3f, .erf, .kdc, .dcr, .k25, .mrw, .mos, .raw), modern HDR stills (.hif, .avifs, .hdr, .exr, .mpo, .jps, .pns), and graphic design/texture formats (.psd, .psb, .ai, .xcf, .kra, .clip, .tga, .targa, .dds, .wbmp, .cur, .ani, .pbm, .pgm, .ppm, .pnm, .pcx, .wmf, .emf).
Full Thumbnail Extraction: Guaranteed thumbnail generation and rendering across List and Grid views for all video formats via native FFmpeg frame decoding and Camera RAW formats via embedded Exif preview extraction across local and remote storage.
Delete and Rename in Slide Show — Added Delete and Rename options when viewing photos in UFM Slide Show on both Mobile and Android TV. Delete supports moving to local Recycle Bin or permanent deletion across local, network shares (SMB, FTP, SFTP, SCP, NFS, TV Share), and cloud drives with automatic index updates and slide advancement. Rename prompts with a pre-filled filename dialog and renames files on disk or remote shares while maintaining tags, index records, and playlist state.
Slideshow Speed Dialog — Added a dedicated Slideshow Speed picker dialog accessible from the 3-dots overflow menu on mobile and interval stepper controls on Android TV, offering selectable intervals from 0.5s to 5.0s.
Multi-Slot Clipboard for Copy/Move — Added multi-item clipboard capability supporting up to 10 clipboard slots across Local, Network shares (SMB, FTP, SFTP, SCP, NFS, TV Share), and Cloud storage (Google Drive, OneDrive, Dropbox, S3, iDrive E2, WebDAV, rclone) on Mobile and Android TV.
Slot Management & Combining — When copying or moving items while items already exist on the clipboard, a prompt allows appending to the active slot (combining local and network entries into unified slots) or creating a new slot. Capacity warnings notify users when 1 slot remains (at 9/10 slots) and prevent exceeding the 10-slot limit.
ViewPager2 Tabbed Clipboard Sheet & TV Dialog — Replaced the single-list clipboard sheet with a ViewPager2 tabbed interface (TabLayout with swipeable slot pages on mobile, and D-pad accessible navigation on Android TV) allowing users to inspect items per slot, remove individual items or entire slots, paste a specific slot ("Paste this slot"), or paste all slots in batch ("Paste all").
JPEG XL (.jxl) Image Support — Added full support for viewing and handling JPEG XL image files across all storage types (local, network, and cloud) and both device targets (mobile and Android TV). .jxl files now display thumbnails in all file browser views (list, grid, compact, large grid), recycle bin, and SAF picker; open and navigate in the built-in image viewer and slideshow; re-encode correctly when saving edits; extract accurate dimensions and megapixel count in the File Properties sheet; generate network thumbnails over SMB, SFTP, SCP, FTP, NFS, WebDAV, and DLNA and all cloud providers (Google Drive, OneDrive, Dropbox, S3/iDrive E2, Box); appear under the Images filter chip, search/index category, Smart Sort, and PDF export. Powered by jxl-coder (io.github.awxkee, Apache-2.0 / BSD-3-Clause, API 21+).
Changed
Settings Screen Categorization & Grouping — Reorganized the Settings hub across Mobile and Android TV into 10 structured card-grouped categories with section headers and polished glass container styling to improve discoverability and usability.
Modernized Slide Show Layout (Mobile) — Redesigned the mobile Slide Show layout with a streamlined top toolbar (Back, Title/Info, Play/Pause, 3-dots Overflow Menu) and a modern glassmorphic bottom photo action bar containing Rotate Left/Right, Draw/Markup, Crop, Save (always visible), Rename, and Delete.
Batch "Extract to New Folder" Isolation — When extracting multiple archives simultaneously using "Extract to New Folder" or "Extract & Select Folder", each archive is now extracted into its own dedicated subfolder named after the archive file across local, Shizuku, and network/cloud storage to prevent filename conflicts and mixed contents.
Fixed
Fixed slideshow skipping videos prematurely after the image interval duration, ensuring videos play to completion before advancing to the next item.
Fixed a bug where a play button, "2.5s" label, and interval seekbar were displayed across the bottom of images during regular photo viewing in UFM Slide Show.
Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the framework's per-glyph text-advance measurement while the Text Viewer measures its wrap-content content EditText during a normal window-measure pass — e.g. top frame android.graphics.Paint.nGetRunCharacterAdvance/getRunCharacterAdvance (the native per-character advance computation) under TextLine.getRunAdvance/handleText/handleRun/measureRun/measure/metrics → Layout.getLineMax/getLineExtent → TextView.desired → TextView.onMeasure, measuring the content EditText (activity_text_viewer.xml/activity_text_viewer_tv.xml: ScrollView → HorizontalScrollView → LinearLayout → EditText, wrap_content width), reached from a frame-draw traversal measure pass (Choreographer.doFrame → ViewRootImpl.performTraversals → measureHierarchy → performMeasure) — reported from a Hisilicon SMART_TV, SDK 34, app 1.8.6-GOOGLE. The text being measured is app-bounded (the viewer paginates at 16 KB per page and caps edit mode at 128 KB), the main thread is RUNNABLE and processing a fresh vsync frame at sample time, and the stack has zero za.kilowatch.ultimatefilemanager frames — the only non-platform frame is the bundled-library androidx.appcompat.widget.ContentFrameLayout in the window-decor chain, which breaks the pure-framework filter — so the >5 s block is device-side CPU starvation on the low-end TV (its DLNA/SSDP/HTTP-server background threads are all RUNNABLE) or a post-stall sample, not app business logic. The AnrWatchdogThread now treats a main-thread stack whose top frame is Paint.getRunCharacterAdvance/nGetRunCharacterAdvance, with a TextLine measurement frame, a TextView.onMeasure frame, a HorizontalScrollView frame and a ScrollView frame (the Text Viewer's wrap-content-in-horizontal-scroll layout), reached from a frame-draw traversal, with no za.kilowatch.ultimatefilemanager frames and no framework blocking primitive anywhere on the stack, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep an app frame on the stack (e.g. a main-thread setText of an unbounded document or a custom view measuring heavy text), a top frame that is not the per-glyph advance under the TextLine/TextView.onMeasure chain, a text measurement NOT reached from a ScrollView/HorizontalScrollView frame-draw traversal (e.g. a RecyclerView row), or a blocking primitive — and are still reported.
Fixed an ANR (App Freeze) when the main thread is blocked inside android.graphics.Bitmap.nativeSetPixel/setPixel while PremiumShareTvActivity.onCreate (Android TV Web Share screen) generated the share URL's QR code synchronously on the main thread — reported from a Hisilicon HiDPTAndroid Hi3751V350, SDK 34, app 1.8.4-GOOGLE. QrCodeUtils.generateQrCode() built a 512×512 RGB_565 Bitmap and wrote every pixel with a nested for (x) for (y) bitmap.setPixel(x, y, …) loop — 262,144 individual JNI nativeSetPixel round-trips — which on a low-end TV exceeded the 5 s ANR threshold and froze the UI at launch (the report's own DlnaSsdpListener, NanoHttpd Main Listener, WebShare-SSL-Proxy and DefaultDispatcher-worker-* threads are all RUNNABLE doing background work while the main thread grinds through per-pixel JNI calls). PremiumShareActivity (mobile Web Share) had the identical pattern in setupWebShareMode(), and both activities' updateConnectionInfo() regenerated the QR on the main thread on every network-state change. QrCodeUtils.generateQrCode() now fills an IntArray of width * height colors in a plain Java loop and uploads the whole buffer with a single Bitmap.setPixels(...) native call instead of per-cell setPixel calls, and both PremiumShareActivity and PremiumShareTvActivity now generate and apply the QR off the main thread (lifecycleScope.launch(Dispatchers.Default) + withContext(Dispatchers.Main)), matching the existing OneDrive device-code QR pattern. The generated QR is pixel-identical (same row-major mapping, same black/white, same 1-module margin, same 512×512) and remains scannable; Web Share URL/PIN display, server startup/teardown, temporary-file cleanup, and network-change URL updates are unchanged — only the thread and the pixel-upload path changed.
Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread at the construction of a java.util.concurrent.LinkedBlockingQueue while a freshly dispatched main-looper Runnable starts running — top frame java.util.concurrent.LinkedBlockingQueue.<init> (the bounded constructor that sets the queue's capacity fields and allocates its sentinel head Node; the no-arg constructor at line 245 delegates to the int capacity constructor at line 255, so the sample carries one or two <init> frames), under cw.run (an R8-obfuscated non-platform Runnable) sitting directly on android.os.Handler.handleCallback — reported from a Xiaomi 23053RN02Y, SDK 35, app 1.8.0-GOOGLE. A LinkedBlockingQueue.<init> is a µs-scale bounded object allocation that cannot by itself occupy the main thread for 5 s, and the main looper is demonstrably processing a freshly dispatched message at sample time (Handler.handleCallback directly below the Runnable's run()), which a thread parked inside a >5 s block cannot do — so the >5 s block is device-side slowness / CPU starvation on the phone (the report's own DlnaSsdpListener, NanoHttpd Main Listener, DefaultDispatcher-worker-* and HTTP-server threads are all RUNNABLE, starving the main thread) or a post-stall sample of the backlog the main looper drains after a genuine stall. The sampled frame is a platform java.* class, so the existing fresh-run-entry filter (which requires a non-platform top frame) did not match, and the obfuscated run() is not platform-prefixed, so the pure-framework filter did not match either. The AnrWatchdogThread now treats a main-thread stack whose top frame is LinkedBlockingQueue.<init>, whose run() is a non-platform method sitting directly on Handler.handleCallback, with no Handler.postDelayed frame (the watchdog-heartbeat re-post shape, already handled) and no framework blocking primitive anywhere on the stack, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside blocking work — a lock/wait/park, a BinderProxy.transact, a file/network/database I/O frame, or a top frame that is not the trivial queue constructor under that freshly-dispatched run() — and are still reported.
Fixed a crash (java.lang.RuntimeException: Unable to create service … AdbRemoteForegroundService → SecurityException: Starting FGS with type connectedDevice … requires permissions … [android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE]) when starting the ADB Remote foreground service on Android 14+ (API 34+) builds whose merged manifest lacked the FOREGROUND_SERVICE_CONNECTED_DEVICE permission — reported from a TV build (app 1.8.6-FOSS code 233, Android SDK 34). AdbRemoteForegroundService is declared in the shared main manifest with foregroundServiceType="connectedDevice" and started from the shared main source set (AdbWifiTransport.connect()), but android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE was declared only in the mobile source-set manifest, so tv* variants merged the service without the permission and Android refused the startForeground call, crashing the process from onCreate(). The permission is now declared in the main manifest alongside the other FOREGROUND_SERVICE_* permissions so every variant (mobile and TV) that can start the service holds it, and AdbRemoteForegroundService.onCreate() now guards the startForeground call with a try/catch that logs and calls stopSelf() instead of crashing — the ADB remote connection/notification behaviour is unchanged when the permission is present.
Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread while the framework saves an Activity's instance state during a normal Activity stop — top frame android.os.BaseBundle.unparcel (the parcel-parse that Bundle.putBundle performs on the saved-instance-state bundle; on the AndroidX path ComponentActivity.onSaveInstanceState → SavedStateRegistry.performSave → outState.putBundle(...), and on an app Activity's own save path the app's onSaveInstanceState override calling outState.putBundle(...)), under Bundle.putBundle → an R8-obfuscated non-platform onSaveInstanceState override (the app or bundled-library Activity) → android.app.Activity.performSaveInstanceState → Instrumentation.callActivityOnSaveInstanceState → ActivityThread.callActivityOnSaveInstanceState/callActivityOnStop/performStopActivityInner/handleStopActivity → servertransaction.StopActivityItem.execute, thread state RUNNABLE — reported from a Google Pixel 6a, SDK 37, app 1.8.4-GOOGLE. The sampled work is the bounded unparcel of the saved-state bundle during the framework-driven stop-save: unparcel is O(saved-state size) bookkeeping the framework runs on every Activity stop, the app's own saved state is small (search-query strings, mode strings, boolean flags — the app has no putBundle call and no large Parcelable in its saved state), and the main thread is RUNNABLE, so the frame cannot by itself occupy the main thread for 5 s on a normally-provisioned phone; the >5 s block is device-side slowness / CPU starvation or a post-stall sample of the backlog the main looper drains after a genuine stall. The AnrWatchdogThread filter 57 (isSaveInstanceStateUnparcelStall) now treats a main-thread stack whose top frame is BaseBundle.unparcel, with a Bundle.putBundle frame, a non-platform onSaveInstanceState override frame, an android.app.Activity.performSaveInstanceState frame and an ActivityThread stop-lifecycle frame (or a servertransaction.StopActivityItem frame), with no za.kilowatch.ultimatefilemanager frames and no framework blocking primitive anywhere on the stack, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside blocking work — a lock/wait/park, a BinderProxy.transact, a file/network/database I/O frame, an unobfuscated app frame on the stack, or saved-state work reached from app business logic outside the framework's Activity-stop save (e.g. an app-constructed huge Parcelable whose own write path blocks, which surfaces as a Parcel write frame, not a putBundle unparcel) — and are still reported.
Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside the framework's font-metrics measurement while a plain single-line TextView inside a scrollable content container measures its text during a normal window-measure pass — top frame android.graphics.Paint.nGetFontMetricsInt/getFontMetricsInt (the native font-metrics read, the innermost frame of the framework's text measurement) under TextLine.expandMetricsFromPaint/handleText/handleRun/measureRun/measure/metrics → BoringLayout.isBoring (the framework's single-line fast-path check that a text run can use the optimized boring layout) → TextView.makeSingleLayout/makeNewLayout → TextView.onMeasure, measuring a TextView nested inside LinearLayout(s) within an androidx.core.widget.NestedScrollView (a scrollable content/settings/about screen), reached from a frame-draw traversal measure pass (Choreographer.doFrame → ViewRootImpl.performTraversals → measureHierarchy → performMeasure) — reported from a Sony BRAVIA 4K UR3, SDK 29, app 1.8.6-GOOGLE. nGetFontMetricsInt is a bounded native call that returns the paint's font metrics, and BoringLayout.isBoring is an O(text-length) single-pass check the framework runs on every TextView relayout, so the measure of one screen's bounded text cannot by itself occupy the main thread for 5 s; the main thread is RUNNABLE and processing a fresh vsync frame at sample time, and the stack has zero za.kilowatch.ultimatefilemanager frames — the only non-platform frames are the bundled-library androidx.core.widget.NestedScrollView and androidx.appcompat.widget.ContentFrameLayout in the window-decor chain, which breaks the pure-framework filter — so the >5 s block is device-side CPU starvation on the low-end TV (its DLNA/SSDP/HTTP-server background threads are all RUNNABLE) or a post-stall sample, not app business logic. This is the BoringLayout.isBoring/font-metrics variant of the already-filtered Text Viewer per-glyph-advance report (filter 55, getRunCharacterAdvance/nGetRunCharacterAdvance top frame + ScrollView/HorizontalScrollView layout), sampled at the single-line font-metrics read inside an androidx NestedScrollView container instead, so filter 55 did not match. The AnrWatchdogThread now treats a main-thread stack whose top frame is Paint.getFontMetricsInt/nGetFontMetricsInt, with a BoringLayout.isBoring frame, a TextLine measurement frame, a TextView.makeSingleLayout/makeNewLayout/onMeasure frame, a scrollable-container frame (androidx.core.widget.NestedScrollView or the framework ScrollView/HorizontalScrollView), reached from a frame-draw traversal, with no za.kilowatch.ultimatefilemanager frames and no framework blocking primitive anywhere on the stack, as a false positive and resets its heartbeat instead of writing a report. Genuine freezes keep the main thread inside app business logic — an app frame on the stack (e.g. a main-thread setText of an unbounded document or a custom view measuring heavy text), a top frame that is not the font-metrics read under the TextLine/BoringLayout.isBoring/TextView.onMeasure measure chain, a text measurement NOT reached from a scrollable-container frame-draw traversal (e.g. a RecyclerView row or a non-scrollable screen), or a blocking primitive (a lock, file/network/database I/O or binder frame) — and are still reported.