動態桌布開發指南(一)概述介紹
一、概述
1.1 簡介
在Android中,桌布分為靜態與動態兩種。靜態桌布是一張圖片,而動態桌布則以動畫為表現形式,或者可以對使用者的操作作出反應。動態桌布實際上和其他應用是類似的,自Android 2.1開始支援。Android桌布執行在一個Android服務之中,這個服務的名字叫做WallpaperService。當用戶選擇了一個桌布之後,此桌布所對應的WallpaperService便會啟動並開始進行桌布的繪製工作。Engine是WallpaperService中的一個內部類,實現了桌布視窗的建立以及Surface的維護工作。
1.2 示例
簡單來說,動態桌布就是一個服務,動態桌布需要實現動態桌布的服務WallpaperService和描繪動態桌布的引擎WallpaperService.Engine。
元件類 | 說明 |
---|---|
WallpaperService | 實現動態桌布的服務程式 |
WallpaperService.Engine | 描繪動態桌布的引擎 |
下面以視訊動態桌布為例,講述一下具體實現流程。
(1) 首先定義一個類VideoWallpaper來繼承WallpaperService類並實現onCreateEngine()方法,在該方法中需要返回一個Engine例項。
public class VideoWallpaper extends WallpaperService { @Override public Engine onCreateEngine() { return null; } }
(2) 然後定義一個VideoEngine類來繼承Engine類並實現onSurfaceCreated() 、onSurfaceDestroyed()和onVisibilityChanged()方法。在onSurfaceCreated()方法中初始物件資源;在onSurfaceDestroyed()中去釋放和銷燬資源;在onVisibilityChanged()方法中去控制檢視是顯示和隱藏邏輯。以視訊桌布為例:
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; } }
(3) 對VideoWallPaper服務進行註冊,這裡在註冊時寫法和普通的Service相同。需要注意的是,WallPaperService需要一個"android.permission.BIND_WALLPAPER"的許可權,新增一個action為"android.service.wallpaper.WallpaperService",還需要一個名為"android.service.wallpaper"的meta-data。如下:
<service
android:label="@string/app_name"
android:permission="android.permission.BIND_WALLPAPER"
android:name=".VideoWallpaper">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/livewallpaper" />
</service>
(4) 上面的程式碼中meta-data中需要一個xml檔案源,所以還需要在res的xml資料夾(沒有就建立)下,建立一個名為wallpaper的xml檔案。xml檔案的根標籤為wallpaper,有一下三個屬性:
- description :動態桌布的文字描述
- thumbnail:動態桌布的圖片描述
- settingsActivity:動態桌布的設定介面
動態桌布的資源來源“/res/xml/liveWallpaper.xml”
<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/wallpaper_description"
android:settingsActivity="com.example.videowallpaper.SettingsActivity"
android:thumbnail="@mipmap/ic_launcher">
</wallpaper>
SettingsActivity程式碼示例如下:
public class SettingsActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.setting_layout);
}
}
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="video_param"
android:title="設定">
<CheckBoxPreference
android:defaultValue="true"
android:key="loop"
android:title="是否迴圈播放" />
<CheckBoxPreference
android:checked="false"
android:key="volume"
android:title="是否開啟聲音" />
</PreferenceScreen>
(5) 接下來就是啟動桌布服務了,這裡不能通過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();
}
其他需要注意的地方,比如可以通過WallpaperManager的getWallpaperInfo()方法來判斷當前桌布的服務是否已經在執行,從而可以通過廣播或者其他通知來直接修改桌布播放的視訊,避免每次更換一個視訊都需要走一次系統的預覽介面。也就是在設定裡面動態設定桌布引數。
上面只是簡單的示例程式碼,如果對視訊動態桌布感興趣,可以參考此專案VideoWallpaper
總結
以上就是實現一個基本動態桌布的流程,其實視訊動態桌布實現起來比較簡單,不需要開發者自己畫出複雜的介面,也沒有手勢互動邏輯。但是市面上的動態桌布大多比較複雜,而且基本上是使用繪圖API畫出來的,包括OpenGL等,在之後的文章裡會詳細介紹。