Advertisement

Android 仿火萤视频桌面 神奇的LiveWallPaper

阅读量:

上周我在微信公众号上推送了一篇题为《Android实现透明屏幕》的文章,并获得了广泛的关注和授权。这篇文章详细介绍了如何利用SurfaceHolder和MediaPlayer等API实现视频桌面效果,并分享了完整的代码实现过程。文章还提供了扩展功能示例,并附上了相关技术教程链接供读者参考学习。通过这篇文章的学习和实践,我对Android的视频播放与显示技术有了更深入的理解,并掌握了如何通过Service机制实现动态壁纸功能。


改写说明

欢迎大家扫描左侧二维码关注我的公众号,每天7点半推送优秀技术博文。

我对该软件有浓厚的兴趣,在一段时间内一直对其保持关注状态。然而,在最近的一段时间里,该平台频繁向我推送了一些与该功能相关的通知信息(即将视频作为桌面进行展示)。这让我对相关技术产生了一定好奇心理,在查看源代码时意外发现了SurfaceHolder组件的存在(即通过这一组件可实现视频展示的效果)。于是周末便着手进行了测试尝试(即尝试将视频播放到桌面上),结果发现其实操作起来非常简单(即这一功能实现起来相当便捷)。

因此本篇文章对Android 实现"透明屏幕"一文进行了深入学习与参考,在代码实现上也进行了部分优化与调整。

https://github.com/songixan/Wallpaper

效果图是这样的:

注:本文采用的小米5S型号手机作为测试设备,在不同环境下可能存在一定的兼容性问题。
我们正在尝试解决这一问题。
如需进一步讨论,请随时留言。

二、实现


(1) 配置相关

请先创建一个XML文件,并将其用于存储wallpaper的thumbnail、description和settingsActivity信息。为了简化说明,默认情况下我们目前只实现了thumbnail功能。

<wallpaper xmlns:android=“http://schemas.android.com/apk/res/android”

android:thumbnail=“@mipmap/ic_launcher” />

(2)编写代码

在屏幕上持续展示的Wallpaper背后其实是一个Service。为了实现这一目标,在此基础上需要继承自WallpaperService并负责实现核心功能模块onCreateEngine的具体逻辑。具体来说onCreateEngine将负责初始化必要的组件和服务资源,并确保整个 WallPaper系统能够稳定运行。

public class VideoLiveWallpaper extends WallpaperService {

public Engine onCreateEngine() {

return new VideoEngine();

}

//…

}

可以看出返回结果是一个名为Engine的特殊对象,在WallpaperService这个类中作为内部类存在。该引擎包括多个事件处理方法:如onSurfaceCreated用于表面创建时的操作、onSurfaceChanged用于表面变化时的处理逻辑以及onSurfaceDestroyed用于表面销毁时的动作;此外还有on.TouchEvent来响应触摸事件的发生。一想到这些事件处理方法的存在,“表面视图”的概念自然浮现在脑海里。“表面视图”是Android系统中一个重要的组件,在使用触摸屏设备时尤其常见。

此外,大家还记得在Android播放视频吗?

传统的方法主要依赖于VideoView。除此之外, 另一种实现方式是利用MediaPlayer与SurfaceView协同工作。例如今天的案例采用了类似的方式。

为了实现数据流的有效传输至Surface端点,建议采用MediaPlayer的技术来持续不断地输入经过解码的数据块。

class VideoEngine extends Engine {

private MediaPlayer mMediaPlayer;

@Override

public void onSurfaceCreated(SurfaceHolder holder) {

L.d("VideoEngine#onSurfaceCreated ");

super.onSurfaceCreated(holder);

mMediaPlayer = new MediaPlayer();

mMediaPlayer.setSurface(holder.getSurface());

try {

AssetManager assetMg = getApplicationContext().getAssets();

AssetFileDescriptor fileDescriptor = assetMg.openFd(“test1.mp4”);

mMediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),

fileDescriptor.getStartOffset(), fileDescriptor.getLength());

mMediaPlayer.setLooping(true);

mMediaPlayer.setVolume(0, 0);

mMediaPlayer.prepare();

mMediaPlayer.start();

} catch (IOException e) {

e.printStackTrace();

}

}

@Override

public void onVisibilityChanged(boolean visible) {

L.d("VideoEngine#onVisibilityChanged visible = " + visible);

if (visible) {

mMediaPlayer.start();

} else {

mMediaPlayer.pause();

}

}

