1

I'm developing an app for a client that wants to use a tablet as a display of interactive ads and games. The tablet will be placed in a holder that will avoid the use of any physical button.

I'm trying to get the app to run fullscreen, and upon swiping from the top I'd like the app to remain fullscreen. But for a moment the status bar appears and so do the buttons.

The code of my activity:

public class OrderActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_order);
        hideSystemUi();
        getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(
                new OnSystemUiVisibilityChangeListener() {
                    @Override
                    public void onSystemUiVisibilityChange(int visibility) {

                        if (visibility == 0) {
                            hideSystemUi();
                        }
                    }
                });
    }

    private void hideSystemUi() {

        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);

    }


}

PD: I know that this behaviour is frowned upon in app from the marketplace, but it's what's required and "correct" in this specific case.

Javier
  • 647
  • 1
  • 7
  • 30
  • It's more that what you want is specifically blocked, at least prior to the "L" Developer Preview, where a true kiosk mode is available (if you have root access, at least). Build your own ROM mod that removes the navigation and status bars. – CommonsWare Aug 08 '14 at 22:25
  • Is the device rooted? What API level are you using? – sarme Aug 08 '14 at 22:32
  • @sarme The device is ideally not rooted. It can be if it yields the best option. The target API isn't defined yet. (We're building the full project for the client, we'll provide the tablets) – Javier Aug 08 '14 at 22:33
  • Javier, have you made it? Because i am in same situation, where permanent full screen is needed – Martynas Nov 07 '14 at 16:22

3 Answers3

3

You can get rid of the buttons at the bottom, assuming the device is rooted, by running the following commands in a terminal shell:

setprop qemu.hw.mainkeys 1
killall surfaceflinger

You can run this programatically in Android with something like:

try {
    Process process = Runtime.getRuntime().exec("getprop qemu.hw.mainkeys");
    BufferedReader prop = new BufferedReader(new InputStreamReader(process.getInputStream()));

    if (prop == null || !prop.trim().equals("1")) {
        Runtime.getRuntime().exec("setprop qemu.hw.mainkeys 1");
        Runtime.getRuntime().exec("killall surfaceflinger");
    }
} catch (Exception e) {
    e.printStackTrace();
}

This SO answer talks about doing it in the build.prop, but I couldn't get that to work for me. Plus, doing it programmatically, I can turn it back on when the user exits the application.

Updated with notification bar

For the notification bar at the top, the best I've been able to do is to stop it from expanding. It still pops-up, but the user can't do much with it.

This is actually a slight variation on another answer I found here: link.

public static class customViewGroup extends ViewGroup {
    public customViewGroup(Context context) {
        super(context);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.v("customViewGroup", "********** Intercepted");
        return true;
    }
}

// https://stackoverflow.com/questions/25284233/prevent-status-bar-for-appearing-android-modified
public static void interceptNotificationBarSwipe(Context c) {
    WindowManager manager = ((WindowManager) c.getApplicationContext().getSystemService(Context.WINDOW_SERVICE));

    WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
    localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
    localLayoutParams.gravity = Gravity.TOP;
    localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |

    // this is to enable the notification to recieve touch events
    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |

            // Draws over status bar
    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

    localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
    localLayoutParams.height = (int) (50 * c.getResources().getDisplayMetrics().scaledDensity);
    localLayoutParams.format = PixelFormat.TRANSPARENT;

    customViewGroup view = new customViewGroup(c);

    manager.addView(view, localLayoutParams);
}

You'll have to add this to your AndroidManifest.xml too:

<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> 

I've only ever used this in Jelly Bean 4.2 (API 17) and higher. Not sure if it works before that.

Hope that helps.

As noted in other responses, this gets easier in L and can also be done with a custom ROM. My goal was a programmatic solution that worked in KitKat

Community
  • 1
  • 1
sarme
  • 1,337
  • 12
  • 19
  • Do you know how to get rid of the status bar? That would complete the answer – Javier Aug 15 '14 at 22:48
  • Could you explain why the `killall surfaceflinger` is needed? – Matt Oct 22 '18 at 17:24
  • @MattD `killall surfaceflinger` was to force surfaceflinger to restart and load the propery change. Otherwise, it just keeps using whatever qemu.hw.mainkeys was when it started. Surfaceflinger is the UI compositor that glues all the UI pieces together and sends them to the display. – sarme Oct 23 '18 at 15:27
2

you can customize your theme in style xml file:

style name="fullscreen_theme" parent="Theme.AppCompat.Light">
<item name="android:windowFullscreen">true</item>
</style>
arsenal
  • 199
  • 1
  • 1
  • 13
  • If the user drags down the top of the screen, he'll be able to see the status bar and buttons. – Javier Aug 09 '14 at 00:18
  • 1
    I implemented your solution and upon dragging from the top of the screen the status bar and buttons show – Javier Aug 09 '14 at 00:30
1

In the android manifest inside the application tag, add this line :

android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen"
  • Same as answer above. If the user drags down the top of the screen, he'll see the status bar and buttons – Javier Aug 09 '14 at 02:21
  • I think it is like this by design, the buttons return when you touch the screen because otherwise there will be no way for the user to exit the app, the only other thing i could think about is to replace the hide navigation flag with View.SYSTEM_UI_FLAG_LOW_PROFILE, not sure why the status bar keeps coming back though because adding the theme in the manifest always works for me –  Aug 09 '14 at 02:43