Android動態桌布解析

anita-austvika-1132037-unsplash.jpg
最近搞了一下Android的動態桌布,像實現“螢火視訊桌面”那樣,本來以為很難的,但是瞭解了一下感覺還是很容易的。
效果圖: ofollow,noindex">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自己畫東西都可以,道理都是一樣的