一灿里、概述:
壁紙運行在一個Android
服務之中凿叠,這個服務的名字叫做WallpaperService
厘擂。當用戶選擇了一個壁紙之后昆淡,此壁紙所對應的WallpaperService
便會啟動并開始進行壁紙的繪制工作。
Engine
是WallpaperService
中的一個內(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)壁紙就搞定了线婚。