├── .gitignore ├── LICENSE ├── README.md ├── example ├── README.md ├── config.xml ├── hooks │ └── README.md └── www │ └── index.html ├── package.json ├── plugin.xml ├── src └── android │ └── com │ └── mesmotronic │ └── plugins │ └── FullScreenPlugin.java └── www └── AndroidFullScreen.js /.gitignore: -------------------------------------------------------------------------------- 1 | /example/platforms 2 | /example/plugins 3 | /src/.settings 4 | /src/bin 5 | /src/.classpath 6 | /src/.project 7 | package-lock.json 8 | node_modules 9 | .gradle -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Mesmotronic Limited 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Full Screen Plugin for Cordova 2 | ============================== 3 | 4 | Plugin for Cordova (or PhoneGap) 3.0+ to enable true full screen on Android devices using lean and immersive modes, ported from our popular [ANE for Adobe AIR](https://github.com/mesmotronic/air-ane-fullscreen). 5 | 6 | Released under BSD license; see LICENSE for details. 7 | 8 | How does it work? 9 | ----------------- 10 | 11 | This plugin enables developers to offer users a true full screen experience in their Cordova and PhoneGap apps for Android. 12 | 13 | Using Android 4.0+, you can use true full screen in "lean mode", the way you see in apps like YouTube, expanding the app right to the edges of the screen, hiding the status and navigation bars until the user next interacts. This is ideally suited to video or cut-scene content. 14 | 15 | In Android 4.4+, however, you can now enter true full screen, fully interactive immersive mode. In this mode, your app will remain in true full screen until you choose otherwise; users can swipe down from the top of the screen to temporarily display the system UI. 16 | 17 | If you find that the plugin doesn't work as you might like on a specific device or Android configuration you're using, don't forget that this project is open source, so feel free to fork the project and adapt it to work in any way you like! 18 | 19 | Installation 20 | ------------ 21 | 22 | **Cordova** 23 | 24 | `cordova plugin add cordova-plugin-fullscreen` 25 | 26 | **PhoneGap** 27 | 28 | `phonegap local plugin add cordova-plugin-fullscreen` 29 | 30 | Notes 31 | ----- 32 | 33 | From version 1.0.2, the plugin ID has changed to `cordova-plugin-fullscreen` in line with the official Cordova plugin naming coventions following the switch to NPM. We therefore recommend that any previous version be uninstalled before upgrading to this release. 34 | 35 | Since the release of `android@5.0.0`, setting `` in `config.xml` will use immersive mode, where available, even without this plugin. 36 | 37 | Code example 38 | ------------ 39 | 40 | Using the plugin in your app couldn't be easier: 41 | 42 | ```js 43 | function successFunction() 44 | { 45 | console.info("It worked!"); 46 | } 47 | 48 | function errorFunction(error) 49 | { 50 | console.error(error); 51 | } 52 | 53 | function trace(value) 54 | { 55 | console.log(value); 56 | } 57 | 58 | // Is this plugin supported? 59 | AndroidFullScreen.isSupported(successFunction, errorFunction); 60 | 61 | // Is immersive mode supported? 62 | AndroidFullScreen.isImmersiveModeSupported(successFunction, errorFunction); 63 | 64 | // The width of the screen in immersive mode 65 | AndroidFullScreen.immersiveWidth(trace, errorFunction); 66 | 67 | // The height of the screen in immersive mode 68 | AndroidFullScreen.immersiveHeight(trace, errorFunction); 69 | 70 | // Hide system UI until user interacts 71 | AndroidFullScreen.leanMode(successFunction, errorFunction); 72 | 73 | // Show system UI 74 | AndroidFullScreen.showSystemUI(successFunction, errorFunction); 75 | 76 | // Extend your app underneath the status bar (Android 4.4+ only) 77 | AndroidFullScreen.showUnderStatusBar(successFunction, errorFunction); 78 | 79 | // Extend your app underneath the system UI (Android 4.4+ only) 80 | AndroidFullScreen.showUnderSystemUI(successFunction, errorFunction); 81 | 82 | // Hide system UI and keep it hidden (Android 4.4+ only) 83 | AndroidFullScreen.immersiveMode(successFunction, errorFunction); 84 | 85 | // Custom full screen mode 86 | // See https://developer.android.com/reference/android/view/View.html#setSystemUiVisibility(int) 87 | AndroidFullScreen.setSystemUiVisibility(AndroidFullScreen.SYSTEM_UI_FLAG_FULLSCREEN | AndroidFullScreen.SYSTEM_UI_FLAG_LOW_PROFILE, successFunction, errorFunction); 88 | ``` 89 | 90 | All methods will call the successFunction callback if the action was successful and the errorFunction if it wasn't (or isn't supported); if you're using the plugin in an app for a platform other than Android, all methods will fail. 91 | 92 | The `immersiveWidth` and `immersiveHeight` properties return the screen width and height available in immersive mode (or with the system UI hidden), where supported. 93 | 94 | Getting the immersive screen size 95 | --------------------------------- 96 | 97 | You can use the `immersiveWidth` and `immersiveHeight` methods to find out the dimensions of the screen with the system UI hidden, regardless of the current screen state. 98 | 99 | Make a donation 100 | --------------- 101 | 102 | If you find this project useful, why not buy us a coffee (or as many as you think it's worth)? 103 | 104 | [![Make a donation](https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif)](http://bit.ly/2W0K8iE) 105 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | You need to add the Android platform and install the plugin before running the example: 2 | 3 | ``` 4 | cordova platform add android 5 | cordova plugin add https://github.com/mesmotronic/cordova-plugin-fullscreen.git 6 | cordova run android 7 | ``` 8 | -------------------------------------------------------------------------------- /example/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Cordova Full Screen Test 4 | 5 | A sample Apache Cordova application that responds to the deviceready event. 6 | 7 | 8 | Apache Cordova Team 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/hooks/README.md: -------------------------------------------------------------------------------- 1 | 21 | # Cordova Hooks 22 | 23 | This directory may contain scripts used to customize cordova commands. This 24 | directory used to exist at `.cordova/hooks`, but has now been moved to the 25 | project root. Any scripts you add to these directories will be executed before 26 | and after the commands corresponding to the directory name. Useful for 27 | integrating your own build systems or integrating with version control systems. 28 | 29 | __Remember__: Make your scripts executable. 30 | 31 | ## Hook Directories 32 | The following subdirectories will be used for hooks: 33 | 34 | after_build/ 35 | after_compile/ 36 | after_docs/ 37 | after_emulate/ 38 | after_platform_add/ 39 | after_platform_rm/ 40 | after_platform_ls/ 41 | after_plugin_add/ 42 | after_plugin_ls/ 43 | after_plugin_rm/ 44 | after_plugin_search/ 45 | after_prepare/ 46 | after_run/ 47 | after_serve/ 48 | before_build/ 49 | before_compile/ 50 | before_docs/ 51 | before_emulate/ 52 | before_platform_add/ 53 | before_platform_rm/ 54 | before_platform_ls/ 55 | before_plugin_add/ 56 | before_plugin_ls/ 57 | before_plugin_rm/ 58 | before_plugin_search/ 59 | before_prepare/ 60 | before_run/ 61 | before_serve/ 62 | pre_package/ <-- Windows 8 and Windows Phone only. 63 | 64 | ## Script Interface 65 | 66 | All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables: 67 | 68 | * CORDOVA_VERSION - The version of the Cordova-CLI. 69 | * CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios). 70 | * CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer) 71 | * CORDOVA_HOOK - Path to the hook that is being executed. 72 | * CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate) 73 | 74 | If a script returns a non-zero exit code, then the parent cordova command will be aborted. 75 | 76 | 77 | ## Writing hooks 78 | 79 | We highly recommend writting your hooks using Node.js so that they are 80 | cross-platform. Some good examples are shown here: 81 | 82 | [http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/) 83 | 84 | -------------------------------------------------------------------------------- /example/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Full Screen Example 8 | 9 | 32 | 33 | 34 | 35 | 36 | 37 |

Android 4.0+

38 | 39 | 40 | 41 | 42 | 43 |

Android 4.4+

44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-fullscreen", 3 | "version": "1.3.0", 4 | "description": "Plugin for Cordova (or PhoneGap) 3.0+ to enable true full screen on Android devices using lean and immersive modes", 5 | "cordova": { 6 | "id": "cordova-plugin-fullscreen", 7 | "platforms": [ 8 | "android" 9 | ] 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/mesmotronic/cordova-fullscreen-plugin.git" 14 | }, 15 | "keywords": [ 16 | "cordova", 17 | "android", 18 | "fullscreen", 19 | "lean", 20 | "immersive", 21 | "ecosystem:cordova", 22 | "cordova-android" 23 | ], 24 | "engines": [ 25 | { 26 | "name": "cordova", 27 | "version": ">=3.0.0" 28 | } 29 | ], 30 | "author": "Neil Rackett", 31 | "license": "BSD", 32 | "bugs": { 33 | "url": "https://github.com/mesmotronic/cordova-fullscreen-plugin/issues" 34 | }, 35 | "homepage": "https://github.com/mesmotronic/cordova-fullscreen-plugin#readme" 36 | } 37 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 32 | 33 | 39 | 40 | cordova-plugin-fullscreen 41 | Plugin for Cordova (or PhoneGap) 3.0+ to enable true full screen on Android devices using lean and immersive modes 42 | cordova,android,fullscreen,lean,immersive,statusbar 43 | https://github.com/mesmotronic/cordova-fullscreen-plugin.git 44 | 45 | BSD 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /src/android/com/mesmotronic/plugins/FullScreenPlugin.java: -------------------------------------------------------------------------------- 1 | package com.mesmotronic.plugins; 2 | 3 | import org.apache.cordova.CallbackContext; 4 | import org.apache.cordova.CordovaPlugin; 5 | import org.apache.cordova.PluginResult; 6 | import org.apache.cordova.CordovaInterface; 7 | import org.apache.cordova.CordovaWebView; 8 | import org.json.JSONArray; 9 | import org.json.JSONException; 10 | 11 | import android.app.Activity; 12 | import android.graphics.Point; 13 | import android.os.Build; 14 | import android.view.View; 15 | import android.view.Window; 16 | import android.view.WindowManager; 17 | import android.graphics.Color; 18 | import android.os.Handler; 19 | 20 | public class FullScreenPlugin extends CordovaPlugin 21 | { 22 | public static final String ACTION_IS_SUPPORTED = "isSupported"; 23 | public static final String ACTION_IS_IMMERSIVE_MODE_SUPPORTED = "isImmersiveModeSupported"; 24 | public static final String ACTION_IMMERSIVE_WIDTH = "immersiveWidth"; 25 | public static final String ACTION_IMMERSIVE_HEIGHT = "immersiveHeight"; 26 | public static final String ACTION_LEAN_MODE = "leanMode"; 27 | public static final String ACTION_SHOW_SYSTEM_UI = "showSystemUI"; 28 | public static final String ACTION_SHOW_UNDER_STATUS_BAR = "showUnderStatusBar"; 29 | public static final String ACTION_SHOW_UNDER_SYSTEM_UI = "showUnderSystemUI"; 30 | public static final String ACTION_IMMERSIVE_MODE = "immersiveMode"; 31 | public static final String ACTION_SET_SYSTEM_UI_VISIBILITY = "setSystemUiVisibility"; 32 | public static final String ACTION_RESET_WINDOW = "resetScreen"; 33 | 34 | private CallbackContext context; 35 | private Activity activity; 36 | private Window window; 37 | private View decorView; 38 | private int mLastSystemUIVisibility = 0; 39 | private final Handler mLeanBackHandler = new Handler(); 40 | private final Runnable mEnterLeanback = new Runnable() { 41 | @Override 42 | public void run() { 43 | leanMode(); 44 | } 45 | }; 46 | 47 | /** 48 | * Sets the context of the Command. This can then be used to do things like 49 | * get file paths associated with the Activity. 50 | * 51 | * @param cordova The context of the main Activity. 52 | * @param webView The CordovaWebView Cordova is running in. 53 | */ 54 | @Override 55 | public void initialize(final CordovaInterface cordova, final CordovaWebView webView) { 56 | super.initialize(cordova, webView); 57 | 58 | this.cordova.getActivity().runOnUiThread(new Runnable() { 59 | @Override 60 | public void run() { 61 | // Clear flag FLAG_FORCE_NOT_FULLSCREEN which is set initially 62 | // by the Cordova. 63 | Window window = cordova.getActivity().getWindow(); 64 | window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 65 | 66 | // Read 'StatusBarBackgroundColor' from config.xml, default is #000000. 67 | setStatusBarBackgroundColor(preferences.getString("StatusBarBackgroundColor", "#000000")); 68 | } 69 | }); 70 | } 71 | 72 | @Override 73 | public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException 74 | { 75 | context = callbackContext; 76 | activity = cordova.getActivity(); 77 | window = activity.getWindow(); 78 | decorView = window.getDecorView(); 79 | 80 | if (ACTION_IS_SUPPORTED.equals(action)) 81 | return isSupported(); 82 | else if (ACTION_IS_IMMERSIVE_MODE_SUPPORTED.equals(action)) 83 | return isImmersiveModeSupported(); 84 | else if (ACTION_IMMERSIVE_WIDTH.equals(action)) 85 | return immersiveWidth(); 86 | else if (ACTION_IMMERSIVE_HEIGHT.equals(action)) 87 | return immersiveHeight(); 88 | else if (ACTION_LEAN_MODE.equals(action)) 89 | return leanMode(); 90 | else if (ACTION_SHOW_SYSTEM_UI.equals(action)) 91 | return showSystemUI(); 92 | else if (ACTION_SHOW_UNDER_STATUS_BAR.equals(action)) 93 | return showUnderStatusBar(); 94 | else if (ACTION_SHOW_UNDER_SYSTEM_UI.equals(action)) 95 | return showUnderSystemUI(); 96 | else if (ACTION_IMMERSIVE_MODE.equals(action)) 97 | return immersiveMode(); 98 | else if (ACTION_SET_SYSTEM_UI_VISIBILITY.equals(action)) 99 | return setSystemUiVisibility(args.getInt(0)); 100 | else if (ACTION_RESET_WINDOW.equals(action)) 101 | return resetScreen(); 102 | 103 | return false; 104 | } 105 | 106 | protected void resetWindow() 107 | { 108 | decorView.setOnFocusChangeListener(null); 109 | decorView.setOnSystemUiVisibilityChangeListener(null); 110 | 111 | window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 112 | } 113 | 114 | /** 115 | * Are any of the features of this plugin supported? 116 | */ 117 | protected boolean isSupported() 118 | { 119 | boolean supported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH; 120 | 121 | PluginResult res = new PluginResult(PluginResult.Status.OK, supported); 122 | context.sendPluginResult(res); 123 | return supported; 124 | } 125 | 126 | /** 127 | * Is immersive mode supported? 128 | */ 129 | protected boolean isImmersiveModeSupported() 130 | { 131 | boolean supported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; 132 | 133 | PluginResult res = new PluginResult(PluginResult.Status.OK, supported); 134 | context.sendPluginResult(res); 135 | return supported; 136 | } 137 | 138 | /** 139 | * The width of the screen in immersive mode 140 | */ 141 | protected boolean immersiveWidth() 142 | { 143 | activity.runOnUiThread(new Runnable() 144 | { 145 | @Override 146 | public void run() 147 | { 148 | try 149 | { 150 | Point outSize = new Point(); 151 | 152 | decorView.getDisplay().getRealSize(outSize); 153 | 154 | PluginResult res = new PluginResult(PluginResult.Status.OK, outSize.x); 155 | context.sendPluginResult(res); 156 | } 157 | catch (Exception e) 158 | { 159 | context.error(e.getMessage()); 160 | } 161 | } 162 | }); 163 | 164 | return true; 165 | } 166 | 167 | /** 168 | * The height of the screen in immersive mode 169 | */ 170 | protected boolean immersiveHeight() 171 | { 172 | activity.runOnUiThread(new Runnable() 173 | { 174 | @Override 175 | public void run() 176 | { 177 | try 178 | { 179 | Point outSize = new Point(); 180 | 181 | decorView.getDisplay().getRealSize(outSize); 182 | 183 | PluginResult res = new PluginResult(PluginResult.Status.OK, outSize.y); 184 | context.sendPluginResult(res); 185 | } 186 | catch (Exception e) 187 | { 188 | context.error(e.getMessage()); 189 | } 190 | } 191 | }); 192 | 193 | return true; 194 | } 195 | 196 | /** 197 | * Hide system UI until user interacts 198 | */ 199 | protected boolean leanMode() 200 | { 201 | if (!isSupported()) 202 | { 203 | context.error("Not supported"); 204 | return false; 205 | } 206 | 207 | activity.runOnUiThread(new Runnable() 208 | { 209 | @Override 210 | public void run() 211 | { 212 | try 213 | { 214 | resetWindow(); 215 | 216 | int uiOptions = 217 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 218 | | View.SYSTEM_UI_FLAG_FULLSCREEN 219 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 220 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 221 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; 222 | 223 | mLastSystemUIVisibility = uiOptions; 224 | decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() 225 | { 226 | @Override 227 | public void onSystemUiVisibilityChange(int visibility) 228 | { 229 | if((mLastSystemUIVisibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 230 | && (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { 231 | resetHideTimer(); 232 | } 233 | mLastSystemUIVisibility = visibility; 234 | } 235 | }); 236 | 237 | decorView.setSystemUiVisibility(uiOptions); 238 | 239 | context.success(); 240 | } 241 | catch (Exception e) 242 | { 243 | context.error(e.getMessage()); 244 | } 245 | } 246 | }); 247 | 248 | return true; 249 | } 250 | 251 | private void resetHideTimer() { 252 | // First cancel any queued events - i.e. resetting the countdown clock 253 | mLeanBackHandler.removeCallbacks(mEnterLeanback); 254 | // And fire the event in 3s time 255 | mLeanBackHandler.postDelayed(mEnterLeanback, 3000); 256 | } 257 | 258 | /** 259 | * Show system UI 260 | */ 261 | protected boolean showSystemUI() 262 | { 263 | if (!isSupported()) 264 | { 265 | context.error("Not supported"); 266 | return false; 267 | } 268 | 269 | activity.runOnUiThread(new Runnable() 270 | { 271 | @Override 272 | public void run() 273 | { 274 | try 275 | { 276 | resetWindow(); 277 | 278 | // Remove translucent theme from bars 279 | 280 | window.clearFlags 281 | ( 282 | WindowManager.LayoutParams.FLAG_FULLSCREEN 283 | | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION 284 | | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS 285 | ); 286 | 287 | // Update system UI 288 | 289 | decorView.setOnSystemUiVisibilityChangeListener(null); 290 | decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); 291 | 292 | PluginResult res = new PluginResult(PluginResult.Status.OK, true); 293 | context.sendPluginResult(res); 294 | 295 | context.success(); 296 | } 297 | catch (Exception e) 298 | { 299 | context.error(e.getMessage()); 300 | } 301 | } 302 | }); 303 | 304 | return true; 305 | } 306 | 307 | /** 308 | * Extend your app underneath the status bar (Android 4.4+ only) 309 | */ 310 | protected boolean showUnderStatusBar() 311 | { 312 | if (!isImmersiveModeSupported()) 313 | { 314 | context.error("Not supported"); 315 | return false; 316 | } 317 | 318 | activity.runOnUiThread(new Runnable() 319 | { 320 | @Override 321 | public void run() 322 | { 323 | try 324 | { 325 | resetWindow(); 326 | 327 | // Make the status bar translucent 328 | 329 | window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 330 | 331 | // Extend view underneath status bar 332 | 333 | int uiOptions = 334 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE 335 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 336 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 337 | 338 | decorView.setSystemUiVisibility(uiOptions); 339 | 340 | context.success(); 341 | } 342 | catch (Exception e) 343 | { 344 | context.error(e.getMessage()); 345 | } 346 | } 347 | }); 348 | 349 | return true; 350 | } 351 | 352 | /** 353 | * Undo the effect of any of the other methods of this plugin 354 | */ 355 | protected boolean resetScreen() 356 | { 357 | activity.runOnUiThread(new Runnable() 358 | { 359 | @Override 360 | public void run() 361 | { 362 | try 363 | { 364 | decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); 365 | context.success(); 366 | } 367 | catch (Exception e) 368 | { 369 | context.error(e.getMessage()); 370 | } 371 | } 372 | }); 373 | 374 | return true; 375 | } 376 | 377 | /** 378 | * Extend your app underneath the system UI (Android 4.4+ only) 379 | */ 380 | protected boolean showUnderSystemUI() 381 | { 382 | if (!isImmersiveModeSupported()) 383 | { 384 | context.error("Not supported"); 385 | return false; 386 | } 387 | 388 | activity.runOnUiThread(new Runnable() 389 | { 390 | @Override 391 | public void run() 392 | { 393 | try 394 | { 395 | resetWindow(); 396 | 397 | // Make the status and nav bars translucent 398 | 399 | window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 400 | window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 401 | 402 | // Extend view underneath status and nav bars 403 | 404 | int uiOptions = 405 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE 406 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 407 | 408 | decorView.setSystemUiVisibility(uiOptions); 409 | 410 | context.success(); 411 | } 412 | catch (Exception e) 413 | { 414 | context.error(e.getMessage()); 415 | } 416 | } 417 | }); 418 | 419 | return true; 420 | } 421 | 422 | /** 423 | * Hide system UI and switch to immersive mode (Android 4.4+ only) 424 | */ 425 | protected boolean immersiveMode() 426 | { 427 | if (!isImmersiveModeSupported()) 428 | { 429 | context.error("Not supported"); 430 | return false; 431 | } 432 | 433 | activity.runOnUiThread(new Runnable() 434 | { 435 | @Override 436 | public void run() 437 | { 438 | try 439 | { 440 | resetWindow(); 441 | 442 | final int uiOptions = 443 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE 444 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 445 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 446 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 447 | | View.SYSTEM_UI_FLAG_FULLSCREEN 448 | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 449 | 450 | window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 451 | decorView.setSystemUiVisibility(uiOptions); 452 | 453 | decorView.setOnFocusChangeListener(new View.OnFocusChangeListener() 454 | { 455 | @Override 456 | public void onFocusChange(View v, boolean hasFocus) 457 | { 458 | if (hasFocus) 459 | { 460 | decorView.setSystemUiVisibility(uiOptions); 461 | } 462 | } 463 | }); 464 | 465 | decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() 466 | { 467 | @Override 468 | public void onSystemUiVisibilityChange(int visibility) 469 | { 470 | decorView.setSystemUiVisibility(uiOptions); 471 | } 472 | }); 473 | 474 | context.success(); 475 | } 476 | catch (Exception e) 477 | { 478 | context.error(e.getMessage()); 479 | } 480 | } 481 | }); 482 | 483 | return true; 484 | } 485 | 486 | protected boolean setSystemUiVisibility(final int visibility) 487 | { 488 | if (!isSupported()) 489 | { 490 | context.error("Not supported"); 491 | return false; 492 | } 493 | 494 | activity.runOnUiThread(new Runnable() 495 | { 496 | @Override 497 | public void run() 498 | { 499 | try 500 | { 501 | resetWindow(); 502 | decorView.setSystemUiVisibility(visibility); 503 | context.success(); 504 | } 505 | catch (Exception e) 506 | { 507 | context.error(e.getMessage()); 508 | } 509 | } 510 | }); 511 | 512 | return true; 513 | } 514 | 515 | private void setStatusBarBackgroundColor(final String colorPref) { 516 | if (Build.VERSION.SDK_INT >= 21) { 517 | if (colorPref != null && !colorPref.isEmpty()) { 518 | final Window window = cordova.getActivity().getWindow(); 519 | // Method and constants not available on all SDKs but we want to be able to compile this code with any SDK 520 | window.clearFlags(0x04000000); // SDK 19: WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 521 | window.addFlags(0x80000000); // SDK 21: WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 522 | try { 523 | // Using reflection makes sure any 5.0+ device will work without having to compile with SDK level 21 524 | window.getClass().getDeclaredMethod("setStatusBarColor", int.class).invoke(window, Color.parseColor(colorPref)); 525 | } catch (IllegalArgumentException ignore) { 526 | } catch (Exception ignore) { 527 | } 528 | } 529 | } 530 | } 531 | 532 | } 533 | -------------------------------------------------------------------------------- /www/AndroidFullScreen.js: -------------------------------------------------------------------------------- 1 | (function(window, undefined) 2 | { 3 | 'use strict'; 4 | 5 | var AndroidFullScreen = 6 | { 7 | SYSTEM_UI_FLAG_FULLSCREEN: 4, 8 | SYSTEM_UI_FLAG_HIDE_NAVIGATION: 2, 9 | SYSTEM_UI_FLAG_IMMERSIVE: 2048, 10 | SYSTEM_UI_FLAG_IMMERSIVE_STICKY: 4096, 11 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN: 1024, 12 | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION: 512, 13 | SYSTEM_UI_FLAG_LAYOUT_STABLE: 256, 14 | SYSTEM_UI_FLAG_LIGHT_STATUS_BAR: 8192, 15 | SYSTEM_UI_FLAG_LOW_PROFILE: 1, 16 | SYSTEM_UI_FLAG_VISIBLE: 0, 17 | 18 | isSupported: function(successFunction, errorFunction) 19 | { 20 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'isSupported', []); 21 | }, 22 | 23 | resetScreen: function(successFunction, errorFunction) 24 | { 25 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'resetScreen', []); 26 | }, 27 | 28 | isImmersiveModeSupported: function(successFunction, errorFunction) 29 | { 30 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'isImmersiveModeSupported', []); 31 | }, 32 | 33 | immersiveWidth: function(successFunction, errorFunction) 34 | { 35 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'immersiveWidth', []); 36 | }, 37 | 38 | immersiveHeight: function(successFunction, errorFunction) 39 | { 40 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'immersiveHeight', []); 41 | }, 42 | 43 | leanMode: function(successFunction, errorFunction) 44 | { 45 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'leanMode', []); 46 | }, 47 | 48 | showSystemUI: function(successFunction, errorFunction) 49 | { 50 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'showSystemUI', []); 51 | }, 52 | 53 | showUnderStatusBar: function(successFunction, errorFunction) 54 | { 55 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'showUnderStatusBar', []); 56 | }, 57 | 58 | showUnderSystemUI: function(successFunction, errorFunction) 59 | { 60 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'showUnderSystemUI', []); 61 | }, 62 | 63 | immersiveMode: function(successFunction, errorFunction) 64 | { 65 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'immersiveMode', []); 66 | }, 67 | 68 | /** 69 | * @see https://developer.android.com/reference/android/view/View.html#setSystemUiVisibility(int) 70 | */ 71 | setSystemUiVisibility: function(visibility, successFunction, errorFunction) 72 | { 73 | cordova.exec(successFunction, errorFunction, 'AndroidFullScreen', 'setSystemUiVisibility', [visibility || 0]); 74 | } 75 | 76 | }; 77 | 78 | cordova.addConstructor(function() 79 | { 80 | window.AndroidFullScreen = AndroidFullScreen; 81 | return window.AndroidFullScreen; 82 | }); 83 | 84 | })(window); 85 | --------------------------------------------------------------------------------