1. 程式人生 > >動態桌布開發指南(一)概述介紹

動態桌布開發指南(一)概述介紹

一、概述

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等,在之後的文章裡會詳細介紹。