视频壁纸属于动态壁纸,所以视频壁纸就可以用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开发学习之WallPaper设置壁纸详细介绍与实例

    今天和大家分享的是关于在android中设置壁纸的方法,在android中设置壁纸的方法有三种,分别是: 1.使用wallpapermanager的setresource(int resourceid ...

  2. android cne服务,android 自带APP 作用

    AntHalService.apk                 就是天线接口,用来连接天线的. ApplicationsProvider.apk            应用程序支持服务,主要用于同 ...

  3. 动态壁纸安卓_酷玩软件第7期:还在用无声的动态壁纸?短视频壁纸软件(Win+安卓版本)...

    最近在刷某视频平台的时候,看到下面这个视频很喜欢,然后我就想能不能把这个视频设置成手机壁纸呢?还带声音那种. 今天终于找到一款叫做"飞火动态壁纸"的软件(包括安卓版和Win版本). ...

  4. android 闹钟服务,android开发笔记之 AlarmManager(闹钟服务)

    手机闹钟服务AlarmManager AlarmManager通常用来开发手机闹钟,并且它是一个全局定时器,可在指定时间或指定周期启动其他组件(包括Activity,Service,Broadcast ...

  5. 安卓壁纸服务(动态壁纸)使用与源码分析

    概览 安卓的动态壁纸可以归属到SystemUI中,是SystemUI管理的一部分,安卓支持静态壁纸,同时也支持动态壁纸(added in API level 7 ) 用户可以从设备的内部或者是外部存储 ...

  6. android 打印机服务,Android系统打印服务插件printservice开发

    一 简介 从Android4.4开始,系统加入了打印相关的API,可以通过系统打印服务实现打印.对于需要使用打印功能的APP可参考官方教程接入打印服务. 这不是本文的内容,本文介绍打印机厂商如何使自己 ...

  7. android socket 服务,android 创建socket 通信型service

    仿照instaled写的 1.声明   在system/core/rootdir/init.rc中添加: service testlang /system/bin/testlang #       名 ...

  8. android 手电筒服务,Android手电筒案例

    最近在学习Android的开发,写了个手电筒的案例,分享一下!//Activity.xml package com.fq.flashlight; import android.app.Activity ...

  9. android 剪贴板服务,Android剪贴板用法详解

    本文实例详述了Android剪贴板的用法,分享给大家供大家参考.具体方法分析如下: 这里首先需要注意的一点,就是在使用Android剪贴板的时候大家只记住一点就行了,不管是安卓设备还是PC机,复制粘贴 ...

最新文章

  1. Android异步处理三:Handler+Looper+MessageQueue深入详解
  2. Building Fire Stations 39届亚洲赛牡丹江站B题
  3. java 数组json_如何在Java中创建JSON数组
  4. Jsoup实现Iteye自动登录
  5. P4213 【模板】杜教筛
  6. AFN框架和SDWebImage框架的上手体验
  7. Paw 百度ai_直面落地!百度EasyDL产业智能创新大赛成果覆盖能源、交通、水利民生重业...
  8. 机器学习笔记(七):神经网络:表示
  9. php调用文章标题,zblogphp标题格式的标签调用详细说明
  10. VUe3 @cli(axios)跨域访问
  11. 分布式资本合伙人孙铭:分布式存储是未来趋势,非短期炒作
  12. centos6下yslow部署
  13. mac 生成公钥和私钥
  14. 使用Python的pandas库操作Excel
  15. 初赛知识点汇总(阶段性完结
  16. 最新二开版本的源码博客论坛源码,UI很漂亮。
  17. 微信小程序中实现吸顶效果(流畅、不卡顿)
  18. 《出版专业基础》2015年版(初级)思考与练习 第六章
  19. 【Javaweb】【答卷】萌狼蓝天大二上学期期末Javaweb考试复习卷(一)
  20. php生成二维码海报

热门文章

  1. 获取中国各省份的名称以及该省份中的市及该市中的区
  2. Ubuntu下安装国际版qq
  3. CentOS下网页百度网盘下载资料
  4. LeetCode--剑指offer 1137题 第 N 个泰波那契数
  5. Android SurfaceFlinger中Fence机制--个人理解整理
  6. 讲述30岁处男的悲惨经历
  7. Python输出简洁美观的文本化表格
  8. IOS版微信新功能!朋友圈评论支持表情包
  9. matlab可以仿真开关电源吗,开关电源系统可以用()软件进行仿真。A、AnsysB、MatlabC、ProtelD、AutoCAD...
  10. windows环境安装BehaviorTree.CPP【基于vscode】