@Override

public void onSurfaceDestroyed(SurfaceHolder holder) {

L.d("VideoEngine#onSurfaceDestroyed ");

super.onSurfaceDestroyed(holder);

mMediaPlayer.release();

mMediaPlayer = null;

}

代码极为简洁,在onSurfaceCreated事件中进行初始化mMediaPlayer。其核心实现方式即为调用setSurface方法。其中,默认采用了静音处理。

当桌面不可见时触发的事件函数 onVisibilityChanged 表示我们需要在不可见状态暂停播放,并等待桌面重新可见后再继续播放。

当onSurfaceDestroyed时释放资源~~

完成我们的VideoLiveWallpaper开发工作,请记住:该应用属于Service类型,请确保已注册。

<service

android:name=“.VideoLiveWallpaper”

Android:Label设置为(@String)/app_name)

android:permission=“android.permission.BIND_WALLPAPER”

android:process=“:wallpaper”>

<meta-data

android:name=“android.service.wallpaper”

android:resource=“@xml/livewallpaper” />

(3)设置为壁纸

完成注册后,在 MainActivity 中部署一个按钮功能用于设置为主屏幕图标。

public static void setToWallPaper(Context context) {

final Intent intent = new Intent(WallpaperManager.ACTIONCHANGE LIVELY WALLPAINTER);

intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,

new ComponentName(context, VideoLiveWallpaper.class));

context.startActivity(intent);

}

这样就完成了代码的初步编写啦~~

(4)增加一些参数的支持

上一次我们默认将视频桌面设置为静音状态,在某些情况下我们需要动态调整视频桌面的参数设置。常规做法是尝试使用settingsActivity进行配置。但我也觉得广播机制同样适用——基本上就是Service(尤其当其运行于独立进程中)与Activity之间的通信方式。

这里我们增加一个复选框,支持设置开启声音or关闭声音。

public static final String VIDEO_PARAMS_CONTROL_ACTION = "com.zhy.livewallpaper";

public static final String KEY_ACTION = “action”;

public static final int ACTION_VOICE_SILENCE = 110;

public static final int ACTION_VOICE_NORMAL = 111;

class VideoEngine extends Engine {

// 省略其他代码

private BroadcastReceiver mVideoParamsControlReceiver;

@Override

public void onCreate(SurfaceHolder surfaceHolder) {

super.onCreate(surfaceHolder);

该视频控制意图过滤器实例由指定参数初始化

注册函数registerReceiver被调用以实现将参数mVideoParamsControlReceiver初始化为新的广播接收器并开始监听指定的事件类型

@Override

public void onReceive(Context context, Intent intent) {

L.d(“onReceive”);

int action = intent.getIntExtra(KEY_ACTION, -1);

switch (action) {

case ACTION_VOICE_NORMAL:

mMediaPlayer.setVolume(1.0f, 1.0f);

break;

case ACTION_VOICE_SILENCE:

mMediaPlayer.setVolume(0, 0);

break;

}

}

}, intentFilter);

}

@Override

总结

在金融公司任职期间, 笔者并未表现出对技术的特别追求, 但个人对于技术创新始终保持较高的热情. 然而由于两者之间的不协调, 笔者并不太融洽, 因此不得不将主要目标锁定在互联网大厂这样的平台. 希望大家能够勇敢地去尝试实现自己的职业理想与创新理念.

觉得有收获的记得点赞,关注+收藏哦!你们的点赞就是我的动力!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
不入,只能把目标放在互联网大厂了。也希望大家都去敢于尝试和追逐自己的梦想!
BATJ大厂Android高频面试题

[外链图片转存中…(img-ZRb3Jbqd-1714407482609)]

[外链图片转存中…(img-Xy1034Do-1714407482611)]

[外链图片转存中…(img-7CaNz9ws-1714407482611)]

[外链图片转存中…(img-fgmI6yDb-1714407482612)]

觉得内容对您有帮助,请点个赞并关注订阅号以及星标公众号!您的支持是我创作的动力源泉!

觉得内容对您有帮助,请点个赞并关注订阅号以及星标公众号!您的支持是我创作的动力源泉!

《Android学习要点归纳 + 移动架构教学视频 + 大厂面试题解析 + 项目实战源码》 ,点击下方传送门 这里 即可获取!

全部评论 (0)

还没有任何评论哟~