Added
- Zero-Shift Contextual Selection Header (Mobile Only) — Replaced the expanding multi-row selection toolbar with an in-place contextual selection header that transitions seamlessly within the fixed 56dp top header upon long-pressing or selecting items across Local, Network (SMB, SFTP, FTP, NFS, WebDAV, DLNA), and Cloud storage (Google Drive, OneDrive, Dropbox, S3, Box) in both Single-Window and Twin Window modes. Eliminates vertical layout shifts and screen jumps, providing a real-time selection count, 1-tap dismiss button (
[X]), dynamic Select All / Deselect All toggle button (ic_select_all/ic_deselect_all), and quick access to all file operations via the Tools FAB. - Selection Mode Auto-Exit on Deselect — Deselecting the last selected item (or tapping "Deselect All") now automatically exits long-press selection mode and restores the normal list view without checkboxes across Local, Network, and Cloud storage in Single-Window and Twin Window modes.
- Photo EXIF Privacy Cleaner & Batch EXIF Renamer (Mobile Only) — Added a dedicated 3-in-1 Photo EXIF inspection, privacy scrubbing, and batch renaming tool accessible from the Tools FAB when images are selected across Local, Network (SMB, SFTP, FTP, NFS, WebDAV, DLNA), and Cloud storage (Google Drive, OneDrive, Dropbox, S3, Box, rclone).
- EXIF & Geotag Inspector: Visual carousel and card-based metadata inspector displaying camera optics (Make, Model, Lens, F-Stop, Shutter Speed, ISO, Focal Length, Flash, White Balance), capture/digitized timestamps, dimensions, device details, and GPS coordinates with interactive "View on Map" launcher and 1-tap single-photo geotag removal.
- Privacy Cleaner (Metadata Scrubber): Strips sensitive metadata before sharing with 1-click Full Privacy Wipe (GPS, camera hardware specs, serial numbers, author/artist tags while preserving photo orientation), Remove GPS Only, or Custom selective stripping (GPS, hardware, author, dates, camera settings), with destination choices for overwriting in-place, creating cleaned copies (
_cleaned), or exporting to a custom folder. - Batch EXIF Renamer: Renames photo collections in bulk using metadata tokens (
{YYYY},{MM},{DD},{hh}{mm}{ss},{MODEL},{ORIGINAL}, sequence numbering{#}), quick preset chips (Date + Original,Date Only,Camera + Date), and real-time preview with automatic duplicate conflict resolution. - Vector Icon & Customization: Registered new professional camera shield vector icon (
ic_exif_cleaner), customizable under Toolbar Icons on mobile.
Changed
- Storage Header Toolbar Standardization (Mobile Only) — Unified the top header toolbar on Local storage to match Network and Cloud storage: replaced the gear icon with the 3-dots overflow menu, moved the dedicated refresh button to the left of the 3-dots menu button, and styled the dropdown menu with a modern glassmorphism aesthetic while removing the Storage Analyzer entry.
- Modern "Create New" Options Dialog (Mobile & TV) — Modernized the "Create New" options dialog across Local, Network, and Online storage with a premium glassmorphic card design inspired by the Re-Index Folder dialog, featuring hero iconography, interactive cards with descriptive subtitles for New Folder and New Text File, and full D-pad TV navigation support.
- Modern "Select View Mode" Dialog (Mobile Only) — Modernized the file browser view mode chooser on mobile with a premium glassmorphic card dialog featuring visual mode indicators and descriptive layout subtitles for all List and Grid configurations.
- Modern "New Folder" & "New File" Input Dialogs (Mobile Only) — Replaced plain alert dialogs with premium glassmorphic input cards featuring hero icons, rounded Material 3 text input fields with clear buttons, and polished action buttons across Local, Network, and Cloud storage.
Fixed
- Amazon In-App Purchasing Initialization Guard — Fixed
"You must register a PurchasingListener before invoking this operation"error when initiating a tip purchase or resumingSupporterLoyaltyActivityon Amazon Appstore / Fire TV builds.AmazonBillingManagernow verifies and re-attempts listener registration before invokingpurchase(),getUserData(),getPurchaseUpdates(), orgetProductData(), and gracefully displays a user-friendly message (amazon_iap_not_ready) if the billing service is not yet ready. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread blocked inside a synchronous binder call to the system server's MediaSessionService while the app's media session (the bundled Media3 / ExoPlayer session in
UFMPlaybackService) syncs the platform media session's playback state — e.g. top frameandroid.os.BinderProxy.transactNativeunderBinderProxy.transact→android.media.session.ISession$Stub$Proxy.setPlaybackState→android.media.session.MediaSession.setPlaybackState, reached from the Media3 session's Player-listener playback-state dispatch (zy3.onPlaybackStateChanged→bd2.onPlaybackStateChanged→ … →sy3.v), invoked from a main-looper Runnable (cg.runsitting directly onHandler.handleCallback) — reported from an askey ADT-3 (Android TV), SDK 34, app 1.8.3-AMAZON (2026-08-12). The app merely ran the one-line framework APIMediaSession.setPlaybackState()whenever the player's playback state changed; the >5 s block is the system server's MediaSessionService response latency, which the app cannot act on, and the stack has zeroza.kilowatch.ultimatefilemanagerframes (the call path is the bundled Media3 library, R8-obfuscated to short names) — the same system-side wait class as the existing binder round-trip filters (unbind/bind service, vendor SDK service lookup, Activity launch, Google Play module, system-service fetch). The existingisLibraryHandlerBinderStallfilter (50) did not match because the binder call here is dispatched by a main-looper Runnable (Handler.handleCallback), not a Handler message (handleMessage). TheAnrWatchdogThreadfilter 61 (isMediaSessionSyncBinderStall) now treats a main-thread stack whose top frame isBinderProxy.transact/transactNative, containing the media-session binder proxy frameandroid.media.session.ISession$Stub$Proxy.setPlaybackStatereached through the frameworkandroid.media.session.MediaSession.setPlaybackStateAPI, with no app frames anywhere, 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 anywhere on the stack, or a top frame that is not the media-session binder transact (e.g. app code around a media-session update doing heavy work, a lock/file/database I/O frame, or a binder call to a different service) — and are still reported. - Fixed slideshow photos displaying uncentered/offset and top toolbar controls getting clipped when rotating the screen between portrait and landscape modes.
- Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread inside an R8-obfuscated ViewHolder bind chain at a bounded resource read while a RecyclerView lays out its rows during a normal frame-draw traversal — e.g. top frame
ct.getResources(the frameworkContext.getResourceslookup, a µs-scale OS-cached getter that returns the app's Resources object) undersx2.j/i87.a/z87.l/z87.d/rz4.b(five obfuscated app classes in the adapter's bind chain, spanning class boundaries) underandroidx.recyclerview.widget.LinearLayoutManager.b1/O0/h0(fill/layoutChunk/onLayoutChildren) underRecyclerView.t/r/onLayoutunderConstraintLayout.onLayout, reached from a frame-draw traversal (Choreographer.doFrame→ViewRootImpl.doTraversal→performTraversals→performLayout) — reported from a Hisilicon HiDPTAndroid Hi3751V350, SDK 34, app 1.8.4-GOOGLE (2026-08-18), the same low-end TV and session family as the already-filtered obfuscated RecyclerView-bind report (filter 38). The innermost call is the µs-scale resource getter, the app's per-row bind is bounded (cached prefs reads, string formatting, icon resolution, and thumbnail loads dispatched to background threads), and the stack has zeroza.kilowatch.ultimatefilemanagerframes and no blocking primitive anywhere, while the report's ownDefaultDispatcher-worker-*threads are busy inside nativeFFmpegThumbnailHelper.extractVideoFrame/extractFrame(several RUNNABLE) withDlnaFetchThread,NanoHttpd Main ListenerandDlnaSsdpListeneralso RUNNABLE — so the >5 s block is device-side CPU starvation on the low-end TV, not app business logic. This is the class-boundary-spanning bind variant of filter 38 (which requires the top two frames in the same obfuscated class), so filter 38 did not match. TheAnrWatchdogThreadfilter 59 (isRecyclerViewBindResourceLookupStall) now treats a main-thread stack whose top frame isgetResourceson a non-platform, non-app, non-RecyclerView class, with aLinearLayoutManager/GridLayoutManagerframe, aRecyclerView.onLayoutframe and a frame-draw dispatch (Choreographer.doFrame/ViewRootImpl.performLayout/performTraversals), with noza.kilowatch.ultimatefilemanagerframes 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 parked inside a blocking primitive (a lock, file/network/database I/O or binder frame), run unbounded app business logic in the bind whose top frame is not the bounded resource read (e.g. a main-threadBitmap.createBitmapor asetTextof an unbounded document), or reach the resource read from outside a RecyclerView frame-draw traversal (e.g. a measure pass or app business logic off the layout path) — and are still reported. - Fixed a false-positive ANR (App Freeze) report when the ANR watchdog samples the main thread at the entry of a bounded
java.util.concurrent.PriorityBlockingQueueenqueue while a bundled Google Play module — the Firebase Analytics / Google Analytics Measurement dynamite module (com.google.android.gms.dynamite_measurementdynamite, whose classes are R8-obfuscated to short names such asm7.*inside the dynamically loaded module) — dispatches one of its own main-looper Runnables — e.g.Handler.handleCallback→m7.km.run→m7.rd.e→m7.rd.i→PriorityBlockingQueue.add(top frame), thread state RUNNABLE — reported from a TPV 2021/22 Philips UHD Android TV, SDK 30, app 1.8.7-GOOGLE.PriorityBlockingQueue.add/offer/put(the unbounded queue'sadddelegates tooffer) is a µs-scale bounded enqueue — the heap-insertion sift-up is O(log n) and the array growth (tryGrow) is a bounded copy — that cannot by itself occupy the main thread for 5 s; the stack has zeroza.kilowatch.ultimatefilemanagerframes (the enqueue is dispatched by the module's own non-platform Runnable, not app business logic), the main looper is demonstrably processing a freshly dispatched message at sample time (Handler.handleCallbackdirectly below the Runnable'srun(), which a thread parked inside a >5 s block cannot do), and no framework blocking primitive appears anywhere (a genuinely contendedPriorityBlockingQueuelock surfaces as aLockSupport/AQS park frame, not theaddentry) — so the >5 s block is device-side slowness / CPU starvation on the low-end TV (the report's ownDlnaSsdpListener,NanoHttpd Main Listener,bc6 www.kilowatch.co.za,Packet Reader for 192.168.1.180andDefaultDispatcher-worker-*threads are all RUNNABLE) or a post-stall sample of the backlog the main looper drains after a genuine stall. TheAnrWatchdogThreadfilter 60 (isLibraryPriorityBlockingQueueEnqueueStall) now treats a main-thread stack whose top frame isPriorityBlockingQueue.add/offer/put, whoserun()is a non-platform method sitting directly onHandler.handleCallback, with noza.kilowatch.ultimatefilemanagerframes 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(surfacing as aLockSupport.park/AQS frame below the enqueue), aBinderProxy.transact, a file/network/database I/O frame, an app frame anywhere on the stack, or the enqueue reached from app business logic without aHandler.handleCallback-dispatchedrun()frame — and are still reported.