Android仿抖音實現(xiàn)動態(tài)壁紙

一灿里、概述:

壁紙運行在一個Android服務之中凿叠,這個服務的名字叫做WallpaperService厘擂。當用戶選擇了一個壁紙之后昆淡,此壁紙所對應的WallpaperService便會啟動并開始進行壁紙的繪制工作。
  
  EngineWallpaperService中的一個內(nèi)部類刽严,實現(xiàn)了壁紙窗口的創(chuàng)建以及Surface的維護工作昂灵。Engine內(nèi)部實現(xiàn)了SurfaceView,我們只需要在其內(nèi)部利用MediaPlayer + SurfaceView就可以播放動態(tài)壁紙了舞萄。

二眨补、實現(xiàn):

WallpaperService需要一個xml去配置,然后在AndroidManifest.xml中聲明

<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
    android:thumbnail="@mipmap/icon_lacation_black___cm">
</wallpaper>

繼承WallpaperService實現(xiàn)我們自己的壁紙服務VideoLiveWallpaper

public class VideoLiveWallpaper extends WallpaperService {


    @Override
    public Engine onCreateEngine() {
        return new VideoEngine();
    }

    class VideoEngine extends Engine {
        private MediaPlayer mMediaPlayer;

        @Override
        public void onCreate(SurfaceHolder surfaceHolder) {
            super.onCreate(surfaceHolder);

        }

        @Override
        public void onDestroy() {
            super.onDestroy();

        }

        @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
            super.onSurfaceCreated(holder);
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setSurface(holder.getSurface());
            try {
                mMediaPlayer.setDataSource(new File(FileUtil.getDCIMCameraDir(), "hlj_wallpaper").getAbsolutePath());
                mMediaPlayer.setLooping(true);
                mMediaPlayer.setVolume(0, 0);
                mMediaPlayer.prepare();
                mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mp) {
                        mMediaPlayer.start();
                    }
                });

            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            super.onSurfaceDestroyed(holder);
            mMediaPlayer.release();
            mMediaPlayer = null;
        }

        @Override
        public void onVisibilityChanged(boolean visible) {
            if (visible) {
                mMediaPlayer.start();
            } else {
                mMediaPlayer.pause();
            }
        }
    }
}

接著聲明這個服務同時聲明我們上面寫的xml配置

 <service
            android:name=".VideoLiveWallpaper"
            android:label="@string/app_name"
            android:permission="android.permission.BIND_WALLPAPER"
            android:process=":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/wallpaper" />
        </service>

重點在onSurfaceCreated方法中倒脓,這里為了可以動態(tài)切換不同的壁紙撑螺,我是指定去加載一個固定目錄下的視頻文件,然后不斷的復制新文件到這個目錄崎弃,因為一旦開啟切換壁紙這個方法就會調(diào)用甘晤,所以當調(diào)用后再動態(tài)通知去更改路徑不起作用。

所以我在更換壁紙前先清空

 try {
                                WallpaperManager.getInstance(getContext())
                                        .clear();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }

再去復制需要替換的壁紙到指定目錄

 copyFile(file.getAbsolutePath(),
                                    new File(FileUtil.getDCIMCameraDir(),
                                            "hlj_wallpaper").getAbsolutePath());
  /**
     * 復制單個文件
     *
     * @param oldPath String 原文件路徑 如:c:/fqf.txt
     * @param newPath String 復制后路徑 如:f:/fqf.txt
     * @return boolean
     */
    public void copyFile(final String oldPath, final String newPath) {
        progressBar.setVisibility(View.VISIBLE);
        Observable.create(new Observable.OnSubscribe<Boolean>() {
            @Override
            public void call(Subscriber<? super Boolean> subscriber) {
                try {
                    int byteSum = 0;
                    int byteRead ;
                    File oldFile = new File(oldPath);
                    if (oldFile.exists()) { //文件存在時
                        InputStream inStream = new FileInputStream(oldPath); //讀入原文件
                        FileOutputStream fs = new FileOutputStream(newPath);
                        byte[] buffer = new byte[1444];
                        while ((byteRead = inStream.read(buffer)) != -1) {
                            byteSum += byteRead; //字節(jié)數(shù) 文件大小
                            System.out.println(byteSum);
                            fs.write(buffer, 0, byteRead);
                        }
                        inStream.close();
                        subscriber.onNext(true);
                        subscriber.onCompleted();
                    }
                } catch (Exception e) {
                    System.out.println("復制單個文件操作出錯");
                    e.printStackTrace();
                    subscriber.onCompleted();
                }
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Boolean>() {
                    @Override
                    public void onCompleted() {
                        progressBar.setVisibility(View.GONE);

                    }

                    @Override
                    public void onError(Throwable e) {
                        progressBar.setVisibility(View.GONE);

                    }

                    @Override
                    public void onNext(Boolean aBoolean) {
                        progressBar.setVisibility(View.GONE);
                        setToWallPaper(getContext());

                    }
                });


    }

setToWallPaper方法就是真正的開啟設置壁紙操作了

  public static void setToWallPaper(Context context) {
        final Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
        intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
                new ComponentName(context, VideoLiveWallpaper.class));
        context.startActivity(intent);
    }

至此饲做,一個簡單的動態(tài)壁紙就搞定了线婚。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盆均,隨后出現(xiàn)的幾起案子塞弊,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件游沿,死亡現(xiàn)場離奇詭異饰抒,居然都是意外死亡,警方通過查閱死者的電腦和手機奏候,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門循集,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蔗草,你說我怎么就攤上這事咒彤。” “怎么了咒精?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵镶柱,是天一觀的道長。 經(jīng)常有香客問我模叙,道長歇拆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任范咨,我火速辦了婚禮故觅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渠啊。我一直安慰自己输吏,他們只是感情好,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布替蛉。 她就那樣靜靜地躺著贯溅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪躲查。 梳的紋絲不亂的頭發(fā)上它浅,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音镣煮,去河邊找鬼姐霍。 笑死,一個胖子當著我的面吹牛典唇,可吹牛的內(nèi)容都是我干的邮弹。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼蚓聘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盟劫?” 一聲冷哼從身側(cè)響起夜牡,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后塘装,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體急迂,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年蹦肴,在試婚紗的時候發(fā)現(xiàn)自己被綠了僚碎。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡阴幌,死狀恐怖勺阐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情矛双,我是刑警寧澤渊抽,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站议忽,受9級特大地震影響懒闷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜栈幸,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一愤估、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧速址,春花似錦玩焰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至闹炉,卻和暖如春蒿赢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背渣触。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工羡棵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嗅钻。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓皂冰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親养篓。 傳聞我的和親對象是個殘疾皇子秃流,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容