Android 仿火萤视频桌面 神奇的LiveWallPaper

来源:互联网 发布:阿里云测试培训 编辑:程序博客网 时间:2024/06/05 09:43

http://blog.csdn.net/lmj623565791/article/details/72170299
本文出自张鸿洋的博客

所以本篇文章无限感谢Android 实现”透明屏幕一文,代码也部分参考自其提供的透明相机。

https://github.com/songixan/Wallpaper    

这里我直接应用作者的GIF图

我用的测试机型是5.0 魅族note3 ,在AP 17 的模拟机上夜神直接崩了
二、实现
(1) 配置相关

首先编写一个xml文件,用于描述wallpaper的thumbnail、description、settingsActivity等,这里为了简单,仅设置了thumbnail。

在xml文件夹下添加wallpaper.xml 文件配置这个参数

<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的内部类,其内部包含onSurfaceCreated、onSurfaceChanged、onSurfaceDestroyed、onTouchEvent等方法,看到这些方法,立刻想到了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);}

Activity 中

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,这样一个简单的视频桌面就完成啦~~


参考

  1. http://www.vogella.com/tutorials/AndroidLiveWallpaper/article.html

  2. http://www.jianshu.com/u/befb61deec9c

不求下载求点赞呵呵
我上传的下载地址Demo