Android源码(6.0和8.1) 屏蔽状态栏下拉和屏蔽导航栏显示

您所在的位置:网站首页 禁止状态栏下拉 Android源码(6.0和8.1) 屏蔽状态栏下拉和屏蔽导航栏显示

Android源码(6.0和8.1) 屏蔽状态栏下拉和屏蔽导航栏显示

2024-07-12 13:56| 来源: 网络整理| 查看: 265

第一种方法是直接禁止,第二种方法是动态禁止

(一)网上关于屏蔽状态栏的文章搜到不少,但都是针对某个应用,或者锁屏状态,才能屏蔽状态栏的下拉,而我的需求是不管任意状态都屏蔽状态栏下拉,百度到的也可能版本不一样,说的一些文件都找不到,搜到一篇文章,自己修改了一个方法,然后OK了,具体如下:

文件位置:frameworks\base\core\java\android\app\StatusBarManager.java 

修改此方法中的参数,不用传穿进去的参数

 

public void disable(int what) { try { mService.disable(DISABLE_EXPAND, mToken, mContext.getPackageName()); } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } }

参考文章:http://www.xuebuyuan.com/1608099.html

 

1.做锁屏软件,锁屏软件具体界面的实现不说,在屏蔽通知栏下拉的时候就出现问题了。网上找了一些资料,可以通过statusbarmanager这个类来实现,由于这个类是系统隐藏的,所以我们很容易就想到使用反射,这个类的源码如下:

 

package android.app; import android.content.Context; import android.os.Binder; import android.os.RemoteException; import android.os.IBinder; import android.os.ServiceManager; public class StatusBarManager { public static final int DISABLE_EXPAND = 0x00000001; public static final int DISABLE_NOTIFICATION_ICONS = 0x00000002; public static final int DISABLE_NOTIFICATION_ALERTS = 0x00000004; public static final int DISABLE_NOTIFICATION_TICKER = 0x00000008; public static final int DISABLE_NONE = 0x00000000; private Context mContext; private IStatusBar mService; private IBinder mToken = new Binder(); StatusBarManager(Context context) { mContext = context; mService = IStatusBar.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); } public void disable(int what) { try { mService.disable(what, mToken, mContext.getPackageName()); } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } public void expand() { try { mService.activate(); } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } public void collapse() { try { mService.deactivate(); } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } public void toggle() { try { mService.toggle(); } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } public IBinder addIcon(String slot, int iconId, int iconLevel) { try { return mService.addIcon(slot, mContext.getPackageName(), iconId, iconLevel); } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } public void updateIcon(IBinder key, String slot, int iconId, int iconLevel) { try { mService.updateIcon(key, slot, mContext.getPackageName(), iconId, iconLevel); } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } public void removeIcon(IBinder key) { try { mService.removeIcon(key); } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } }

 

 

2.如果是系统级应用,也就是手机厂家植入的应用,可以使用disable(int)的方法来进行屏蔽,参数如上源码五个参数之一即可。但是如果是在应用层上的,disable方法因为权限问题无法使用(如果一定要使用必须具有系统签名)。这个时候可以使用collapse()方法,现在的小米锁屏和360锁屏都是使用该方法,具体代码如下:

 

@Override public void onWindowFocusChanged(boolean hasFocus) { disableStatusBar(); super.onWindowFocusChanged(hasFocus); } public void disableStatusBar(){ try { Object service = getSystemService("statusbar"); Class claz = Class.forName("android.app.StatusBarManager"); Method expand = claz.getMethod("collapse"); expand.invoke(service); } catch (Exception e) { e.printStackTrace(); } }

3.重写activity的onWindowfocuschanged方法,执行如上操作即可。以上方法使用了反射,如果不想使用使用反射获得隐藏的StatusBarManager,我这里提供一个jar包,将jar包导入到项目中,即可直接使用StatusBarManager ,还可以直接使用ServiceManager这个隐藏类,它有什么用?相信做过自动挂断电话的童鞋应该了解。

jar下载地址包:http://download.csdn.net/detail/welen123456789/5068165

(二)屏蔽状态栏下拉 6.0解决办法

源码位置 SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBarView.java

