文章目录

  • 创建surface
  • 创建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

关于窗口的层次关系:同一类型的窗口后添加的窗口是在之前添加的窗口之上的,所以要让你自己新建的窗口位于原生窗口之下的话,你需要让你的窗口创建时机早于wallpaperService原生创建wallpaper类型Window的时机,即你自己的创建时机早于updateSurface函数执行时机就可以

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

  • adb shell dumpsys SurfaceFlinger

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

  • adb shell dumpsys window

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

如何编译代码

上面的代码很多都调用了hide接口,android studio直接编译是编译不过的,下面给出两种解决办法:

  1. 下载全量的android源码,在源码中增加单独的module,这样就会编译得到一个你需要的jar
  2. app的编译依赖中增加framework.jar,这样app中调用hide接口的代码就可以直接编译过了,这样就很方便(推荐)

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

Android中创建Surface和TYPE_WALLPAPER类型的window相关推荐

  1. Android中的Android中的Surface和SurfaceView

    一.什么是Surface 简单的说Surface对应了一块屏幕缓冲区,每个window对应一个Surface,任何View都要画在Surface上.传统的view共享一块屏幕缓冲区,所有的绘制必须在U ...

  2. 如何在android中创建自定义对话框?

    本文翻译自:How to create a Custom Dialog box in android? I want to create a custom dialog box like below ...

  3. Android中的Surface, SurfaceHolder, SurfaceHolder.Callback, SurfaceView

    传入一个surface,然后让openGL在surface上画图 window->view hierachy(DecorView是tree的root)->ViewRoot->Surf ...

  4. android sqlite 创建空表,sqlite3在android中创建表错误(sqlite3 create table error in android)...

    sqlite3在android中创建表错误(sqlite3 create table error in android) 我试图在android中使用sqlite3创建表我的开放助手是这样的: pub ...

  5. android中的surface

    在android中,对view及其子类,都是画在surface上的.每个window对应一个surface,各surface对象通过surfaceflinger合成到framebuffer,每个sur ...

  6. Android中创建自己的对话框

    Activities提供了一种方便管理的创建.保存.回复的对话框机制,例如 onCreateDialog(int), onPrepareDialog(int, Dialog), showDialog( ...

  7. Android中创建和响应选项菜单

    计应112班 谭娇娇 这个是一个创建菜单和响应选项的一个实例同时也Android同样支持子菜单,你可以通过addSubMenu(int groupId, int itemId, int order, ...

  8. android 实现定时通知,在Android中创建定时通知(例如,针对事件)

    对于某些Android应用程序,我想集成以下功能: 用户可以定义他想要被提醒的时间.当时间到了,应用程序应该在通知栏中创建通知,即使此时用户没有使用该应用程序. 为此,需要查看AlarmManager ...

  9. 如何轻松理解Android中的Surface概念

    安卓开发中,涉及多媒体尤其是视频,经常会接触到一个概念Surface 那么如何理解他呢.最简单的理解就是其实就是一块内存区域仅此而已. 如果通过字面理解,好像是一个平面,但这个平面在哪里呢? 写代码经 ...

最新文章

  1. Flask-RESTful的简单使用
  2. python经典案例-Python经典实例
  3. java mail 发件人昵称,Java使用javax.mail发送邮件 解决收件人、发件人名字乱码问题...
  4. Electron中 提示:Uncaught ReferenceError: process is not defined
  5. stm32串口通信(初学者对于串口通信的理解)
  6. 你爱我吗? | 今日最佳
  7. 【Hibernate3.3复习知识点二】 - 配置hibernate环境(annotations)
  8. HSRP的初步解析及典型应用2
  9. 舵机控制激光头(51单片机)
  10. 软件工程的难题-解耦问题
  11. 【英语学习】【Level 07】U06 First Time L2 A good food experience
  12. 关于OPENGL与OPENGL ES的区别
  13. linux内存中的文件权限,理解Linux文件权限
  14. 档案管理软件 php_致PM:除了Excel,你还有这五个项目管理软件可以用
  15. 程序员常去的14个顶级开发社区
  16. bzoj·入门OJ·统计损失
  17. 计算机仿真实训平台软件,虚拟仿真实验室软件有哪些
  18. 华为手机Mate20pro打开AP LOG依然无法连接Locat解决办法
  19. unity开发记录:TextMeshPro设置显示中文
  20. 阿里云安全中心如何设置掌控云服务器安全

热门文章

  1. 陌陌-pyspark
  2. c语言c 关键字大全,C语言关键字大全(共32个)
  3. PLSQL导入dmp文件或sql文件
  4. Maple 入门常用教程
  5. springBoot集成Activiti5.0
  6. 关于取消计算机系统集成资质,系统集成资质取消了吗
  7. 再见 Typora!这款 Markdown 神器绝了!
  8. SQL Server 2008R2完整安装教程
  9. 被入侵计算机系统恢复指南(转)
  10. 读《神奇的手帐整理魔法》