视频壁纸属于动态壁纸,所以视频壁纸就可以用Android系统提供的动态壁纸服务来实现。首先先介绍一下在实现过程中会用到的几个类。

WallpaperManager

Android提供的用于管理壁纸的类,里面有几个方法在实现过程中需要用到

getInstance(context) 获取一个实例

clear() 清空所有的壁纸

getWallpaperInfo() 获取当前壁纸的信息

WallpaperService

Android系统提供的壁纸服务的抽象类,实现一个动态壁纸必须要继承该类并实现onCreateEngine()方法,该类的唯一功能就是返回绘制动态壁纸所需要的Engine实例。

WallpaperService.Engine

Engine是WallpaperService一个内部类,动态壁纸的所有显示过程的绘制都由该类完成,我们需要继承该类并实现以下三个方法:

onSurfaceCreated()

onSurfaceDestroyed()

onVisibilityChanged()

当然还有其他的如onCreate()和onDestroy()方法等等。

视频壁纸的实现过程

首先我们需要自定义一个类VideoWallPaperService来继承WallpaperService类并实现onCreateEngine()方法,在该方法中需要返回一个Engine实例。

public class VideoWallPaperService extends WallpaperService {

@Override

public Engine onCreateEngine() {

return new VideoEngine();

}

}

所以我们需要再VideoWallPaperService内部自定义一个VideoEngine类来继承Engine类并实现onSurfaceCreated() 、onSurfaceDestroyed()和onVisibilityChanged()方法。然后在onSurfaceCreated()方法中初始化一个MediaPlayer;在onSurfaceDestroyed()中去释放和销毁MediaPlayer;在onVisibilityChanged()方法中去切换MediaPlayer的播放和暂停。

private class VideoEngine extends Engine {

private MediaPlayer mPlayer;

@Override

public void onVisibilityChanged(boolean visible) {

if(visible) {

mPlayer.start();

} else {

mPlayer.pause();

}

}

@Override

public void onSurfaceCreated(SurfaceHolder holder) {

super.onSurfaceCreated(holder);

mPlayer = new MediaPlayer();

//不能使用setDisplay()方法

mPlayer.setSurface(holder.getSurface());

mPlayer.setDataSource(videoPath);

mPlayer.prepare();

mPlayer.start();

}

@Override

public void onSurfaceDestroyed(SurfaceHolder holder) {

super.onSurfaceDestroyed(holder);

if(mPlayer.isPlaying()) {

mPlayer.stop();

}

mPlayer.release();

mPlayer = null;

}

}

以上都完成后我们还需要对VideoWallPaperService进行注册,这里在注册时写法和普通的Service相同,其中VideoWallPaperService需要一个"android.permission.BIND_WALLPAPER"的权限,需要添加一个action为"android.service.wallpaper.WallpaperService"(固定写法),还需要一个名为"android.service.wallpaper"(固定写法)的meta-data。

android:name=".VideoWallPaperService"

android:permission="android.permission.BIND_WALLPAPER">

android:name="android.service.wallpaper"

android:resource="@xml/wallpaper" />

上面一步的代码中meta-data中需要一个xml文件源,所以我们需要再res的xml文件夹(没有就自己建)下创建一个名为wallpaper的xml文件。xml文件的根标签为wallpaper,有一下三个属性:

description 动态壁纸的文字描述

thumbnail 动态壁纸的图片描述

settingsActivity 动态壁纸的设置界面(会在预览界面出现)

android:description="@string/wallpaper_description"

android:settingsActivity="com.example.videowallpaper.SettingsActivity"

android:thumbnail="@mipmap/ic_launcher">

接下来就是启动壁纸服务了,这里我们不能通过context的startService()方法来启动壁纸服务,我们需要通过启动系统的预览界面来间接启动服务。

Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);

intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, new ComponentName(context, VideoWallPaperService.class));

context.startActivity(intent);

除了启动还需要关闭壁纸服务,我们可以通过WallpaperManager的clear()方法来关闭,也可以通过WallpaperService的clearWallpaper()(已经被标记过时)方法来关闭壁纸。

