主要以在launcher界面长按点击wallpaper按钮来设置壁纸的流程。
当我们点击wallpaper按钮后进入WallpaperPickerActivity.java界面,分三块上为设置按钮,中为将要设置的wallpaper图片,下为所有壁纸的缩略图。
选择好壁纸后点击设置按钮
/packages/apps/Launcher3/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
// Action bar
// Show the custom action bar view
final ActionBar actionBar = getActionBar();
actionBar.setCustomView(R.layout.actionbar_set_wallpaper);
actionBar.getCustomView().setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Ensure that a tile is slelected and loaded.
if (mSelectedTile != null && mCropView.getTileSource() != null) {
// Prevent user from selecting any new tile.
mWallpaperStrip.setVisibility(View.GONE);
actionBar.hide();
WallpaperTileInfo info = (WallpaperTileInfo) mSelectedTile.getTag();
info.onSave(WallpaperPickerActivity.this);//接着这个方法
} else {
// no tile was selected, so we just finish the activity and go back
setResult(Activity.RESULT_OK);
finish();
}
}
});
mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);
上面这个方法调用FileWallpaperInfo中的onSave方法
<pre name="code" class="java"> /packages/apps/Launcher3/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java@FileWallpaperInfo@Override
public void onSave(WallpaperPickerActivity a)
{ a.setWallpaper(Uri.fromFile(mFile), true);//该setWallpaper在WallpaperCropActivity.java中实现
由上转入WallpaperCropActivity.java的setWallpaper()方法。
/packages/apps/Launcher3/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
protected void setWallpaper(Uri uri, final boolean finishActivityWhenDone) {
int rotation = BitmapUtils.getRotationFromExif(getContext(), uri);
BitmapCropTask cropTask = new BitmapCropTask( getContext(), uri, null, rotation, 0, 0, true, false, null);//该task是图片处理与切割关键
final Point bounds = cropTask.getImageBounds();
Runnable onEndCrop = new Runnable() {
public void run() {
updateWallpaperDimensions(bounds.x, bounds.y);
if (finishActivityWhenDone) {
setResult(Activity.RESULT_OK);
finish();
} } };
cropTask.setCropSize(bounds.x, bounds.y);
cropTask.setOnEndRunnable(onEndCrop);
cropTask.setNoCrop(true);
cropTask.execute(); }
由上转入BitmapCropTask.java,具体代码就不全贴出,关键看cropBitmap()里的wallpaperManager.setStream(is);调用
/packages/apps/Launcher3/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
public boolean cropBitmap() {
boolean failure = false;
... ... ...
wallpaperManager.setStream(is);
... ... ...
}
我们看到最后通过流数据写入,将图片资源写入到wallpaper文件里面。具体实现我们转到wallpaperManager.java这个类
/frameworks/base/core/java/android/app/wallpaperManager.java
public void setStream(InputStream data) throws IOException {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
return;
}
try {
ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
mContext.getOpPackageName());//这个service调用是关键,获取wallpaper文件载体
if (fd == null) {
return;
}
FileOutputStream fos = null;
try {
fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
setWallpaper(data, fos);//获取到wallpaper文件载体后往里面写如数据
} finally {
if (fos != null) {
fos.close();
}
}
} catch (RemoteException e) {
// Ignore
}
}
private void setWallpaper(InputStream data, FileOutputStream fos)//往wallpaper文件载体里面写数据
throws IOException {
byte[] buffer = new byte[32768];
int amt;
while ((amt=data.read(buffer)) > 0) {
fos.write(buffer, 0, amt);
}
}
我们看到上面有一个ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,mContext.getOpPackageName());,该setWallpaper实现在WallpaperManagerService.java中实现,由于是远程service调用所以这里用到aidl.具体接口声明在
frameworks/base/core/java/android/app/IWallpaperManagerCallback.aidl,这里不列出。
public ParcelFileDescriptor setWallpaper(String name, String callingPackage) {
checkPermission(android.Manifest.permission.SET_WALLPAPER);
if (!isWallpaperSupported(callingPackage)) {
return null;
}
synchronized (mLock) {
if (DEBUG) Slog.v(TAG, "setWallpaper");
// /M: To support Smart Book @ {
if (isSmartBookSupport()) {
mHaveUsedSmartBook = false;
}
// /@ }
int userId = UserHandle.getCallingUserId();
WallpaperData wallpaper = getWallpaperSafeLocked(userId);
final long ident = Binder.clearCallingIdentity();
try {
ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper);
if (pfd != null) {
wallpaper.imageWallpaperPending = true;
}
return pfd;
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) {
if (name == null) name = "";
try {
File dir = getWallpaperDir(wallpaper.userId);
if (!dir.exists()) {
dir.mkdir();
FileUtils.setPermissions(
dir.getPath(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-1, -1);
}
File file = new File(dir, mWallpaperFileName);
ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
if (!SELinux.restorecon(file)) {
return null;
}
wallpaper.name = name;
return fd;
} catch (FileNotFoundException e) {
Slog.w(TAG, "Error setting wallpaper", e);
}
return null;
}
private static File getWallpaperDir(int userId) {
return Environment.getUserSystemDirectory(userId);
}