上一片篇文章分析了Android窗口系统层次、Ativity的窗口和系统窗口的区别,这篇文章我来说说使用系统窗口来实现浮窗的一些限制,我们如何越过这些限制。

简单的浮窗实现

final WindowManager windowManager =     getWindowManager(context);//创建自定义浮窗 FloatView    hideDialog = new FloatView(context);WindowManager.LayoutParams  params = new     WindowManager.LayoutParams();//params.type 窗口类型,主要决定了窗口的层次params.type = WindowManager.LayoutParams.TYPE_PHONE;params.format = PixelFormat.RGBA_8888;//params.flags 描述窗体其他属性的标记位,//LayoutParams.FLAG_NOT_FOCUSABLE表示不能获取输入法焦点params.flags = LayoutParams.FLAG_NOT_FOCUSABLE;params.gravity = Gravity.LEFT | Gravity.TOP;params.width = LayoutParams.MATCH_PARENT;params.height = LayoutParams.MATCH_PARENT;//添加windowManager.addView(hideDialog, dialogParams);

使用WindowManager.LayoutParams.TYPE_PHONE
或WindowManager.LayoutParams.TYPE_SYS_ALERT窗体类型,然后在别忘了AndroidManifest.xml文件中申明权限

窗实现越过权限使用浮窗

《交易猫》App已经越过浮窗授权,正常使用浮窗功能。


类型为TYPE_PHONE、TYPE_PRIORITY_PHONE、TYPE_SYSTEM_ALERT、TYPE_SYSTEM_ERROR、TYPE_SYSTEM_ERROR这些的窗口都是需要用户授权的,类型为TYPE_TOAST的不需要,然而在Android 4.4 (api 19)以下TYPE_TOAST是无法获取焦点的,具体源码分析过程可以参考文章:
[《Android悬浮窗TYPE_TOAST小结源码分析》](http://www.90159.com/2015/11/14/Android-Floating-analysis/)。于是我们就可以做一个细分流程了:首先获取系统版本如果大于等于19我们使用TYPE_TOAST,小于19我们使用TYPE_PHONE窗口类型。

输入法的限制

在4.4以上使用TYPE_TOAST还是有些小小的限制,如果浮窗交互中需要输入框,TYPE_TOAST和TYPE_PHONE两种类型窗体对输入法的处理还是有些区别。当我们的浮窗在横屏环境中(浮窗下面的应用是横屏的),输入法默认是全屏的,我们可以通过设置文本属性android:imeOptions=“flagNoExtractUi”来禁止输入法的全屏,同时可以设置窗体属性为adjustResize来适配调整浮窗位置防止输入法盖住输入框。

然而adjustResize这个属性对TYPE_TOAST类型的窗体是无效的,本人暂时没找到对应的源码佐证,如果你找到了请告诉我一下。所以如果你的浮窗交互中是需要输入文字的,就不能使用半屏幕输入法的体验了。

为了最大程度的优化体验,我们使用浮窗的流程可以细化为:


关于浮窗授权,我们可以使用一下方法来判断是否授权:

/** * 判断是否开启浮窗权限,api未公开,使用反射调用 * @return */private static boolean hasAuthorFloatWin(Context context){    if (Device.getSystemVersion() < 19){        return false;    }    try {        AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);        Class c = appOps.getClass();        Class[] cArg = new Class[3];        cArg[0] = int.class;        cArg[1] = int.class;        cArg[2] = String.class;        Method lMethod = c.getDeclaredMethod("checkOp", cArg);        //24是浮窗权限的标记        return (AppOpsManager.MODE_ALLOWED == (Integer) lMethod.invoke(appOps, 24, Binder.getCallingUid(), context.getPackageName())){    } catch(Exception e) {       return false;    }}

AppOpsManager是api 19以后引入的,第三方rom可以利用它来管理权限,将某些权限交给用户来定夺,例如浮窗。详细参考官方文档:AppOpsManager。

更多相关文章

  1. Copy" did not complete normally. Please see the log for more
  2. Android培训班(50)
  3. android 【点击输入框调出输入法前的】输入框获取焦点和输入法的
  4. Android_显示某个Activity时立即弹出软键盘
  5. android关闭应用程序
  6. Android(安卓)5.0(Lollipop)事件输入系统(Input System)
  7. Android使用SwipeListView实现类似QQ的滑动删除效果
  8. Android平台输入法的生命周期
  9. Android中使用Intent进行窗体切换,并且传值和自定义类的对象详解

随机推荐

  1. android代码实现关机
  2. Android market 发布个人免费应用的步骤
  3. Android之Bundle传递数据详解与实例及Bun
  4. Android深入浅出系列课程---Lesson0 SHW1
  5. Smalidea+IntelliJ IDEA/Android Studio
  6. Android中使用apache commons-net发送后
  7. Android联系人数据库全解析(4)
  8. android 报错java.io.IOException: Permi
  9. android 拨号盘Contact模块讲解(四)
  10. 使用NDK开发SQLite3