Search code examples
androidandroid-9.0-piekiosk-mode

Restrict Notification Bar from pulling


@Override
    public void onWindowFocusChanged(boolean hasFocus){
        super.onWindowFocusChanged(hasFocus);
        try{
            if(!hasFocus && enableKioskMode){
                Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
                sendBroadcast(closeDialog);

                ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
                am.moveTaskToFront(getTaskId(), ActivityManager.MOVE_TASK_WITH_HOME);

                // sametime required to close opened notification area
                Timer timer = new Timer();
                timer.schedule(new TimerTask(){
                    public void run() {
                        Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
                        sendBroadcast(closeDialog);
                    }
                }, 500);

            }
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
private 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) {
            return true;
        }

    }
private void addBlockingViews() {

        try {
            WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));

            //For Bottom View
            WindowManager.LayoutParams bottomlocalLayoutParams = new WindowManager.LayoutParams();
            bottomlocalLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;

            bottomlocalLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
            bottomlocalLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
            bottomlocalLayoutParams.height = (int) (50 * getResources().getDisplayMetrics().scaledDensity);

            bottomlocalLayoutParams.format = PixelFormat.RGBX_8888;
            bottomlocalLayoutParams.gravity = Gravity.BOTTOM;

            bottomView = new CustomViewGroup(BaseActivity.this);
            ViewGroup.LayoutParams layoutParams1 = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 50);
            bottomView.setLayoutParams(layoutParams1);
            manager.addView(bottomView, bottomlocalLayoutParams);

            WindowManager.LayoutParams toplocalLayoutParams = new WindowManager.LayoutParams();
            toplocalLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;

            toplocalLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
            int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
            int result = 0;
            if (resId > 0) {
                result = getResources().getDimensionPixelSize(resId);
            } else {
                // Use Fallback size:
                result = 60; // 60px Fallback
            }
            //toplocalLayoutParams.height = result;
            toplocalLayoutParams.height = (int) (50 * getResources().getDisplayMetrics().scaledDensity);
            toplocalLayoutParams.gravity = Gravity.TOP;
            toplocalLayoutParams.format = PixelFormat.TRANSPARENT;
            topView = new CustomViewGroup(BaseActivity.this);
            ViewGroup.LayoutParams layoutParams2 = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    25);
            topView.setLayoutParams(layoutParams2);
            manager.addView(topView, toplocalLayoutParams);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

My aim is to create a Kiosk app. I checked many codes for that like this and this. With their help I have achieved navigation bar hiding. Now I want to block user from dragging the notification bar down just like Surelock does. I've tried the common answers given in SO posts like here. But it does not work in my Redmi Note 5 Pro with Android Pie. Is there any other way to accomplish this?


Solution

  • In this solution notification bar is not blocked entirely but it gets closed after user opens it. You need a service that checks if the notification bar is open repeatedly. This service uses reflection to get needed method to close the notification bar after it gets opened so I think it wont work on android 9 devices(just checked it working fine with compilesdk 28 on a 7.1.1 device). you need to use this permission:

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

    this is the code for the service:

    public class CollapseService extends Service {
        ScheduledExecutorService scheduler;
    
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
    
        @Override
        public void onCreate() {
            super.onCreate();
            MyRunnable runnable = new MyRunnable(this);
    
            scheduler = Executors.newScheduledThreadPool(1);
            scheduler.scheduleAtFixedRate
                    (runnable, 0, 100, TimeUnit.MILLISECONDS);
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
    
            return Service.START_STICKY;
        }
    
        private void collapseNow() {
            Object statusBarService = getSystemService("statusbar");
            Class<?> statusBarManager = null;
    
            try {
                statusBarManager = Class.forName("android.app.StatusBarManager");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            Method collapseStatusBar = null;
    
            try {
                collapseStatusBar = statusBarManager.getMethod("collapsePanels");
    
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
    
            collapseStatusBar.setAccessible(true);
    
            try {
                collapseStatusBar.invoke(statusBarService);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
    
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            scheduler.shutdown();
        }
    
        static class MyRunnable implements Runnable{
            CollapseService aService = null;
            MyRunnable(CollapseService service){
                WeakReference<CollapseService> weakReference = new WeakReference<>(service);
                aService = weakReference.get();
            }
    
            @Override
            public void run(){
                if(aService != null) {
                    aService.collapseNow();
                }
            }
    
        }
    
    }
    

    Weak reference is to remove the possibility of occurrence of memory leaks.