try {

WallpaperManager.getInstance(context).clear();

} catch(IOException e) {

e.printStackTrace();

}

其他需要注意的地方

设置壁纸需要"android.permission.SET_WALLPAPER"权限

播放本地视频需要"android.permission.READ_EXTERNAL_STORAGE"权限

VideoEngine的MediaPlayer的播放地址要使用持久化保存数据(数据库、Preference等),否则设置好视频壁纸后将手机关机再开机,就会出bug

WallpaperService的onCreateEngine()方法返回的Engine实例不能使用单例模式,必须每次都返回一个新的Engine实例

可以通过WallpaperManager的getWallpaperInfo()方法来判断当前自己的服务是否已经在运行,从而可以通过广播或者其他通知来直接修改壁纸播放的视频,从而避免每次更换一个视频都需要走一次系统的预览界面。

最后贴一下VideoWallPaperService的完整代码(仅供参考):

package com.example.videowallpaper;

import android.app.WallpaperInfo;

import android.app.WallpaperManager;

import android.content.BroadcastReceiver;

import android.content.ComponentName;

import android.content.Context;

import android.content.Intent;

import android.content.IntentFilter;

import android.content.SharedPreferences;

import android.media.MediaPlayer;

import android.preference.PreferenceManager;

import android.service.wallpaper.WallpaperService;

import android.text.TextUtils;

import android.view.SurfaceHolder;

import java.io.IOException;

public class VideoWallPaperService extends WallpaperService {

private static final String SERVICE_NAME = "com.example.videowallpaper.VideoWallPaperService";

@Override

public Engine onCreateEngine() {

return new VideoEngine();

}

public static void startWallPaper(Context context, String videoPath) {

WallpaperInfo info = WallpaperManager.getInstance(context).getWallpaperInfo();

if(info != null && SERVICE_NAME.equals(info.getServiceName())) {

changeVideo(context, videoPath);

} else {

startNewWallpaper(context, videoPath);

}

}

public static void closeWallpaper(Context context) {

try {

WallpaperManager.getInstance(context).clear();

} catch(IOException e) {

e.printStackTrace();

}

}

private static void startNewWallpaper(Context context, String path) {

saveVideoPath(context, path);

Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);

intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, new ComponentName(context, VideoWallPaperService.class));

context.startActivity(intent);

}

private static void changeVideo(Context context, String path) {

saveVideoPath(context, path);

Intent intent = new Intent();

intent.setAction(Constant.ACTION);

intent.putExtra(Constant.BROADCAST_SET_VIDEO_PARAM, Constant.ACTION_SET_VIDEO);

context.sendBroadcast(intent);

}

public static void setVolume(Context context, boolean hasVolume) {

Intent intent = new Intent();

intent.setAction(Constant.ACTION);

if(hasVolume) {

intent.putExtra(Constant.BROADCAST_SET_VIDEO_PARAM, Constant.ACTION_VOICE_NORMAL);

} else {

intent.putExtra(Constant.BROADCAST_SET_VIDEO_PARAM, Constant.ACTION_VOICE_SILENCE);

}

context.sendBroadcast(intent);

}

private static void saveVideoPath(Context context, String path) {

SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();

editor.putString(Constant.VIDEO_PATH, path);

editor.apply();

}

private String getVideoPath() {

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);

return preferences.getString(Constant.VIDEO_PATH, null);

}

private class VideoEngine extends Engine implements MediaPlayer.OnPreparedListener,

MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {

private MediaPlayer mPlayer;

private boolean mLoop;

private boolean mVolume;

private boolean isPapered = false;

private VideoEngine() {

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(VideoWallPaperService.this);

mLoop = preferences.getBoolean("loop", true);

mVolume = preferences.getBoolean("volume", false);

}

private BroadcastReceiver mReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

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

switch(action) {

case Constant.ACTION_SET_VIDEO: {

setVideo(getVideoPath());

break;

}

case Constant.ACTION_VOICE_NORMAL: {

mVolume = true;

setVolume();

break;

}

case Constant.ACTION_VOICE_SILENCE: {

mVolume = false;

setVolume();

break;

}

}

}

};