@Override public boolean onTouchEvent(MotionEvent event) { boolean barConsumedEvent = mBar.interceptTouchEvent(event); if (DEBUG_GESTURES) { if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { EventLog.writeEvent(EventLogTags.SYSUI_PANELBAR_TOUCH, event.getActionMasked(), (int) event.getX(), (int) event.getY(), barConsumedEvent ? 1 : 0); } } // return barConsumedEvent || super.onTouchEvent(event); return false; }

直接返回false,action_move不会执行,代码看似简单,实则super.onTouchEvent(event)调用的是PanelBar.java中的onTouchEvent()

8.1解决办法(同上) 6.0和8.1的状态栏代码是有差异的,但是通过上面的方法都能达到需求效果

6.0的PhoneStatusBarView调用onTouchEvent(),最终调用PanelBar的onTouchEvent()

8.1的PhoneStatusBarView调用onTouchEvent(),接着调用PanelBar的onTouchEvent(),最终调用PanelView的onTouchEvent()

从根本上阻止事件的传递来达到屏蔽下拉的效果

补充 如果需要动态的控制是否允许下拉状态栏,可以通过广播通知,接受传递的参数,持久化保存(可通过SharedPreference或者Settings.Global.xxxx)当前状态栏的状态,一般建议采用Settings.Global保存。

具体步骤 1.在frameworks\base\core\java\android\provider\Settings.java中Globel内部类下添加变量名称,比如OPEN_PANEL_ENABLED 2.通过make update-api指令重新编译,因为在Settings中修改后需要编译才能对应到这两文件frameworks/base/api/system-current.txt、frameworks/base/api/current.txt 3.在广播接收的地方通过Settings.Global.putInt(context.getContentResolver(), Settings.Global.OPEN_PANEL_ENABLED, 1) 保存值 (ps 可通过adb命令 adb shell settings put global open_panel_enabled 1 模拟写入 adb shell settings get global open_panel_enabled 模拟查看) 4.将刚刚的return false改成

boolean flag=Settings.Global.getInt(getContext().getContentResolver(), Settings.Global.OPEN_PANEL_ENABLED,1)==1; return flag ? barConsumedEvent || super.onTouchEvent(event) : flag; 屏蔽导航栏显示 6.0解决办法

源码位置SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBar.java

@Override public void start() { mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); updateDisplaySize(); mScrimSrcModeEnabled = mContext.getResources().getBoolean( R.bool.config_status_bar_scrim_behind_use_src); super.start(); // calls createAndAddWindows() mMediaSessionManager = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE); // TODO: use MediaSessionManager.SessionListener to hook us up to future updates // in session state addNavigationBar(); ..... }

直接注释addNavigationBar()就能达到需求效果

8.1解决办法

源码位置SystemUI\src\com\android\systemui\statusbar\phone\StatusBar.java

protected void makeStatusBarView() { final Context context = mContext; updateDisplaySize(); // populates mDisplayMetrics updateResources(); updateTheme(); .... try { boolean showNav = mWindowManagerService.hasNavigationBar(); if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav); if (showNav) { createNavigationBar(); } } catch (RemoteException ex) { // no window manager? good luck with that } .... }

 

直接注释createNavigationBar()或者将showNav=false就能达到需求效果

 

代码流程分析 6.0和8.1的导航栏都是通过WindowManager的addView来添加的,通过WindowManager的removeViewImmediate来移除

1、6.0的addNavigationBar实现,通过addView将mNavigationBarView添加,prepareNavigationBarView方法设置了点击、触摸、长按事件,无需关心

private void addNavigationBar() { if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView); if (mNavigationBarView == null) return; prepareNavigationBarView(); mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams()); mNavigationShown=true; } 查找到在makeStatusBarView()中,mNavigationBarView初始化,加载navigation_bar布局文件 protected PhoneStatusBarView makeStatusBarView() { final Context context = mContext; Resources res = context.getResources(); updateDisplaySize(); // populates mDisplayMetrics updateResources(); ... mNavigationBarView = (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null); mNavigationBarView.setDisabledFlags(mDisabled1); mNavigationBarView.setBar(this); mNavigationBarView.setOnVerticalChangedListener( new NavigationBarView.OnVerticalChangedListener() { @Override public void onVerticalChanged(boolean isVertical) { if (mAssistManager != null) { mAssistManager.onConfigurationChanged(); } mNotificationPanel.setQsScrimEnabled(!isVertical); } }); mNavigationBarView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { checkUserAutohide(v, event); return false; }}); }

2、8.1的createNavigationBar实现,发现是通过NavigationBarFragment来实例化mNavigationBarView

protected void createNavigationBar() { mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> { mNavigationBar = (NavigationBarFragment) fragment; if (mLightBarController != null) { mNavigationBar.setLightBarController(mLightBarController); } mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility); }); }

NavigationBarFragment的crate方法通过addView将mNavigationBarView添加,加载navigation_bar_window布局

public static View create(Context context, FragmentListener listener) { WindowManager.LayoutParams lp = new WindowManager.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR, WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH | WindowManager.LayoutParams.FLAG_SLIPPERY, PixelFormat.TRANSLUCENT); lp.token = new Binder(); lp.setTitle("NavigationBar"); lp.windowAnimations = 0; View navigationBarView = LayoutInflater.from(context).inflate( R.layout.navigation_bar_window, null); if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView); if (navigationBarView == null) return null; context.getSystemService(WindowManager.class).addView(navigationBarView, lp); FragmentHostManager fragmentHost = FragmentHostManager.get(navigationBarView); NavigationBarFragment fragment = new NavigationBarFragment(); fragmentHost.getFragmentManager().beginTransaction() .replace(R.id.navigation_bar_frame, fragment, TAG) .commit(); fragmentHost.addTagListener(TAG, listener); return navigationBarView; } 补充

依旧是通过广播来动态控制导航栏的显示和隐藏

6.0已在开头文章中写过,这里就只补充8.1的显示和隐藏

源码位置SystemUI\src\com\android\systemui\statusbar\phone\StatusBar.java

private static final String SHOW_NAVIGATION = "cc.intent.systemui.shownavigation"; private static final String HIDE_NAVIGATION = "cc.intent.systemui.hidenavigation"; private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.e(TAG, "onReceive: " + intent); String action = intent.getAction(); if (HIDE_NAVIGATION.equals(action)) { if (mNavigationBarView == null) return; mWindowManager.removeViewImmediate(mNavigationBarView); mNavigationBarView = null; }else if (SHOW_NAVIGATION.equals(action)) { if (mNavigationBarView != null) return; createNavigationBar(); } } };

原文地址:https://blog.csdn.net/u012932409/article/details/89156391



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3