Service能够创建界面(addView)吗?

2023-11-10

一个Service能够创建界面(addView)吗?

一个app,只有Service,没有Activity,能够通过WindowManager调用addView()添加可视界面吗?

答案是可以,但是能够创建的界面类型(WindowManager.LayoutParams.type)不多,且大多需要android.permission.INTERNAL_SYSTEM_WINDOW权限,这个权限只能授予system app。

在没有Activity的进程中创建显示View,存在两个问题:

  1. 线程,安卓只能在主线程操作UI界面。
  2. token,在启动Activity时实例化ActivityRecord对象创建token(ActivityRecord继承WindowToken类)。

第一个问题好解决,Service生命周期方法onStartCommand()运行在主线程,可以在此方法中定义Handler,service线程通过handler发送消息跨线程通信,在主线程操作UI界面。

    Handler handler;
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 1:
                        CursorLocationView cursorLocationView = new CursorLocationView(BleService.this);
                        params.type = 2015;		//WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY
                        mWindowManager.addView(cursorLocationView, params);
                        break;
                }
            }
        };
    }

第二个问题需要解决token问题,WindowManagerService.addWindow()方法中在检查到token==null的情况时通过unprivilegedAppCanCreateTokenWith()检查属性:WindowManager.LayoutParams.type,如果不是特权类型的话返回false。

//WindowManagerService.java
	private boolean unprivilegedAppCanCreateTokenWith(WindowState parentWindow,
            int callingUid, int type, int rootType, IBinder tokenForLog, String packageName) {
        if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
            ProtoLog.w(WM_ERROR, "Attempted to add application window with unknown token "
                    + "%s.  Aborting.", tokenForLog);
            return false;
        }
        if (rootType == TYPE_INPUT_METHOD) {
            ProtoLog.w(WM_ERROR, "Attempted to add input method window with unknown token "
                    + "%s.  Aborting.", tokenForLog);
            return false;
        }
        if (rootType == TYPE_VOICE_INTERACTION) {
            ProtoLog.w(WM_ERROR,
                    "Attempted to add voice interaction window with unknown token "
                            + "%s.  Aborting.", tokenForLog);
            return false;
        }
        if (rootType == TYPE_WALLPAPER) {
            ProtoLog.w(WM_ERROR, "Attempted to add wallpaper window with unknown token "
                    + "%s.  Aborting.", tokenForLog);
            return false;
        }
        if (rootType == TYPE_QS_DIALOG) {
            ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with unknown token "
                    + "%s.  Aborting.", tokenForLog);
            return false;
        }
        if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
            ProtoLog.w(WM_ERROR,
                    "Attempted to add Accessibility overlay window with unknown token "
                            + "%s.  Aborting.", tokenForLog);
            return false;
        }
        if (type == TYPE_TOAST) {
            // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
            if (doesAddToastWindowRequireToken(packageName, callingUid, parentWindow)) {
                ProtoLog.w(WM_ERROR, "Attempted to add a toast window with unknown token "
                        + "%s.  Aborting.", tokenForLog);
                return false;
            }
        }
        return true;
    }

可以看到以下类型是需要token的,都和用户界面交互强相关:

  • FIRST_APPLICATION_WINDOW~LAST_APPLICATION_WINDOW
  • TYPE_INPUT_METHOD
  • TYPE_VOICE_INTERACTION
  • TYPE_WALLPAPER
  • TYPE_QS_DIALOG
  • TYPE_ACCESSIBILITY_OVERLAY
  • TYPE_TOAST(appInfo.targetSdkVersion < Build.VERSION_CODES.O 时例外)

其余特权类型在token=null的情况下,创建新的Token对象:

//WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
            LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
            Rect outContentInsets, Rect outStableInsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
            int requestUserId) {
    		...
            if (token == null) {
                if (!unprivilegedAppCanCreateTokenWith(parentWindow, callingUid, type,
                        rootType, attrs.token, attrs.packageName)) {
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
                
                // 特权类型!!!!
                if (hasParent) {
                    // Use existing parent window token for child windows.
                    token = parentWindow.mToken;
                } else {
                    final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
                    token = new WindowToken(this, binder, type, false, displayContent,
                            session.mCanAddInternalSystemWindow, isRoundedCornerOverlay);
                }
            }
}

一些权限类型:

Window Type int permission (*只能赋权给system app)
TYPE_SECURE_SYSTEM_OVERLAY 2015 *android.permission.INTERNAL_SYSTEM_WINDOW 覆盖在所有Window上
TYPE_PHONE 2002 *android.permission.INTERNAL_SYSTEM_WINDOW 覆盖在所有application上,但是不覆盖status bar
TYPE_APPLICATION_OVERLAY 2038 android.permission.SYSTEM_ALERT_WINDOW 覆盖所有Activity window,(types between {@link #FIRST_APPLICATION_WINDOW} and {@link #LAST_APPLICATION_WINDOW})
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Service能够创建界面(addView)吗? 的相关文章

随机推荐

  • unity 调用android的activity,Unity调用Android的Activity

    写了关于Unity与Android结合所遇到的问题及解决方法 总结一下 Unity做一个简单的场景 AndroidStudio建一个简单的项目 其中MainActivity是要继承自 UnityPlayerActivity的 这样Unity
  • python学习(5):celery-beat-task异步驱动框架

    https github com celery celery tree master examples celery的example程序periodic tasks存在如下问题 2017 08 26 21 52 11 412 INFO Ma
  • 开发中遇到的问题

    1 当写一个导出功能时 因为编码写URL地址 参数的时候 用反转字符串的时候换行了 造成地址拼接不成 一直报错 后来发现是编码格式造成的 已解决 解决方案 不换行或者用 拼接 2 当本地项目起两个终端的时候 会有两个地址 如http loc
  • CSS !important 规则

    CSS important 规则 那么什么是 important呢 CSS中的 important 规则用于向属性 值添加比正常值更重要的内容 事实上 如果你用 important 规则 它将覆盖该元素上该特定属性的所有以前的样式设置规则
  • 利用Matlab实现贝叶斯优化卷积神经网络进行数据回归预测

    利用Matlab实现贝叶斯优化卷积神经网络进行数据回归预测 概述 数据回归预测是一项重要的任务 可以通过建立卷积神经网络 Convolutional Neural Network CNN 来实现 然而 在模型参数调优方面存在着挑战 为了解决
  • http请求参数编码问题

    给某api发送http请求 结果查不到数据 而api开发者自测可以查到数据 僵持不下 经过分析发现 我的url是经过urlencode编码的 传出去的中文变成 E5 B2这种 而api开发者的url是明文传输中文 我通过httpclient
  • 构造原生单选或者多选下拉框

    function getRadioList tag pageNum pageSize ajaxHelper ajaxFun type post url data data contentType application json async
  • 急速安装git lfs

    什么是git LFS LFS是large File Storage的缩写 专门用来帮助git管理大型文件 一 curl s https packagecloud io install repositories github git lfs
  • 【问题解决】eclipse ‘Launching Hello'has encountered a problem

    问题 删除eclipse很多项目后 再次运行某一个项目 就会出现错误 eclipse Launching Hello has encountered a problem 解决方案 点此启动此项目 即可 原因 看网上答案 原来点 run 时是
  • 3D 智慧农场可视化——解锁绿色生态田园

    何为 无人农场 中国工程院院士罗锡文用五句话高度概括 耕种管收生产环节全覆盖 机库田间转移作业全自动 自动避障异况停车保安全 作物生产过程实施全监控 智能决策精准作业全无人 随着新一代信息技术飞速融入传统产业 农业数字化 网络化 智能化逐步
  • 聊天室--javaWeb

    文章目录 一 简介 项目说明 实现的主要功能 系统架构 二 项目代码和demo地址 项目代码 项目demo地址 三 具体的功能实现 登录功能 单点登录 聊天功能的实现 踢人功能 简单的分权限 四 补充说明 关于代码 关于项目部署 一 简介
  • 方舟官方服务器怎么显示血量,方舟端游怎么显示血量

    解决方舟如何显示伤害数字 在ARK ShooterGame Saved Config WindowsNoEditor文件夹下的GameUserSetting文件的 ServerSettings 的最后一行中添加命令 ShowFloating
  • array_filter函数的简单使用

    array filter函数 学习笔记 代码 function test odd var 先创建一个方法 方法是调动test odd函数 return var 1 返回条件 取奇数 a1 array a b c 2 3 4 11 23 ec
  • #vue# vue锚点定位,滚动到具体位置

    需求 点击导航栏的各个tab 跳转 滚动 到当前页面的具体位置 步骤 1 首先在导航栏的版块里面加入方法goToAnchor 以及 跳转的id类名 div class nav item center div About div div To
  • 查看.o, .obj文件符号列表,强大的nm命令

    nm命令可以查看 linux以及windows下的 o obj文件中的符号列表 其中 o文件可以由gcc g 编译得到 obj由vc编译得到 太爽了 以后遇到undefined reference错误的时候就可以这个命令搞定了 举一例子 在
  • 【java笔记】常用接口(2):Consumer接口

    Consumer接口是一个消费型接口 泛型指定什么类型 就可以使用accept消费什么类型数据 直接输出 public class Demo public static void main String args method asd na
  • 高德地图弹窗使用vue模板

  • android 遍历assets下的文件

    在AssetManager中有个list 方法 传入你的子文件名称即可 String flLists this getAssets list your subdir 如果是根目录 那么就是这么写 AssetManager assetMana
  • 集合框架的简要介绍

    目录 集合和数组的区别 Collection接口 ArrayList实现类 ArrayList的创建和使用 linkedList Set接口及其实现类 Set接口特点 HashSet实现类 HashSet特点 HashSet避免对象重复的规
  • Service能够创建界面(addView)吗?

    一个Service能够创建界面 addView 吗 一个app 只有Service 没有Activity 能够通过WindowManager调用addView 添加可视界面吗 答案是可以 但是能够创建的界面类型 WindowManager