@Override

public void onCreate(SurfaceHolder surfaceHolder) {

super.onCreate(surfaceHolder);

IntentFilter filter = new IntentFilter();

filter.addAction(Constant.ACTION);

registerReceiver(mReceiver, filter);

}

@Override

public void onDestroy() {

super.onDestroy();

unregisterReceiver(mReceiver);

}

@Override

public void onVisibilityChanged(boolean visible) {

if(isPapered) {

if(visible) {

mPlayer.start();

} else {

mPlayer.pause();

}

}

}

@Override

public void onSurfaceCreated(SurfaceHolder holder) {

super.onSurfaceCreated(holder);

mPlayer = new MediaPlayer();

setVideo(getVideoPath());

}

@Override

public void onSurfaceDestroyed(SurfaceHolder holder) {

super.onSurfaceDestroyed(holder);

if(mPlayer.isPlaying()) {

mPlayer.stop();

}

mPlayer.release();

mPlayer = null;

}

@Override

public void onPrepared(MediaPlayer mp) {

isPapered = true;

mp.start();

}

@Override

public void onCompletion(MediaPlayer mp) {

closeWallpaper(getApplicationContext());

}

@Override

public boolean onError(MediaPlayer mp, int what, int extra) {

closeWallpaper(getApplicationContext());

return true;

}

private void setVideo(String videoPath) {

if(TextUtils.isEmpty(videoPath)) {

closeWallpaper(getApplicationContext());

throw new IllegalArgumentException("video path is null");

}

if(mPlayer != null) {

mPlayer.reset();

isPapered = false;

try {

mPlayer.setOnPreparedListener(this);

mPlayer.setOnCompletionListener(this);

mPlayer.setOnErrorListener(this);

mPlayer.setLooping(mLoop);

// mPlayer.setDisplay(getSurfaceHolder());

mPlayer.setSurface(getSurfaceHolder().getSurface());

setVolume();

mPlayer.setDataSource(videoPath);

mPlayer.prepareAsync();

} catch(IOException e) {

e.printStackTrace();

}

}

}

private void setVolume() {

if(mPlayer != null) {

if(mVolume) {

mPlayer.setVolume(1.0f, 1.0f);

} else {

mPlayer.setVolume(0f, 0f);

}

}

}

}

}

还有一个SettingsActivity的代码也贴出来吧

这里说明一下推荐使用PreferenceFragment来代替PreferenceActivity

package com.example.videowallpaper;

import android.os.Bundle;

import android.preference.PreferenceActivity;

public class SettingsActivity extends PreferenceActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

addPreferencesFromResource(R.xml.setting_layout);

}

}

setting_layout

android:key="video_param"

android:title="设置">

android:defaultValue="true"

android:key="loop"

android:title="是否循环播放" />

android:checked="false"

android:key="volume"

android:title="是否开启声音" />

Constant.java(自定义的一些常量)

public class Constant {

public static final String BROADCAST_SET_VIDEO_PARAM = "broadcast_set_video_param";

public static final String ACTION = "action";

public static final String VIDEO_PATH = "action_video_path";

public static final int ACTION_SET_VIDEO = 0x101;

public static final int ACTION_VOICE_SILENCE = 0x102;

public static final int ACTION_VOICE_NORMAL = 0x103;

}

