IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android中创建Surface和TYPE_WALLPAPER类型的window -> 正文阅读

[移动开发]Android中创建Surface和TYPE_WALLPAPER类型的window

上面这两个技术的出发点:因为Android中同一时刻只能运行单个WallpaperService,一个WallpaperService只有一个Surface,因此当你需要在一个WallpaperService中使用多个Surface的时候,可以使用上面的方式创建Surface来进行显示。

创建surface

当需要自己创建一个surface的时候,首先应用必须是系统应用,因为底层的一些接口和权限只有系统应用才能获取到。
创建Surface的时候我们需要下面的权限:

<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER"/>

查看系统中对该权限的定义:

<!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
         <p>Not for use by third-party applications.
         @hide
    -->
    <permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
        android:protectionLevel="signature" />

该权限只有系统签名的应用才能使用,当app获得了该权限,会在system/etc/permissions/下面根据app的预置目录生成响应的xml,该xml中包含了该路径下app的系统权限。
拥有了权限之后,就可以开始进行Surface的创建了,创建的源码参考View中Surface的创建,也可以参考SurfaceView中Surface的创建:

        final SurfaceSession session = new SurfaceSession();
        final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
                .setName("drag surface")
                .setParent(root.getSurfaceControl())
                .setBufferSize(width, height)
                .setFormat(PixelFormat.TRANSLUCENT)
                .build();
        final Surface surface = new Surface();
        surface.copyFrom(surfaceControl);

如果没有parent的话,可以省略这个。然后,使用下面的方式让Surface显示出来:

SurfaceControl.openTransaction()try{
 surfaceControl.show();
}finally{
SurfaceControl.closeTransaction();
}

上面的接口有很多都是Hide接口,只有系统应用才能直接调用,创建了Surface之后,就可以使用创建的Surface显示图像了,具体可以参考View和SurfaceView中的源码创建Surface中。

创建Wallpaper类型的window

在壁纸服务中是没有办法使用View的,如何哪位同学知道咋使用View希望能帮忙解答下。
wallpaper类型的window可以使用窗口动效,因而我们可以简单的实现缩放,透明度变化等动画效果,上面的创建Surface的方式可以创建一个单独的图像缓冲区,但是创建的Surface没有依赖于window,所以没办法使用窗口动效,那么如何让新建的Surface拥有窗口动效的能力呢,可以参考WallPaperService创建window的过程。主要涉及WallpaperService和WallaperManagerService两个类。
Android原生壁纸启动的时候,WallpaperManagerService会向WallpaperService传递一个比较重要的对象,mToken,这个其实是一个Binder对象,wms用这个来标识可以来管理窗口。

mWindowManagerInternal.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId);

同时WallpaperManagerService还给WallpaperService传递了displayid,宽高等参数。
在WallpaperService中,首先会获取windowSession,并将session和window相关联:

mSession = WindowManagerGlobal.getWindowSession();
mWindow.setSession(mSession);

关联了后,会调用mSession.addToDisplay添加window,添加了Window之后,调用mSession.relayout,具体这里的作用是在做什么其实不大清楚,但是看代码传递进去了一个SurfaceControl,之后从SurfaceControl中获得了创建好的Surface,至此我们就可以使用创建好的Surface了。window相关参数的在WallpaperService和WallaperManagerService中加日志,然后在自己的window中设置相应的参数。

final int relayoutResult = mSession.relayout(mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,View.VISIBLE, 0, -1, mWinFrame, mContentInsets,mVisibleInsets, mStableInsets, mBackdropFrame,mDisplayCutout, mMergedConfiguration, mSurfaceControl,mInsetsState, mTempControls, mSurfaceSize, mTmpSurfaceControl);
if (mSurfaceControl.isValid()) {                     mSurfaceHolder.mSurface.copyFrom(mSurfaceControl);
}

如果是我们自己创建window的话,还需要自己调用下面的方法让图像显示出来:

SurfaceControl.openTransaction()try{
 surfaceControl.show();
}finally{
SurfaceControl.closeTransaction();
}

当绘制的图像显示出来的时候,应该调用下面的方法向wms汇报绘制完成,这样窗口状态才能正确,不然会奇怪的问题,比如闪一帧黑屏。

mSession.finishDrawing(mWindow, null /* postDrawTransaction */)

最后,当服务销毁的时候,应该将window和创建的wallpaperWindowtoken移除。

mSession.remove(mWindow);
mWindowManagerInternal.removeWindowToken(mToken, false,mDisplayId)

其它:addWindowToken首先需要权限:
WindowManagerService在添加窗口的时候首先会进行权限校验:

    private int addWindowTokenWithOptions(IBinder binder, int type, int displayId, Bundle options,
            String packageName, boolean fromClientToken) {
        final boolean callerCanManageAppTokens =
                checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()");

需要下面的系统权限,只有是系统应用才能拿到

android.permission.MANAGE_APP_TOKENS

在完成自建window的时候,同时自己也学习了一些基本的调试和定位命令:
dump surfacelinger信息:

  • adb shell dumpsys SurfaceFlinger

dump window查看窗口层级信息(连续抓取多帧的时候可以for循环抓取,但是dump需要时间,不可能每一帧都抓到):

  • adb shell dumpsys window

同时,我们可以使用:
adb shell dumpsys –help 查看基本命令帮助
使用 adb shell dumpsys -l 查看支持dump的模块

参考:SurfaceView源码,WallpaperService和WallpaperServiceManager源码。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-25 11:48:06  更:2021-07-25 11:48:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 18:26:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码