最近搞了一下Android的動態壁紙,像實現“螢火視頻桌面”那樣,本來以為很難的,但是了解了一下感覺還是很容易的。
效果圖:http://lc-fgtnb2h8.cn-n1.lcfile.com/82f4e474384b28b5739a.gif
Android壁紙的實現和管理分為三層:
只想了解動態壁紙的看第一個就好了
WallpaperService與Engine
壁紙運行在一個Android服務之中,這個服務的名字叫做WallpaperService。當用戶選擇了一個壁紙之后,此壁紙所對應的WallpaperService便會啟動并開始進行壁紙的繪制工作。Engine是WallpaperService中的一個內部類,實現了壁紙窗口的創建以及Surface的維護工作。這一層次的內容主要體現了壁紙的實現原理。
WallpaperManagerService
這個系統服務用于管理壁紙的運行與切換,并通過WallpaperManager類向外界提供操作壁紙的接口。這一層次主要體現了Android對壁紙的管理方式。
WindowManagerService
用于計算壁紙窗口的Z序、可見性以及為壁紙應用窗口動畫。這一層次主要體現了Android對壁紙窗口的管理方式。
實現
首先靜態壁紙是很簡單的,大概就是如下幾種方法,我也沒有試過,
- 使用WallpaperManager的setResource(int ResourceID)方法
- 使用WallpaperManager的setBitmap(Bitmap bitmap)方法
- 使用WallpaperManager的setStream(InputStream data)方法
//需要權限
<uses-permission android:name = "android.permission.SET_WALLPAPER"/>
WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
try {
wallpaperManager.setResource(R.drawable.picture);
} catch (IOException e) {
e.printStackTrace();
}
動態壁紙
剛才講了,動態壁紙就是一個服務,我們先創建一個服務并繼承WallpaperService。這個服務里面有個內部類Engine,實現了壁紙窗口的創建以及Surface的維護工作。就是說我們可以獲取到一個SurfaceHolder,拿到這個東西就好辦了,我們可以在上面畫自己想要的東西或者把視頻輸出到上面去。
我就直接上代碼了
設置視頻桌面
public class VideoWallpaper extends WallpaperService {
private MediaPlayer mp;
private int progress = 0;
//這里就是返回我們自定義的Engine
@Override
public Engine onCreateEngine() {
return new VideoEngine();
}
//自定義Engine
class VideoEngine extends Engine {
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
//可以設置點擊事件
setTouchEventsEnabled(true);
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
//把視頻輸出到SurfaceHolder上面
if (mp != null && mp.isPlaying())
return;
//可以設置SD卡的視頻
mp = MediaPlayer.create(getApplicationContext(), R.raw.bird);
//這句話并不簡單
mp.setSurface(holder.getSurface());
//重復播放
mp.setLooping(true);
mp.start();
}
//當桌面不可見的時候的處理
@Override
public void onVisibilityChanged(boolean visible) {
if (visible) {
if (mp != null)
return;
mp = MediaPlayer.create(getApplicationContext(), R.raw.bird);
mp.setSurface(getSurfaceHolder().getSurface());
mp.setLooping(true);
//獲取進度播放
mp.seekTo(progress);
mp.start();
} else {
if (mp != null && mp.isPlaying()) {
//保存進度
progress = mp.getCurrentPosition();
mp.stop();
mp.release();
mp = null;
}
}
}
@Override
public void onDestroy() {
if (mp != null) {
mp.stop();
mp.release();
}
super.onDestroy();
}
}
}
上面的代碼并不復雜,只是自己做的時候會遇到一些問題,首在不能在Engine的onCreate的方法里面設置視頻播放,應該是SurfaceHolder還沒有創建吧,還有mediaPlayer設置輸出的Surface
//正確設置代碼
mediaPlayer.setSurface(holder.getSurface());
//一般是這樣設置,這里這樣設置報錯
mediaPlayer.setDisplay(holder);
是Service那肯定要注冊的
<service
android:name="ui.service.VideoWallpaper"
android:permission="android.permission.BIND_WALLPAPER">
<!-- 為動態壁紙配置intent-filter -->
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<!-- 為動態壁紙配置meta-data -->
<meta-data
android:name="android.service.wallpaper"
android:resource="@xml/livewallpapervideo" />
</service>
然后關于"livewallpapervideo.xml",就是一個正常的布局文件
<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
android:settingsActivity="ui.activity.LiveWallPreference"
android:thumbnail="@mipmap/ic_video"
android:description="@string/wallpaper_description4"
/>
里面有個settingsActivity,這個東西我不知道有什么用,就是隨便一個Activity,你也要注冊這個Activity,
其他玩法
除了將視頻作為壁紙以為還可以將GIF作為壁紙,將攝像頭獲取到的圖象作為壁紙,甚至直接自己在SurfaceHolder自己畫東西都可以,道理都是一樣的
服務器掛了,可以看看本地壁紙