越过用户授权使用浮窗

上一片篇文章分析了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

时间: 2024-10-06 00:43:19

越过用户授权使用浮窗的相关文章

浮窗开发之窗口层级

最近在项目中遇到了这样的需求:需要在特定的其他应用之上悬浮自己的UI交互(拖动.输入等复杂的UI交互),和九游的浮窗类似,不过我们的比九游的体验更好,我们越过了很多授权的限制. 很多人都知道如何去实现一个简单的浮窗,但是却很少有人去深入的研究背后的流程机制,由于项目中浮窗交互比较复杂,遇到了些坑查看了很多资料,故总结浮窗涉及到的知识点: * 窗口层级关系(浮窗是如何"浮"的)? * 浮窗有哪些限制,如何越过用户授权实现浮窗功能? * 窗口与用户输入系统(Activity是如何接收到to

Android 浮窗开发之窗口层级

很多人都知道如何去实现一个简单的浮窗,但是却很少有人去深入的研究背后的流程机制,由于项目中浮窗交互比较复杂,遇到了些坑查看了很多资料,故总结浮窗涉及到的知识点: 窗口层级关系(浮窗是如何"浮"的)? 浮窗有哪些限制,如何越过用户授权实现浮窗功能? 窗口与用户输入系统(Activity是如何接收到touch事件?). 本章我们来研究第一个问题:浮窗为何会浮. 浮窗之所以叫浮窗,是因为它能悬浮于应用或者桌面窗口之上,能脱离Activity而存在.为了研究其中区别,我们先来看看我们最熟悉的A

Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮

前言 之前写过屏蔽系统导航栏功能的文章,具体可看Android6.0 源码修改之屏蔽导航栏虚拟按键(Home和RecentAPP)/动态显示和隐藏NavigationBar 在某些特殊定制的版本中要求完全去掉导航栏,那么当用户点进一些系统自带的应用界面如设置.联系人等,就没法退出了,虽然可以在actionBar中添加back按钮,但总不能每一个app都去添加吧.所以灵机一动我们就给系统添加一个全屏可拖拽的浮窗按钮,点击的时候处理返回键的逻辑.它大概长这样(审美可能丑了点,你们可以自由发挥) 图1

仿360在Launcher画面显示内存使用率的浮窗(基础版)

MainActivity如下: package cc.cc; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.app.Activity; import android.content.Context; import android.content.Intent; /**

【回忆1314】回忆之浮窗

直接看效果点这里 HTML <!DOCTYPE html> <html> <head lang="zh-CN"> <meta charset="utf-8"> <title> 浮窗 </title> <style> * { margin: 0; padding: 0; } .staff { width: 1200px; margin: 0 auto; height: 800px; l

仿360在Launcher画面显示内存使用率的浮窗(改进版)

MainActivity如下: package cc.cc; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.app.Activity; import android.content.Context; import android.content.Intent; /**

自定义提示用户授权使用地理定位功能时的提示语

以前程序的地理定位功能若查询GPS授权情况,返回的是CLAuthorizationStatus.NotDetermined,意思是授权状态未定. 需要在使用CoreLocation前调用方法 requestWhenInUseAuthorization() 或者 requestAlwaysAuthorization() 并在Info.plist中加入两个缺省没有的字段 NSLocationAlwaysUsageDescription NSLocationWhenInUseUsageDescript

VC++玩转炫酷悬浮窗1---悬浮窗的实现

?? 目标实现像迅雷那样炫酷的悬浮窗.计划&方案首先第一步要实现一个悬浮窗,窗体无边框,能够随意拖动.对于一个窗体来说,只有我们把鼠标放到标题栏中才进入到拖拽模式.由于是无边框的窗体,默认是不能够移动的.我们尝试用两种办法使其跟随鼠标移动.一个是用OnNcHitTest函数,另一个是在OnLButtonDown时发消息.实践一. OnNcHitTest方案这个CWnd类的一个方法,我们可以捕捉鼠标点击的坐标,然后将其HTCLIENT结果偷换成HTCAPTION,这样就可以让系统误以为鼠标左键点击

网页浮窗效果

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-