<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged android-development</title>
<link>https://coderlegion.com/tag/android-development</link>
<description>Powered by Question2Answer</description>
<item>
<title>Android Fullscreen Video Exit and Layout Restore</title>
<link>https://coderlegion.com/31598/android-fullscreen-video-exit-and-layout-restore</link>
<description>&lt;p&gt;When an HTML5 video requests fullscreen playback inside an Android WebView, the application often encounters visual artifacts, broken back button handling, or frozen system bars upon exit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quick solution:&lt;/strong&gt;&lt;br&gt;
Implement WebChromeClient callbacks to store the original layout visibility and window flags before adding the custom video view to a dedicated FrameLayout container, and restore those exact flags inside onHideCustomView.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;private View mCustomView;
private WebChromeClient.CustomViewCallback mCustomViewCallback;
private FrameLayout mCustomViewContainer;
private int mOriginalSystemUiVisibility;
private int mOriginalOrientation;

@Override
public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
    if (mCustomView != null) {
        callback.onCustomViewHidden();
        return;
    }
    mCustomView = view;
    mCustomViewCallback = callback;
    mOriginalSystemUiVisibility = getWindow().getDecorView().getSystemUiVisibility();
    mOriginalOrientation = getRequestedOrientation();
    
    ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
    mCustomViewContainer = new FrameLayout(this);
    mCustomViewContainer.setBackgroundColor(Color.BLACK);
    mCustomViewContainer.addView(mCustomView, new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT));
    decorView.addView(mCustomViewContainer, new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT));
            
    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
            View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
            View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
            View.SYSTEM_UI_FLAG_FULLSCREEN |
            View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}

@Override
public void onHideCustomView() {
    if (mCustomView == null) {
        return;
    }
    getWindow().getDecorView().setSystemUiVisibility(mOriginalSystemUiVisibility);
    setRequestedOrientation(mOriginalOrientation);
    
    ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
    decorView.removeView(mCustomViewContainer);
    mCustomViewContainer = null;
    mCustomView = null;
    mCustomViewCallback.onCustomViewHidden();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;who-owns-the-fullscreen-custom-view-&quot;&gt;Who owns the fullscreen custom view?&lt;/h3&gt;
&lt;p&gt;The host activity owns the container and manages the lifecycle of the fullscreen view, while the WebView engine triggers the creation request via the WebChromeClient interface. Developers often mistake the WebView itself as the direct renderer of the fullscreen element. In reality, the web engine passes a native View instance to the onShowCustomView callback method. The host activity must intercept this view, attach it to a top-level overlay layout such as a full-screen FrameLayout, and keep a direct reference to the supplied CustomViewCallback so it can signal when playback concludes.&lt;/p&gt;
&lt;p&gt;If the host activity fails to maintain exclusive ownership, multiple enter requests can orphan the initial view in memory. Checking whether the custom view reference is already non-null before assigning a new one prevents memory leaks and overlapping layers. For more details on standard web chrome handling, consult the official &lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.android.com/reference/android/webkit/WebChromeClient&quot;&gt;Android WebChromeClient reference&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;how-does-back-trigger-the-paired-exit-path-&quot;&gt;How does Back trigger the paired exit path?&lt;/h3&gt;
&lt;p&gt;When a user presses the physical or predictive hardware back button during fullscreen video playback, the event must bypass the web engine navigation stack and immediately trigger the custom view dismissal. If the back button only invokes webView.goBack(), the web page may navigate to a different document while the native fullscreen container remains active on screen, trapping the user in a black overlay.&lt;/p&gt;
&lt;p&gt;To wire this correctly, the activity should override onBackPressed to check if a custom view is currently active. If the view is present, invoke the hiding method directly. If the view is null, delegate the event to super or let the WebView handle internal history.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;@Override
public void onBackPressed() {
    if (mCustomView != null) {
        onHideCustomView();
    } else if (mWebView.canGoBack()) {
        mWebView.goBack();
    } else {
        super.onBackPressed();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This paired exit path ensures that whether the exit is triggered by the web player's internal close button or the device back button, the exact same teardown sequence executes cleanly. Sometimes developers forget to &lt;a rel=&quot;nofollow&quot; href=&quot;https://raylabs.app/articles/audit-macos-system-data-before-deleting-developer-caches/&quot;&gt;audit macOS system data before deleting developer caches&lt;/a&gt; or checking resource limits in parallel debugging environments, leading to unexpected memory pressures during heavy web rendering. You can also review guidance on &lt;a rel=&quot;nofollow&quot; href=&quot;https://raylabs.app/articles/managing-context-window-limitations-in-ai-developer-tools/&quot;&gt;managing context window limitations in AI developer tools&lt;/a&gt; when optimizing complex codebases.&lt;/p&gt;
&lt;h3 id=&quot;which-prior-ui-flags-must-be-restored-rather-than-hard-coded-&quot;&gt;Which prior UI flags must be restored rather than hard-coded?&lt;/h3&gt;
&lt;p&gt;Developers frequently hard-code system bar visibility when exiting fullscreen mode, forcing visible flags or clearing all immersive flags unconditionally. This approach often breaks applications that feature complex layouts, such as edge-to-edge displays, dark-mode status bar configurations, or multi-window modes where specific system bar policies were active prior to video playback.&lt;/p&gt;
&lt;p&gt;Instead of applying blanket visibility values, capture the exact decor view system UI visibility flags and the requested screen orientation immediately before entering fullscreen. When the hide method executes, restore those captured integers. Proper handling of system UI flags aligns with the guidelines outlined in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.android.com/develop/ui/views/layout/immersive&quot;&gt;Android immersive system bars&lt;/a&gt; documentation.&lt;/p&gt;
&lt;h3 id=&quot;trade-offs-and-architectural-patterns&quot;&gt;Trade-offs and Architectural Patterns&lt;/h3&gt;
&lt;p&gt;When managing fullscreen custom views, developers must weigh encapsulation against flexibility. The following comparison table highlights common architectural options for handling media playback views inside hybrid applications.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Option &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;When to use it &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Trade-off or failure mode &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Recommendation&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Host Activity Overlay&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Standard multi-activity apps or single-activity apps with top-level container access. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Requires boilerplate code inside every activity hosting a WebView. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Recommended for most standard implementations.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Custom WebView Subclass&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Reusable component architectures where WebView encapsulates its own chrome callbacks. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Tight coupling between UI state and web rendering logic; harder to manage activity orientation changes. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Use only in heavily modularized UI components.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Fragment-Level Host&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Fragment-heavy single-activity architectures. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Lifecycle mismatch between Fragment view destruction and Activity window decor views can cause window leaks. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Requires careful cleanup in onDestroyView.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;edge-cases-and-failure-modes-in-production&quot;&gt;Edge Cases and Failure Modes in Production&lt;/h3&gt;
&lt;p&gt;Handling video playback transitions within a restricted WebView environment introduces subtle race conditions that can crash production applications. One common failure mode occurs when a user initiates a second fullscreen request before the first instance has completed its teardown sequence, resulting in an illegal argument exception or a leaked window token. Guarding your transition logic with explicit null checks and state verification flags prevents these asynchronous collisions.&lt;/p&gt;
&lt;p&gt;Another frequent issue involves audio focus and surface destruction during rapid orientation changes. When a device rotates while a video element is actively rendering inside a custom FrameLayout, the underlying activity recreation destroys the window decor view context. If the custom view reference is not deliberately detached from its parent container during the activity pause or destroy lifecycle callback, the application retains a hard reference to the defunct activity context, triggering severe memory leaks.&lt;/p&gt;
&lt;h3 id=&quot;verification-checklist&quot;&gt;Verification Checklist&lt;/h3&gt;
&lt;p&gt;Execute these verification steps in your test environment to confirm that the fullscreen exit transition operates correctly without leaving orphan views or corrupted window states.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[ ] Enter fullscreen video mode and exit twice in succession. Verify that the original layout, scroll position, and activity orientation are fully restored without visual distortion.&lt;/li&gt;
&lt;li&gt;[ ] Trigger exit using both the web player close button and the hardware back button. Confirm that both methods invoke the exact same cleanup code path and dismiss the overlay immediately.&lt;/li&gt;
&lt;li&gt;[ ] Force an activity recreation, such as rotating the screen while a video is in fullscreen mode. Verify that the custom view is dismissed and no background memory references persist in the destroyed activity context.&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31598/android-fullscreen-video-exit-and-layout-restore</guid>
<pubDate>Sun, 18 Oct 2026 10:46:13 +0000</pubDate>
</item>
<item>
<title>Oviora Builder: A Lightweight Android Studio Alternative for Low-Spec Windows PCs</title>
<link>https://coderlegion.com/24972/oviora-builder-a-lightweight-android-studio-alternative-for-low-spec-windows-pcs</link>
<description>&lt;p&gt; &lt;strong&gt;The Problem I Kept Running Into&lt;/strong&gt;&lt;br&gt;
Android development is powerful — but the &lt;em&gt;first step&lt;/em&gt; is brutal if your machine isn't strong.&lt;/p&gt;
&lt;p&gt;Ask any beginner who's tried to start Android development on a low-spec Windows laptop and you'll hear the same story:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Android Studio takes forever to install and even longer to index a project&lt;/li&gt;
&lt;li&gt;SDK setup is confusing — which components, which paths, which versions?&lt;/li&gt;
&lt;li&gt;JDK version conflicts break builds before you've written a single line&lt;/li&gt;
&lt;li&gt;Gradle errors read like a foreign language&lt;/li&gt;
&lt;li&gt;ADB device setup silently fails with no clear reason why&lt;/li&gt;
&lt;li&gt;By the time all of this is sorted, many beginners have already given up — before their first APK even runs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This isn't a hypothetical. It's a real barrier for students, self-taught developers, coding bootcamp learners, and anyone working on a 4GB RAM / 2-core / HDD machine — which describes a huge number of learners outside well-resourced tech hubs.&lt;/p&gt;
&lt;p&gt;I kept hitting this wall myself, and eventually built a tool to get past it.&lt;/p&gt;
&lt;h3 id=&quot;what-oviora-builder-actually-does&quot;&gt;What Oviora Builder Actually Does&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Oviora Builder&lt;/strong&gt; is a lightweight, CLI-based tool that lets you create a real &lt;strong&gt;native Android Java/XML project&lt;/strong&gt;, build a debug APK with Gradle, install it on a connected phone via ADB, and launch it — all from a few terminal commands, without ever opening Android Studio.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;oviora create MyApp
cd MyApp
oviora br
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That last command — &lt;code&gt;br&lt;/code&gt;, short for &lt;strong&gt;Build + Run&lt;/strong&gt; — does the entire pipeline in one shot: validates the project, backs up existing output, syncs your workspace into the actual Android project structure, builds the APK with Gradle, installs it with ADB, and launches it on your phone.&lt;/p&gt;
&lt;p&gt;On a local low-spec test (2GB RAM Windows PC), that entire flow — create, build, install, launch — finished in under 6 minutes.&lt;/p&gt;
&lt;h3 id=&quot;two-ways-to-get-started&quot;&gt;Two Ways to Get Started&lt;/h3&gt;
&lt;p&gt;Oviora Builder ships in two forms, depending on what's already on your machine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NPM CLI&lt;/strong&gt; (&lt;code&gt;npm install -g oviora-builder&lt;/code&gt;) — for developers who already have Node.js, JDK, Android SDK, and Gradle installed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows Installer (.exe)&lt;/strong&gt; — for complete beginners on a fresh Windows PC. It bundles a portable Node.js, JDK, Android SDK, ADB, and Gradle setup, so there's nothing to configure manually — you install it, open PowerShell, and start building.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The installer path is really the point of the project: it removes the setup barrier entirely for someone who has never configured an Android dev environment before.&lt;/p&gt;
&lt;h3 id=&quot;where-it-came-from&quot;&gt;Where It Came From&lt;/h3&gt;
&lt;p&gt;The idea started from a simple, recurring observation: most Android tooling assumes you already have a fast machine and a fully configured environment. Flutter, React Native, and even Android Studio itself are all excellent — but they're heavy by design, and that weight falls hardest on exactly the people who can least afford it: students and beginners on modest hardware.&lt;/p&gt;
&lt;p&gt;Oviora Builder isn't trying to compete with those tools on features. It has one narrow, deliberate goal:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Make native Android app development possible to &lt;em&gt;start&lt;/em&gt; on a low-spec Windows PC, without a heavy IDE getting in the way.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;who-it-s-actually-for&quot;&gt;Who It's Actually For&lt;/h3&gt;
&lt;p&gt;Oviora Builder is built for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Students and self-taught beginners&lt;/li&gt;
&lt;li&gt;Learners on low-spec laptops or older hardware&lt;/li&gt;
&lt;li&gt;Coding bootcamps and college labs with shared, modest machines&lt;/li&gt;
&lt;li&gt;Developers who just want a fast, no-GUI way to spin up a native Android project&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is &lt;strong&gt;not&lt;/strong&gt; aimed at senior Android engineers, large production teams, or anyone needing Jetpack Compose, a full debugger/profiler, or a signing/release pipeline — Android Studio remains the right tool for that. Oviora Builder solves a different, narrower problem: getting someone from zero to a working native APK on their own phone, as fast and painlessly as possible.&lt;/p&gt;
&lt;h3 id=&quot;what-makes-it-different&quot;&gt;What Makes It Different&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Oviora Builder &lt;/th&gt;&lt;th&gt;Android Studio &lt;/th&gt;&lt;th&gt;Flutter / React Native&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Setup for beginners &lt;/td&gt;&lt;td&gt;One installer, done &lt;/td&gt;&lt;td&gt;Complex, multi-step &lt;/td&gt;&lt;td&gt;Complex, multi-step&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Low-spec PC friendly &lt;/td&gt;&lt;td&gt;Core design goal &lt;/td&gt;&lt;td&gt;Heavy &lt;/td&gt;&lt;td&gt;Heavy/medium&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Output &lt;/td&gt;&lt;td&gt;Native Java/XML &lt;/td&gt;&lt;td&gt;Native &lt;/td&gt;&lt;td&gt;Cross-platform abstraction&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;GUI/IDE required &lt;/td&gt;&lt;td&gt;No &lt;/td&gt;&lt;td&gt;Yes &lt;/td&gt;&lt;td&gt;Often, for setup/debug&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A few things it does under the hood that beginners specifically benefit from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Built-in static lint&lt;/strong&gt; (&lt;code&gt;oviora lint&lt;/code&gt;) catches broken &lt;code&gt;@drawable/&lt;/code&gt;, &lt;code&gt;@color/&lt;/code&gt;, &lt;code&gt;@layout/&lt;/code&gt;, and &lt;code&gt;@id/&lt;/code&gt; references &lt;em&gt;before&lt;/em&gt; Gradle runs — instead of a slow build failing with a cryptic &quot;cannot find symbol&quot; error at the very end.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stale APK detection&lt;/strong&gt; — if you've edited your project since the last build, &lt;code&gt;oviora run&lt;/code&gt; rebuilds automatically so you never accidentally test an old APK.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plain-language error explanations&lt;/strong&gt; — common failures (missing SDK path, no device connected, manifest merger conflicts, AndroidX mismatches) are recognized and explained in plain English instead of dumping a raw Gradle stack trace on a beginner.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Safe-by-default file handling&lt;/strong&gt; — nothing is auto-restored or auto-renamed silently. If a workspace file goes missing or a support-library import needs updating, Oviora tells you and lets you decide, rather than guessing and possibly overwriting real project files.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;try-it&quot;&gt;Try It&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;npm install -g oviora-builder
oviora doctor
oviora create MyApp --package com.example.myapp
cd MyApp
oviora br
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/nagodip7-sys/oviora-builder&quot;&gt;https://github.com/nagodip7-sys/oviora-builder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;NPM: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.npmjs.com/package/oviora-builder&quot;&gt;https://www.npmjs.com/package/oviora-builder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Windows Installer: available on the GitHub releases page&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oviora Builder isn't trying to be the biggest Android tool out there. It's trying to be one of the fastest, least painful ways for a beginner on a weak Windows PC to go from nothing to a real, working native Android app on their own phone.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/24972/oviora-builder-a-lightweight-android-studio-alternative-for-low-spec-windows-pcs</guid>
<pubDate>Thu, 20 Aug 2026 08:34:19 +0000</pubDate>
</item>
</channel>
</rss>