- Introduction
- Basic Setup
- Plain WebView
- Set to Fullscreen Mode on App Open
- Keep Fullscreen During Usage
- Keep Fullscreen After Accessing Navigation/System Bar
- Keep Fullscreen After Resume
Introduction
Android app development adventures - or when an AI guy, who prefers assembly or FORTRAN over JAVA, tries to build a fullscreen (web) app displaying results of a machine learning pipeline on a device.
Notes up front. Copying the first best example code from github or stackexchange should do the job and everything is done in 15 mins, right? Hell no! Yes, on modern Android SDK versions (31+) is seems to be more straight forward. However, it using the recommended programming language Kotlin resulted in trouble with resolving the right androidx
extensions via gradle and using Jetpack was a dead end as well. Hence back to JAVA it was and even that was not without troubles. This adventures is documented below. Have fun;)
Basic Setup
As we all know, the “s” in “IoT” stands for security… . Therefore, you can’t expect Android to be up to date on which software should be deployed. In this example compatibility with Android 9.0 was required.
The basic setup is straight forward. Creating a New Empty Activity
with the following settings:
Name: WebViewFullscreen
Package name: com.bla.webviewfullscreen
Language: Java
Minimum SDK: API 28: Android 9.0 (Pie)
After starting an empty project, an older androidx versions needs to be specified in build.gradle (:app)
:
dependencies {
implementation 'androidx.appcompat:appcompat:1.5.1'
The AndroidManifest.xml
is simple and straight forward.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.WebViewFullscreen"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/web"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
That is pretty much all that is needed to set up the app.
Plain WebView
The simplest thing that can be done is to run the webkit.WebView
activity as main activity. This is pretty straight forward. It is important to note that the “return button” should have some functionality and that links should be followed in this app without opening a new browser instance when pressing on a link. MainActivity.java
looks like this:
package com.bla.webviewfullscreen;
import androidx.appcompat.app.AppCompatActivity;
import android.view.Window;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
// define variable without constructing it
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// hides the app's title
requestWindowFeature(Window.FEATURE_NO_TITLE);
// hides the app's title bar
getSupportActionBar().hide();
// set main activity
setContentView(R.layout.activity_main);
// constructs WebView (linked to the element in the layout)
webView = findViewById(R.id.web);
// set default url
webView.loadUrl("https://archive-beta.ics.uci.edu/");
// with JavaScript & zoom enabled
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSupportZoom(true);
// allow to use it as a web browser (aka opening links)
// (otherwise following any other url results in opening
// the default browser)
webView.setWebViewClient(new WebViewClient());
}
// some basic navigation functionality ;)
@Override
public void onBackPressed()
{
if(webView!= null && webView.canGoBack())
// go to previous page if such a page exists in the history
webView.goBack();
else
// close app otherwise aka follow system-wide default for back button
super.onBackPressed();
}
}
Let’s open the app in the emulator. That looks like it should.

Set to Fullscreen Mode on App Open
Next a function is needed to set the fullscreen (immersive) mode. NB! this needs to be part of class MainActivity
. Immersive mode for newer versions (>= Build.VERSION_CODES.R
) is super simple and straight forward. Making it work with older versions is a bit more tricky.
private void setFullScreen()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
getWindow().setDecorFitsSystemWindows(false);
WindowInsetsController controller = getWindow().getInsetsController();
if(controller != null) {
controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
}
}
else {
// for older versions
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
}
The full source code of the main activity looks as follows now:
package com.bla.webviewfullscreen;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
// define variable without constructing it
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// hides the app's title
requestWindowFeature(Window.FEATURE_NO_TITLE);
// hides the app's title bar
getSupportActionBar().hide();
// set main activity
setContentView(R.layout.activity_main);
// constructs WebView (linked to the element in the layout)
webView = findViewById(R.id.web);
// set default url
webView.loadUrl("https://archive-beta.ics.uci.edu/");
// with JavaScript & zoom enabled
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSupportZoom(true);
// allow to use it as a web browser (aka opening links)
// (otherwise following any other url results in opening
// the default browser)
webView.setWebViewClient(new WebViewClient());
// set immersive (fullscreen) mode
setFullScreen();
}
// some basic navigation functionality ;)
@Override
public void onBackPressed()
{
if(webView!= null && webView.canGoBack())
// go to previous page if such a page exists in the history
webView.goBack();
else
// close app otherwise aka follow system-wide default for back button
super.onBackPressed();
}
private void setFullScreen()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
getWindow().setDecorFitsSystemWindows(false);
WindowInsetsController controller = getWindow().getInsetsController();
if(controller != null) {
controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
}
}
else {
// for older versions
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
}
}
So, let’s see what happens this new setFullScreen
function is called. On new versions everything is fine! On older versions we get this result when opening the app.

