我想用代码来打开android的消息中心,也叫做statusbar、通知栏。通知栏其实就是一个常驻的服务,至于原理这里就不多说了,简单说下思路和问题。
思路:API中没有实现的方法,那么就利用反射机制
问题:4.2系统中的方法变更
解决办法:分系统实现不同的方法
源码路径:……sdksourcesandroid-18androidappStatusBarManager
我们先来看android 4.4(API 19)中的方法,android 4.3(API 18),android 4.2.2(API 17)中都是下列方法
/** * Expand the notifications panel. */ public void expandNotificationsPanel() { try { final IStatusBarService svc = getService(); if (svc != null) { svc.expandNotificationsPanel(); } } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } /** * Collapse the notifications and settings panels. */ public void collapsePanels() { try { final IStatusBarService svc = getService(); if (svc != null) { svc.collapsePanels(); } } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } }
我们再来看android 4.1.2(API 16)中的方法,终于发现了方法名的不同了。
/** * Expand the status bar. */ public void expand() { try { final IStatusBarService svc = getService(); if (svc != null) { svc.expand(); } } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } /** * Collapse the status bar. */ public void collapse() { try { final IStatusBarService svc = getService(); if (svc != null) { svc.collapse(); } } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } }
最后发现API 16自己包括之前的方法都是叫做expand(),collapse(),之后的方法就改名了。至于改名的原因也很清楚,就是4.2后状态栏中多了一个设置界面。所以要所写一个方法,由于expand(展开)这个方法名太笼统,所以就把拉开通知栏的方法叫做了expandNotificationsPanel,把拉开设置界面的方法叫做expandSettingsPanel。
下面是折叠/拉开设置界面的方法:
/** * Collapse the notifications and settings panels. */ public void collapsePanels() { try { final IStatusBarService svc = getService(); if (svc != null) { svc.collapsePanels(); } } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } } /** * Expand the settings panel. */ public void expandSettingsPanel() { try { final IStatusBarService svc = getService(); if (svc != null) { svc.expandSettingsPanel(); } } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); } }
好啦,找到问题后我们就需要用反射机制和判断系统版本的方式来写代码了。
/** * 显示消息中心 */ public static void openStatusBar(Context mContext){ try { Object service = mContext.getSystemService ("statusbar"); System.out.println("SDK INT= "+VERSION.SDK_INT +" BUILD.VERSION.SDK"+Build.VERSION.SDK_INT); Class <?> statusBarManager = Class.forName("android.app.StatusBarManager"); // 判断系统版本号 String methodName = (VERSION.SDK_INT<=16)?"expand":"expandNotificationsPanel"; Method expand = statusBarManager.getMethod (methodName); expand.invoke (service); } catch (Exception e) { e.printStackTrace(); } } /** * 关闭消息中心 */ public static void closeStatusBar(Context mContext){ try { Object service = mContext.getSystemService ("statusbar"); Class <?> statusBarManager = Class.forName("android.app.StatusBarManager"); // 判断系统版本号 String methodName = (VERSION.SDK_INT<=16)?"collapse":"collapsePanels"; Method expand = statusBarManager.getMethod(methodName); expand.invoke(service); } catch (Exception e) { e.printStackTrace(); } }
整理后得到如下代码,方便大家调用(android 2.2及以上测试正常):
private static void doInStatusBar(Context mContext, String methodName) { try { Object service = mContext.getSystemService("statusbar"); Class<?> statusBarManager = Class.forName("android.app.StatusBarManager"); Method expand = statusBarManager.getMethod(methodName); expand.invoke(service); } catch (Exception e) { e.printStackTrace(); } } /** * 显示消息中心 */ public static void openStatusBar(Context mContext) { // 判断系统版本号 String methodName = (VERSION.SDK_INT <= 16) ? "expand" : "expandNotificationsPanel"; doInStatusBar(mContext, methodName); } /** * 关闭消息中心 */ public static void closeStatusBar(Context mContext) { // 判断系统版本号 String methodName = (VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels"; doInStatusBar(mContext, methodName); }