android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@411da608 -- permission denied for this window type: at android.view.ViewRootImpl.setView(ViewRootImpl.java:537) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:301) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:215) at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:140) at android.view.Window$LocalWindowManager.addView(Window.java:537) at android.app.Dialog.show(Dialog.java:278)
① android.view.ViewRootImpl.setView(ViewRootImpl.java:481) ② com.android.server.wm.Session.add(Session.java:139) ③ com.android.server.wm.WindowManagerService.addWindow(WindowManagerService:1999) ④ com.android.internal.policy.impl.PhoneWindowManager.checkAddPermission(PhoneWindowMana:1063)
在这里发现了
String permission = null; switch (type) { case TYPE_TOAST: // XXX right now the app process has complete control over // this... should introduce a token to let the system // monitor/control what they are doing. break; case TYPE_INPUT_METHOD: case TYPE_WALLPAPER: // The window manager will check these. break; case TYPE_PHONE: case TYPE_PRIORITY_PHONE: case TYPE_SYSTEM_ALERT: case TYPE_SYSTEM_ERROR: case TYPE_SYSTEM_OVERLAY: permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW; break; default: permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; }
可是带进去一跑,还是不行,再找
<!-- Allows an application to open windows that are for use by parts of the system user interface. Not for use by third party apps. --> <permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" android:label="@string/permlab_internalSystemWindow" android:description="@string/permdesc_internalSystemWindow" android:protectionLevel="signature" />原来有个保护等级,baidu了一下有四个
等级不够,用不了
・Service的Context可以显示。
4、Service中的代码
public void test() { View v = View.inflate(mContext, R.layout.volume_panel, null); AlertDialog.Builder b = new AlertDialog.Builder(mContext, R.style.selectorDialog); b.setView(v); AlertDialog d = b.create(); d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); //d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY); d.show(); /* set size & pos */ WindowManager.LayoutParams lp = d.getWindow().getAttributes(); WindowManager wm = (WindowManager) mContext.getSystemService(mContext.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); if (display.getHeight() > display.getWidth()) { //lp.height = (int) (display.getHeight() * 0.5); lp.width = (int) (display.getWidth() * 1.0); } else { //lp.height = (int) (display.getHeight() * 0.75); lp.width = (int) (display.getWidth() * 0.5); } d.getWindow().setAttributes(lp); Log.d("M1-service", "show()"); }
其实不用Service,也可以直接使用WindowManager.addView()在后台直接显示窗口
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); mDesktopLayout = inflater.inflate(R.layout.volume_panel, null); // 取得系统窗体 mWindowManager = (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE); // 窗体的布局样式 mLayoutParams = new WindowManager.LayoutParams(); // 设置窗体显示类型――TYPE_SYSTEM_ALERT(系统提示) mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; // 设置窗体焦点及触摸: // FLAG_NOT_FOCUSABLE(不能获得按键输入焦点) mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 设置显示的模式 mLayoutParams.format = PixelFormat.RGBA_8888; // 设置对齐的方法 mLayoutParams.gravity = Gravity.TOP | Gravity.LEFT; // 设置窗体宽度和高度 mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; // 设置窗体显示的位置,否则在屏幕中心显示 mLayoutParams.x = 50; mLayoutParams.y = 50; mWindowManager.addView(mDesktopLayout, mLayoutParams);6、总结
这两种方式显示出来的窗口都不会激发当前Activity的onPause()事件。据说还可以先一个窗口风格的Activity,不过显示时会激发当前窗口的onPause()事件,具体咋样没试过。
网上下了一个风格非常不错
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="selectorDialog" parent="@android:style/Theme.Dialog"> <item name="android:windowFrame">@null</item><!--边框--> <item name="android:windowIsFloating">true</item><!--是否浮现在activity之上--> <item name="android:windowIsTranslucent">false</item><!--半透明--> <item name="android:windowNoTitle">true</item><!--无标题--> <!--<item name="android:windowBackground">@drawable/selector_dialog_bg</item>背景透明--> <item name="android:backgroundDimEnabled">false</item><!--模糊--> <item name="android:backgroundDimAmount">0.6</item> </style> </resources>