android视频壁纸源码,Android 视频壁纸

最近开发了一个视频桌面类的App,期间遇到了一些问题,现在做一个总结,记录一下自己的分析过程。也希望能够给遇到相关问题的人带来一些收获吧。

1.视频壁纸的实现

在网上搜索一下Android视频桌面的实现,很顺利的完成了一个应用,主要用到的类有两个:

WallpaperService

这是Android系统提供的一个用于实现壁纸服务的抽象类,它的唯一目的就是根据需要生成一个Engine的实例。主要复写如下方法即可,该方法返回一个Engine类:

@Override

public Engine onCreateEngine() {

return new Engine();

}

WallpaperService.Engine

这个类是WallpaperService的一个内部类,WallpaperService要返回的Engine就是它。这个Engine是壁纸的实际实现。这个Engine会提供一个对应的SurfaceHolder,预览视频时MediaPlayer可以通过调用mPlayer.setSurface(surface);将Engine提供的SurfaceHolder.getSurface()设置进去。

主要复写以下几个方法:

public void onCreate(SurfaceHolder surfaceHolder) {

}

public void onDestroy() {

}

public void onVisibilityChanged(boolean visible) {

}

public void onSurfaceCreated(SurfaceHolder holder) {

}

public void onSurfaceDestroyed(SurfaceHolder holder) {

}

其中onVisibilityChanged方法非常重要,在该方法中,当visible为false时,你可能就需要暂停视频的播放。

然后通过如下方式启动壁纸服务:

Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);

intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,

new ComponentName(activity, VideoWallpaperService.class));

activity.startActivityForResult(intent, REQUEST_SET_LIVE_WALLPAPER);

效果如下图所示:

628a1d678c15fb843e874a284b05524e.png

2.遇到的问题(一):设置第一个视频桌面后,第二个只能预览,设置不成功

第一反应是不是哪里代码写错了,于是到网上到处找资料。一行一行对比代码。期间下载了网上的例子,发现有些也有这个问题。于是在stackoverflow上搜索,

https://stackoverflow.com/questions/39805800/live-wallpaper-not-change-in-android-device-when-set-another-live-wallpaper/39888063#39888063

结果真的搜索到一个答案。在启动壁纸服务之前之前调用如下代码

try {

WallpaperManager wm = WallpaperManager.getInstance(context);

wm.clear();

} catch (IOException e) {

e.printStackTrace();

}

然后将这个代码加了上去。本以为这样就结束了,可是测试着发现,当你点击设置壁纸到壁纸预览界面的时候。这个时候如果你返回,不把当前视频设置为壁纸,你会发现你之前设置的壁纸也已经被清除了。这显然是不满足产品需求的。

于是老老实实看代码,研究为啥设置壁纸的时候能够预览,但是设置不生效。刚开始以为是缓存,是不是设置过视频之后,系统的壁纸服务是从缓存再读取数据。找了一圈也没有缓存相关的信息与接口。于是在自己实现的WallpaperService内的所有类的所有回调方法里面打印信息,先点击进入预览界面。然后上面提到的Engine的回调方法都走了一遍,然后点击设置壁纸,发现又走了一遍上面的方法。而且又走了次onSurfaceDestroyed,这就很奇怪了。过滤之后的信息如下:

bb3ae97a31ad59ea61720b95894545b6.png

为什么Engine会走两遍了,真的是想不通。点进去Engine里看源代码,结果类上面有这样的注释

24d4d50fb737a79f12cb8cd8d3f9b045.png

上面的意思是一个wallpaper service 可能有多个运行的Engine实例,例如用于预览的Engine以及用于真正壁纸的Engine。于是赶紧去验证一下,在上面自定义Engine里面所有的生命周期方法中打印一下Engine的hashcode,以及surfaceviewholder的hashcode,果然两次的值是不一样的。然后重新设置一下壁纸,发现只有用于Preview的Engine销毁重建了,用于真正壁纸的Engine是没有销毁重建的。这样就解释了为什么第二次设置视频壁纸的时候设置不上,因为real wallpaper的engine还是用的之前的。那么现在我们如果想要更新的话只需要将real wallpaper engine里的视频源更新一下就好。那么我们首先要做的就是将real wallpaper的engine保存下来。那么怎么区分是preview还是real wallpaper的engine呢,查看service的源码还真找到了如下方法

/**

* Returns true if this engine is running in preview mode -- that is,

* it is being shown to the user before they select it as the actual

* wallpaper.

*/

public boolean isPreview() {

return mIWallpaperEngine.mIsPreview;

}

那么我们需要做的就是在自定义的Engine里的onCreate方法中调用该方法判断一下,如果不是Preview的Engine就将当前Engine保存下来。用于之后的视频源更新。

3.遇到的问题(二) 清除最近运行应用的时候,有些手机设置的壁纸会失效

其实这个问题本质是,有些手机清除最近应用时会杀掉进程,而有些手机不会。而一旦进程被杀掉,壁纸服务就会停止运行,然后设置的壁纸自然会失效。然后研究了一下火萤和抖音,发现他们的方案是需要下载一个插件,然后插件其实是一个独立的提供壁纸服务的apk。大家可以去试一下,只要把这个插件的进程杀掉,他们设置的壁纸一样会失效。

由于我们这个壁纸应用只是简单的想进入应用市场试一下,就只做了简单的处理。

1.我们是在android配置文件中设置了如下代码,让应用不显示在最近运行的进程任务列表中;

android:excludeFromRecents="true"

2.同时提高了Service的优先级,让service不那么轻易被杀死;

4.总结

其实遇到问题的时候,在简单搜索之后,如果找不到答案,就应该好好查看代码,通过代码来分析定位问题。不应该一直在网上搜索,去找现成的答案,我就是在这上面浪费了许多时间。长时间尝试自己定位问题,思考解决方案之后,自己解决代码的能力才会越来越强。加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值