android视频壁纸源码,Android视频壁纸的实现相关推荐

  1. 一对一视频直播源码|手机视频直播平台android源码/可打包视频直播

    源码介绍 一对一视频直播源码|手机视频直播平台android源码集视频.语音.动态.直播.社交等功能于一身. 前端功能说明: 登入注册:手机验证码登入.编辑个人信息.上传头像 首页直播:查看主播用户. ...

  2. 短视频seo源码 短视频seo矩阵系统源码私有化部署

    短视频seo源码 短视频seo矩阵系统源码私有化部署 短视频seo源码 短视频seo矩阵系统源码私有化怎么部署? 首先我们来给大家普及一下什么是短视频seo矩阵系统?视频矩阵分为多平台矩阵与一个平台多 ...

  3. android 手机壁纸源码,Android设置手机壁纸-源码(WallPaper)

    Android设置手机壁纸-源码(WallPaper) /** * Andorid设置手机屏幕的壁纸 * * @description: * @author ldm * @date 2016-5-4 ...

  4. android 滑动接听源码,android仿摩拜单车APP、炫酷RecyclerView、卡片滑动、仿饿了么点餐、自定义索引等源码...

    Android精选源码 Android优质博客 前言permissions4m 最初的设计是仅仅做成一个编译器注解框架,在1.0.0版本时,它纯粹地实现了原生 Android 请求流程,关于它的设计思 ...

  5. android studio im源码,Android Studio 导入 AOSP 源码

    有了 AOSP 源码,接下来就是如何看了,可以直接文本看,可以用 Source Insight,我当然选择 Android Studio,Android Studio 是我熟悉且十分强大的工具.问题来 ...

  6. Android 12系统源码_系统壁纸(一)系统壁纸的原理分析

    前言 在Android中,壁纸分为静态与动态两种.静态壁纸是一张图片,而动态壁纸则以动画为表现形式,或者可以对用户的操作作出反应.这两种形式看似差异很大,其实二者的本质是统一的.它们都以一个Servi ...

  7. Android 12系统源码_系统壁纸(二)动态壁纸的设置流程

    在Android中,壁纸分为静态与动态两种.静态壁纸是一张图片,而动态壁纸则以动画为表现形式,或者可以对用户的操作作出反应.这两种形式看似差异很大,其实二者的本质是统一的.它们都以一个Service的 ...

  8. 仿抖音短视频APP源码android布局悬停顶部效果

    实现: 1.导入design库 implementation 'com.android.support:design:28.0.0' 2.布局 <android.support.design.w ...

  9. android 自定义相机源码,Android 自定义相机及分析源码

    Android 自定义相机及分析源码 使用Android 系统相机的方法: 要想让应用有相机的action,咱们就必须在清单文件中做一些声明,好让系统知道,如下 action的作用就是声明action ...

最新文章

  1. listview改变选中行字体颜色
  2. HTML5中使用SpeechSynthesisAPI实现语音合成
  3. php判断是否为数字_PHP将英文数字转换为阿拉伯数字
  4. beego2---入门
  5. STM8单片机ADC带缓存的连续采样模式
  6. python读取图片路径f.read()转化为bytes类型
  7. 怎么用简单的方法压缩手机图片
  8. TreeView 右键菜单
  9. windows10常见故障排查
  10. 英语发音规则---P字母
  11. 小米手机qq不读取相册照片_【qq影像读取不了照片】qq影像读取不到相册_qq影像读取不了相册...
  12. 一个玩游戏的失足青年,转行做软件开发的挣扎过程(1)
  13. 【POJ 2484】A Funny Game(对称博弈)
  14. element-ui弹出层置于遮罩层下面问题
  15. 荐书|《DBT技巧训练手册》:宝贝,你就是你活着的原因
  16. [HDU1004] Let the balloon rise - 让气球升起来
  17. 怎么删除w7桌面计算机图标,桌面图标删除不了_Win7桌面有图标删不掉怎么办
  18. 学习笔记:C语言程序设计
  19. 序列自相关矩阵的计算和分析
  20. python可以用于dsp吗,Python DSP,自动增益控制(AGC)

热门文章

  1. 浏览器访问Linux的Tomcat
  2. 剑指Offe面试题:用两个栈实现队列
  3. 7.17正则表达式与re模块
  4. shineblink LD3320A语音识别
  5. 常见品牌的手机型号所代表的含义
  6. 【Devc++】战斗1.0.2
  7. 概率论与数理统计--笔记
  8. 【论文总结】Incremental Learning of Object Detectors without Catastrophic Forgetting(附翻译)
  9. android 获取设备的mac地址,Android编程获取设备MAC地址的实现方法
  10. 图像处理那张熟悉的面孔——Lena