Android動態壁紙解析

anita-austvika-1132037-unsplash.jpg

最近搞了一下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自己畫東西都可以,道理都是一樣的

服務器掛了,可以看看本地壁紙

項目地址:https://github.com/tyhjh/liveWallpaper

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容