最近项目新需求要用到悬浮球技术,因以前的工作项目中就用到了这个技术,因此看到这个需求时心里是愉悦的,心念着照搬过来即可。开发中也确实如此,直接搬过来,然后测试了三星C5,小米Note4以及OPPO手机,运行顺畅,均无异常。当测试到华为Honor8青春版时,就GG了。抛出了以下异常:
java.lang.RuntimeException: Unable to create service com.haoyue.notedemos.floatball.FloatServive: android.view.WindowManager$BadTokenException:
Unable to add window android.view.ViewRootImpl$W@270feab --
******permission denied for window type 2002******
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3878)
at android.app.ActivityThread.-wrap5(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1989)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
Caused by: android.view.WindowManager$BadTokenException:
******Unable to add window android.view.ViewRootImpl$W@270feab -- ******
******permission denied for window type 2002******
at android.view.ViewRootImpl.setView(ViewRootImpl.java:908)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:372)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:128)
at com.haoyue.notedemos.floatball.FloatServive.initFloatBall(FloatServive.java:64)
at com.haoyue.notedemos.floatball.FloatServive.onCreate(FloatServive.java:34)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3858)
at android.app.ActivityThread.-wrap5(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1989)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
异常的重点在这里:Unable to add window android.view.ViewRootImpl$W@270feab –permission denied for window type 2002,大体上说就是需要Window type的权限。这就真GGJJ了,不是给了:
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE的权限么?
工程中关于该部分的代码如下:
mLayoutParams = new WindowManager.LayoutParams();
mManager = (WindowManager) getApplication().getSystemService(WINDOW_SERVICE);
mLayout = (LinearLayout) LayoutInflater.from(getApplication()).inflate(R.layout.flaot_ball, null);
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
mLayoutParams.format = PixelFormat.RGBA_8888;
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayoutParams.x = 100;
mLayoutParams.y = 100;
mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mManager.addView(mLayout, mLayoutParams);
xml文件清单也配置了这两条权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
查询了很多资料,没几篇文章能够说清楚怎么回事,怎么解决。好吧,回到原点,排查该异常的原因。查来查去,除了发现华为honor青春版时8.0版本的系统外,就没有别的特别明显的不同了。难道是8.0版本的问题?
再次带着问题查询资料,不同的是目的性更强:Android8.0下的悬浮球。终于,找到了原因,有大神遇到相同的问题并解释清了抛该异常的原因:
在Android O之前的系统中申请了该权限后,再给对应的window设置:
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE即可。
但是在Android O的系统中,除了在xml文件清单中配置权限外,google规定还要申请权限:.
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
只有这样,悬浮窗才能显示出来。
所以,在授予权限时,要对手机的版本做如下判断:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}else {
mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
SDK版本在Android8.0(Android 0)以上,授予TYPE_APPLICATION_OVERLAY权限,在这之下的,授予TYPE_PHONE权限。不能为了省事,统一的授予TYPE_APPLICATION_OVERLAY,否则8.0之下的机型还是会继续报前面的错误。