限制通知栏拉动

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

    }

我的目标是创建一个 Kiosk 应用程序。我检查了很多代码,比如 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。但它在我的带有 Android Pie 的 Redmi Note 5 Pro 中不起作用。有没有其他方法可以做到这一点?

如果您的信息亭应用程序是设备所有者(如您引用的示例之一所述),您可以使用 DevicePolicyManager.setStatusBarDisabled() :

Disabling the status bar blocks notifications, quick settings and other screen overlays that allow escaping from a single use device.

从 Android 6 (API 23) 开始可用,状态栏仍然显示(包括时间、wifi 级别、蓝牙指示器...)但通知不显示而且你无法展开它。

在此解决方案中,通知栏并未完全被阻止,但会在用户打开后关闭。您需要一个检查通知栏是否重复打开的服务。此服务使用反射来获取打开通知栏后关闭通知栏所需的方法,因此我认为它无法在 android 9 台设备上运行(刚刚检查过它在 7.1.1 设备上与 compilesdk 28 一起工作正常)。您需要使用此权限:

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

这是服务代码:

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

    }

}

弱引用是为了排除内存泄漏发生的可能性。