一种屏蔽系统下拉菜单的方式
2016-04-12 14:50
941 查看
一种屏蔽系统下拉菜单的方式
导语
Android操作系统下禁用通知栏下拉功能一般使用反射调用StatusBarManager类中函数实现,但该方式需应用具有系统权限。本文介绍的方式采用修改framework层,绕过系统权限检查的方式实现。一、禁用通知栏下拉功能
查看系统源码: /frameworks/base/core/java/android/app/StatusBarManager.java/** * Disable some features in the status bar. Pass the bitwise-or of the DISABLE_flags. * To re-enable everything, pass {@link #DISABLE_NONE}. */ public void disable(int what) { try { final IStatusBarService svc = getService(); if (svc != null) { svc.disable(what, mToken, mContext.getPackageName()); } } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } }
根据其中 disable 函数,采用反射方式禁用下拉菜单,源码如下:
public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000; public static final void disableStatusBar(Context ctx) { Object sbservice = ctx.getSystemService("statusbar"); try { Class<?> statusBarManager = Class .forName("android.app.StatusBarManager"); Method collapse; collapse = statusBarManager.getMethod("disable", int.class); collapse.invoke(sbservice, Integer.valueOf(STATUS_BAR_DISABLE_EXPAND)); } catch (Exception e) { e.printStackTrace(); } }
但是实际调用时会抛出异常信息,如下图所示:
异常显示必须配置 android.Manifest.permission.STATUS_BAR 权限,但必须系统应用才能配置该权限。怎样绕过系统权限的检测呢,下面将进行介绍。
二、怎样绕过 android.Manifest.permission.STATUS_BAR 权限检测
继续查看源码,查找 StatusBarManager.java 中 disable 实现方式发现 /frameworks/base/services/java/com/android/server/StatusBarManagerService.java 中有该函数的具体实现。
public void disable(int what, IBinder token, String pkg) { enforceStatusBar(); synchronized (mLock) { disableLocked(what, token, pkg); } }
查看 enforceStatusBar 源码发现该函数,对 android.Manifest.permission.STATUS_BAR 权限进行了检测。
private void enforceStatusBar() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR, "StatusBarManagerService"); }
那么我们只要修改 disable 函数,取消其中关于 enforceStatusBar 调用,直接调用 disableLocked 函数禁用下拉通知,即可绕过权限的检测了。
三、framewok层修改
此步需要用到的工具:baksmali、smali。下载地址
1、adb 连接入手机,将 /system/framework/services.jar 文件考出进行修改,此步骤需要 ROOT 权限。
2、使用 baksmali 对 serviec.jar 进行反编译。命令:java -jar baksmali.jar -o OUTDIR services.jar
3、在反编译生成的 smali 文件中找到 StatusBarManagerService.smali 进行修改。此步需要对smali文件格式有一定的了解,可参照网上相关教程这里不再详解。
.method public disable(ILandroid/os/IBinder;Ljava/lang/String;)V .registers 6 .param p1, "what" # I .param p2, "token" # Landroid/os/IBinder; .param p3, "pkg" # Ljava/lang/String; .prologue .line 143 invoke-direct {p0}, Lcom/android/server/StatusBarManagerService;->enforceStatusBar()V .line 145 iget-object v1, p0, Lcom/android/server/StatusBarManagerService;->mLock:Ljava/lang/Object; monitor-enter v1 .line 146 :try_start_6 invoke-direct {p0, p1, p2, p3}, Lcom/android/server/StatusBarManagerService;->disableLocked(ILandroid/os/IBinder;Ljava/lang/String;)V .line 147 monitor-exit v1 .line 148 return-void .line 147 :catchall_b move-exception v0 monitor-exit v1 :try_end_d .catchall {:try_start_6 .. :try_end_d} :catchall_b throw v0 .end method
其中第143行,就是对 enforceStatusBar 函数的调用,这里删除相关的调用即可。
.line 143 invoke-direct {p0}, Lcom/android/server/StatusBarManagerService;->enforceStatusBar()V
修改后的 disable 函数如下:
.method public disable(ILandroid/os/IBinder;Ljava/lang/String;)V .registers 6 .param p1, "what" # I .param p2, "token" # Landroid/os/IBinder; .param p3, "pkg" # Ljava/lang/String; .prologue .line 145 iget-object v1, p0, Lcom/android/server/StatusBarManagerService;->mLock:Ljava/lang/Object; monitor-enter v1 .line 146 :try_start_6 invoke-direct {p0, p1, p2, p3}, Lcom/android/server/StatusBarManagerService;->disableLocked(ILandroid/os/IBinder;Ljava/lang/String;)V .line 147 monitor-exit v1 .line 148 return-void .line 147 :catchall_b move-exception v0 monitor-exit v1 :try_end_d .catchall {:try_start_6 .. :try_end_d} :catchall_b throw v0 .end method
4、使用 smali 对修改后的文件进行编译。命令:java -jar smali.jar SRCDIR -o OUTDIR\classes.dex
5、用压缩方式打开 services.jar,将生成的 classes.dex 复制进去替换同名文件。
6、再将完成修改的 services.jar 文件复制到手机 /system/framework/ 目录并替换源文件,整个framework层的修改就完成了,替换后一定记得修改 services.jar 文件权限并重启手机,默认权限为644。
四、结语
修改后使用之前反射的方式调用 disable 函数就不会再抛出异常,而且下拉栏也被成功禁用。本文主要提供了一种绕过权限检测,禁用下拉菜单的思路,针对4.0以上的大多数系统都能完美实现。大家也可以根据该思路实现其他需要 framework 层修改的功能,具体实现就需要查阅相关系统源码了。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories