Android 仿火螢視頻案頭 神奇的LiveWallPaper

來源:互聯網
上載者:User

標籤:tar   des   ref   bind   return   water   mis   XML   聯絡   

本文已在我的公眾號hongyangAndroid原創首發。
轉載請標明出處:
http://blog.csdn.net/lmj623565791/article/details/72170299
本文出自張鴻洋的部落格

一、概述

上周我的公眾號推送了一篇Android 實現”透明螢幕,當時我看到之後就覺得特別感興趣,也立即聯絡作者要了授權~~

歡迎大家掃描左側二維碼關注我的公眾號,每天7點半推送優秀技術博文。

感興趣的原因是,我是內涵段子的資深使用者,前段時間基本被一款叫火螢視頻案頭的軟體(就是將視頻作為案頭)給刷屏了,所以看了下作者的代碼,看到了SurfaceHolder,立刻想到了,肯定可以用來播放視頻實現視頻案頭的效果,於是周末嘗試了下,果然很簡單。

所以本篇文章無限感謝Android 實現”透明螢幕一文,代碼也部分參考自其提供的透明相機。

https://github.com/songixan/Wallpaper

是這樣的:

註:本文的測試機為小米5s ,可能不同手機會有一些相容性問題,嘗試解決下,歡迎留言。

二、實現(1) 配置相關

首先編寫一個xml檔案,用於描述wallpaper的thumbnaildescriptionsettingsActivity等,這裡為了簡單,僅設定了thumbnail。

<?xml version="1.0" encoding="utf-8"?><wallpaper xmlns:android="http://schemas.android.com/apk/res/android"    android:thumbnail="@mipmap/ic_launcher" />
(2)編寫代碼

Wallpaper需要在螢幕上一直顯示,其背後其實是一個Service,所以實現一個Wallpaper需要繼承自WallpaperService,實現其抽象方法onCreateEngine,如下:

public class VideoLiveWallpaper extends WallpaperService {    public Engine onCreateEngine() {        return new VideoEngine();    }    //...}   

可以看到傳回值是一個Engine,Engine為WallpaperService的內部類,其內部包含onSurfaceCreatedonSurfaceChangedonSurfaceDestroyedonTouchEvent等方法,看到這些方法,立刻想到了SurfaceView,關於SurfaceView相關知識可以參考:

  • Android SurfaceView實戰 打造抽獎轉盤

此外,大家還記得在Android播放視頻嗎?

常規的做法有通過VideoView,除此以外還有通過MediaPlayer配合SurfaceView配合來實現,今天這個例子類似後者。

我們只需要通過MediaPlayer將解碼的資料不斷的輸送到傳入的Surface中即可。

class VideoEngine extends Engine {    private MediaPlayer mMediaPlayer;    @Override    public void onSurfaceCreated(SurfaceHolder holder) {        L.d("VideoEngine#onSurfaceCreated ");        super.onSurfaceCreated(holder);        mMediaPlayer = new MediaPlayer();        mMediaPlayer.setSurface(holder.getSurface());        try {            AssetManager assetMg = getApplicationContext().getAssets();            AssetFileDescriptor fileDescriptor = assetMg.openFd("test1.mp4");            mMediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),                    fileDescriptor.getStartOffset(), fileDescriptor.getLength());            mMediaPlayer.setLooping(true);            mMediaPlayer.setVolume(0, 0);            mMediaPlayer.prepare();            mMediaPlayer.start();        } catch (IOException e) {            e.printStackTrace();        }    }     @Override    public void onVisibilityChanged(boolean visible) {        L.d("VideoEngine#onVisibilityChanged visible = " + visible);        if (visible) {            mMediaPlayer.start();        } else {            mMediaPlayer.pause();        }    }    @Override    public void onSurfaceDestroyed(SurfaceHolder holder) {        L.d("VideoEngine#onSurfaceDestroyed ");        super.onSurfaceDestroyed(holder);        mMediaPlayer.release();        mMediaPlayer = null;    }

代碼非常簡單,在onSurfaceCreated中去初始化mMediaPlayer,核心代碼即為設定setSurface方法,這裡我預設設定了靜音。

onVisibilityChanged,即當案頭不可見時,我們要暫停播放,等回到案頭繼續。

當onSurfaceDestroyed時釋放資源~~