That looks good but as soon as there is any touch interaction, this happens:

Keep Fullscreen During Usage
Apparently, the View.SYSTEM_UI_FLAG_IMMERSIVE
was missing.
package com.bla.webviewfullscreen;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
// define variable without constructing it
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// hides the app's title
requestWindowFeature(Window.FEATURE_NO_TITLE);
// hides the app's title bar
getSupportActionBar().hide();
// set main activity
setContentView(R.layout.activity_main);
// constructs WebView (linked to the element in the layout)
webView = findViewById(R.id.web);
// set default url
webView.loadUrl("https://archive-beta.ics.uci.edu/");
// with JavaScript & zoom enabled
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSupportZoom(true);
// allow to use it as a web browser (aka opening links)
// (otherwise following any other url results in opening
// the default browser)
webView.setWebViewClient(new WebViewClient());
// set immersive (fullscreen) mode
setFullScreen();
}
// some basic navigation functionality ;)
@Override
public void onBackPressed()
{
if(webView!= null && webView.canGoBack())
// go to previous page if such a page exists in the history
webView.goBack();
else
// close app otherwise aka follow system-wide default for back button
super.onBackPressed();
}
private void setFullScreen()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
getWindow().setDecorFitsSystemWindows(false);
WindowInsetsController controller = getWindow().getInsetsController();
if(controller != null) {
controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
}
}
else {
// for older versions
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
}
}
Everything looks great now except when pulling down the system bar or trying to access the navigation bar.

Keep Fullscreen After Accessing Navigation/System Bar
It turns out the View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
was missing. NB!: on some devices tested it required both flags View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
&View.SYSTEM_UI_FLAG_IMMERSIVE
to return stay in fullscreen mode and not just the sticky flag.
package com.bla.webviewfullscreen;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
// define variable without constructing it
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// hides the app's title
requestWindowFeature(Window.FEATURE_NO_TITLE);
// hides the app's title bar
getSupportActionBar().hide();
// set main activity
setContentView(R.layout.activity_main);
// constructs WebView (linked to the element in the layout)
webView = findViewById(R.id.web);
// set default url
webView.loadUrl("https://archive-beta.ics.uci.edu/");
// with JavaScript & zoom enabled
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSupportZoom(true);
// allow to use it as a web browser (aka opening links)
// (otherwise following any other url results in opening
// the default browser)
webView.setWebViewClient(new WebViewClient());
// set immersive (fullscreen) mode
setFullScreen();
}
// some basic navigation functionality ;)
@Override
public void onBackPressed()
{
if(webView!= null && webView.canGoBack())
// go to previous page if such a page exists in the history
webView.goBack();
else
// close app otherwise aka follow system-wide default for back button
super.onBackPressed();
}
private void setFullScreen()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
getWindow().setDecorFitsSystemWindows(false);
WindowInsetsController controller = getWindow().getInsetsController();
if(controller != null) {
controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
}
}
else {
// for older versions
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
}
}
Well, it works now. The navigation bar is semi-transparent now.

However, when closing and resuming the app the fullscreen mode is gone again:


Keep Fullscreen After Resume
Luckily, there exists a class function onResume
. Calling setFullScreen
again after resume resolves this problem as well.
@Override
public void onResume()
{
super.onResume();
setFullScreen();
}
The final source code for the main activity:
package com.bla.webviewfullscreen;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
// define variable without constructing it
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// hides the app's title
requestWindowFeature(Window.FEATURE_NO_TITLE);
// hides the app's title bar
getSupportActionBar().hide();
// set main activity
setContentView(R.layout.activity_main);
// constructs WebView (linked to the element in the layout)
webView = findViewById(R.id.web);
// set default url
webView.loadUrl("https://archive-beta.ics.uci.edu/");
// with JavaScript & zoom enabled
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSupportZoom(true);
// allow to use it as a web browser (aka opening links)
// (otherwise following any other url results in opening
// the default browser)
webView.setWebViewClient(new WebViewClient());
// set immersive (fullscreen) mode
setFullScreen();
}
// some basic navigation functionality ;)
@Override
public void onBackPressed()
{
if(webView!= null && webView.canGoBack())
// go to previous page if such a page exists in the history
webView.goBack();
else
// close app otherwise aka follow system-wide default for back button
super.onBackPressed();
}
private void setFullScreen()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
getWindow().setDecorFitsSystemWindows(false);
WindowInsetsController controller = getWindow().getInsetsController();
if(controller != null) {
controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
}
}
else {
// for older versions
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
}
@Override
public void onResume()
{
super.onResume();
setFullScreen();
}
}