這樣我們的VideoLiveWallpaper就寫好了,別忘了他是個Service,需要我們去註冊。

<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/livewallpaper" /></service>
(3)設定為壁紙

註冊完成後,我們在MainActivity中添加一個按鈕點擊設定為案頭背景,調用代碼如下

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);}

這樣就完成了代碼的初步編寫啦~~

(4)增加一些參數的支援

剛才我們設定了預設是靜音,可能有時候我們會希望能夠動態去控制視頻案頭的參數,正常應該嘗試去使用settingsActivity,不過我覺得其實廣播也挺合適的,無非就是Service(可能在獨立的進程)和Activity等通訊嘛~~

這裡我們增加一個複選框,支援設定開啟聲音or關閉聲音。

public static final String VIDEO_PARAMS_CONTROL_ACTION = "com.zhy.livewallpaper";public static final String KEY_ACTION = "action";public static final int ACTION_VOICE_SILENCE = 110;public static final int ACTION_VOICE_NORMAL = 111;class VideoEngine extends Engine {    // 省略其他代碼    private BroadcastReceiver mVideoParamsControlReceiver;    @Override    public void onCreate(SurfaceHolder surfaceHolder) {        super.onCreate(surfaceHolder);        IntentFilter intentFilter = new IntentFilter(VIDEO_PARAMS_CONTROL_ACTION);        registerReceiver(mVideoParamsControlReceiver = new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                L.d("onReceive");                int action = intent.getIntExtra(KEY_ACTION, -1);                switch (action) {                    case ACTION_VOICE_NORMAL:                        mMediaPlayer.setVolume(1.0f, 1.0f);                        break;                    case ACTION_VOICE_SILENCE:                        mMediaPlayer.setVolume(0, 0);                        break;                }            }        }, intentFilter);    }    @Override    public void onDestroy() {        unregisterReceiver(mVideoParamsControlReceiver);        super.onDestroy();    }}

Engine還有onCreate和onDestroy聲明周期方法,可以在onCreate中註冊動態廣播,當接受到發送的action為ACTION_VOICE_NORMAL則開啟聲音;接收到發送的ACTION_VOICE_SILENCE則為靜音狀態。

最後直接在VideoLiveWallpaper中添加兩個靜態方法用於發送廣播即可:

public static void voiceSilence(Context context) {    Intent intent = new Intent(VideoLiveWallpaper.VIDEO_PARAMS_CONTROL_ACTION);    intent.putExtra(VideoLiveWallpaper.KEY_ACTION, VideoLiveWallpaper.ACTION_VOICE_SILENCE);    context.sendBroadcast(intent);}public static void voiceNormal(Context context) {    Intent intent = new Intent(VideoLiveWallpaper.VIDEO_PARAMS_CONTROL_ACTION);    intent.putExtra(VideoLiveWallpaper.KEY_ACTION, VideoLiveWallpaper.ACTION_VOICE_NORMAL);    context.sendBroadcast(intent);}

在Actiivty中:

public class MainActivity extends AppCompatActivity {    private CheckBox mCbVoice;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mCbVoice = (CheckBox) findViewById(R.id.id_cb_voice);        mCbVoice.setOnCheckedChangeListener(                new CompoundButton.OnCheckedChangeListener() {                    @Override                    public void onCheckedChanged(                            CompoundButton buttonView, boolean isChecked) {                        if (isChecked) {                            // 靜音                            VideoLiveWallpaper.voiceSilence(getApplicationContext());                        } else {                            VideoLiveWallpaper.voiceNormal(getApplicationContext());                        }                    }                });    }}

監聽一下CheckBox狀態,發送廣播即可。

ok,這樣一個簡單的視頻案頭就完成啦~~

源碼地址:

  • https://github.com/WanAndroid/LiveWallPaper/tree/master/hongyang/MagicWallPaper

直接將這個目錄以項目形式匯入。

支援我的話可以關注下我的公眾號,每天都會推送新知識~

歡迎關注我的公眾號:hongyangAndroid
(可以給我留言你想學習的文章,支援投稿)

參考
  • http://www.vogella.com/tutorials/AndroidLiveWallpaper/article.html
  • http://www.jianshu.com/u/befb61deec9c

Android 仿火螢視頻案頭 神奇的LiveWallPaper

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.