我们设置android默认壁纸的时候,会替换对应的资源文件,但是android O之后只能配置系统壁纸,锁屏壁纸设置为透明或设置与系统壁纸一样,如果我们要像之前一样单独配置锁屏壁纸需要修改WallpaperManager.关于Android O后面为什么不能设置锁屏壁纸,源码有下面的解释:
frameowrks/base/core/java/android/app/WallpaperManager.java
public static InputStream openDefaultWallpaper(Context context, @SetWallpaperFlags int which) {
final String whichProp;
final int defaultResId;
if (which == FLAG_LOCK) {
/* Factory-default lock wallpapers are not yet supported
whichProp = PROP_LOCK_WALLPAPER;
defaultResId = com.android.internal.R.drawable.default_lock_wallpaper;
*/
return null;
} else {
whichProp = PROP_WALLPAPER;
defaultResId = com.android.internal.R.drawable.default_wallpaper;
}
........
return null;
}
openDefaultWallpaper方法有一个参数which,它只会有两种类型FLAG_LOCK,FLAG_SYSTEM,分别代表这锁屏壁纸和桌面壁纸(桌面壁纸在SysemUI应用里面).但是源码这里有一个注解"Factory-default lock wallpapers are not yet supported",说明官方不支持设置默认锁屏壁纸,经过发现,默认锁屏就是默认桌面的壁纸,default_lock_wallpaper;是无效.
如果要实现单独配置锁屏和桌面壁纸,需要修改相关代码,在修改之前需要了解加载流程.
以展讯8.1为例:
展讯8.1直接把默认壁纸透明话,只显示桌面壁纸.从而省略了加载锁屏壁纸的流程,提高了流畅度.所以我们需要先把这个开关打开.
frameowrks/base/package/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = SystemProperties.getBoolean("ro.lockwallpaper.enable", true);
加载锁屏和默认壁纸有相关的4个类
modified: base/core/java/android/app/WallpaperManager.java
modified: base/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
modified: base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
modified: base/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
功能 | 类,名 | 所属 |
---|---|---|
桌面壁纸(系统壁纸加载类) | ImageWallpaper | SystemUI |
锁屏壁纸加载类 | LockscreenWallpaper | SystemUI |
壁纸加载服务类应用进程端 | ImageWallpaper | frameworks |
壁纸加载服务类系统进程端 | WallpaperManagerService | frameworks |
加载默认壁纸是在"壁纸加载服务类应用进程端"
加载默认壁纸是不会调用WallpaperManagerService,只在
在LockscreenWallpaperhe 和ImageWallpaper最终调用getBitmapAsUser如下所示
public Bitmap getBitmap() {
return getBitmapAsUser(mContext.getUserId());
}
/**
* Like {@link #getDrawable()} but returns a Bitmap for the provided user.
*
* @hide
*/
public Bitmap getBitmapAsUser(int userId) {
return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId);
}
在getBitmapAsUser只会传入FLAG_SYSTEM,见:peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId);所以要在加载锁屏壁纸这个逻辑要修改(后面修改)
然后进入peekWallpaperBitmap,代码如下
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
@SetWallpaperFlags int which, int userId) {
....
if (returnDefault) {
Bitmap defaultWallpaper = mDefaultWallpaper;
if (defaultWallpaper == null) {
;
defaultWallpaper = getDefaultWallpaper(context, which);
synchronized (this) {
mDefaultLockWallpaper = defaultWallpaper;
}
}
return defaultWallpaper;
}
return null;
}
这个只有一个mDefaultLockWallpaper,所以在保存的时候只会保存一个,因为要想锁屏壁纸和系统壁纸都有效,必须分别加载,这里也要修改.(后面修改)
最后到openDefaultWallpaper方法
public static InputStream openDefaultWallpaper(Context context, @SetWallpaperFlags int which) {
....
if (which == FLAG_LOCK) {
/* Factory-default lock wallpapers are not yet supported*/
whichProp = PROP_LOCK_WALLPAPER;
defaultResId = com.android.internal.R.drawable.default_lock_wallpaper;
return null;
*/
} else {
whichProp = PROP_WALLPAPER;
defaultResId = com.android.internal.R.drawable.default_wallpaper;
}
final String path = SystemProperties.get(whichProp);
if (!TextUtils.isEmpty(path)) {
final File file = new File(path);
if (file.exists()) {
try {
return new FileInputStream(file);
} catch (IOException e) {
// Ignored, fall back to platform default below
}
}
}
try {
return context.getResources().openRawResource(defaultResId);
} catch (NotFoundException e) {
// no default defined for this device; this is not a failure
}
return null;
}
which == FLAG_LOCK已经被注解了,需要去掉注解,去掉retrun null;(后面修改)
SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
打开加载锁屏壁纸开关
- private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = SystemProperties.getBoolean("ro.lockwallpaper.enable", true);
+ private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
修改LockscreenWallpaper加载方式
base/core/java/android/app/WallpaperManager.java
上面方法是原来的加载的方法,现在只做系统壁纸加载,后面添加的方法做锁屏壁纸加载
修改:WallpaperManager内部类Globals的方法peekWallpaperBitmap
修改:WallpaperManager内部类Globals的方法openDefaultWallpaper
按照如上修改,系统就能分别配置锁屏和默认壁纸了
其他平台和android版本修改应该大同小异
下面是3个文件的修改patch
diff --git a/base/core/java/android/app/WallpaperManager.java b/base/core/java/android/app/WallpaperManager.java
index 8a375cd44..2cb77e88d 100644
--- a/base/core/java/android/app/WallpaperManager.java
+++ b/base/core/java/android/app/WallpaperManager.java
@@ -284,6 +284,7 @@ public class WallpaperManager {
private Bitmap mCachedWallpaper;
private int mCachedWallpaperUserId;
private Bitmap mDefaultWallpaper;
+ private Bitmap mDefaultLockWallpaper;
private Handler mMainLooperHandler;
Globals(Looper looper) {
@@ -393,6 +394,7 @@ public class WallpaperManager {
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
@SetWallpaperFlags int which, int userId) {
+
if (mService != null) {
try {
if (!mService.isWallpaperSupported(context.getOpPackageName())) {
@@ -427,11 +429,15 @@ public class WallpaperManager {
}
}
if (returnDefault) {
- Bitmap defaultWallpaper = mDefaultWallpaper;
+ Bitmap defaultWallpaper = (which == FLAG_LOCK) ? mDefaultLockWallpaper : mDefaultWallpaper;
if (defaultWallpaper == null) {
defaultWallpaper = getDefaultWallpaper(context, which);
synchronized (this) {
- mDefaultWallpaper = defaultWallpaper;
+ if(which == FLAG_LOCK) {
+ mDefaultLockWallpaper = defaultWallpaper;
+ } else {
+ mDefaultWallpaper = defaultWallpaper;
+ }
}
}
return defaultWallpaper;
@@ -831,6 +837,17 @@ public class WallpaperManager {
return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId);
}
+ /**
+ * Like {@link #getDrawable()} but returns a Bitmap for the provided user.
+ *
+ * @hide
+ */
+ public Bitmap getLockBitmapAsUser(int userId) {
+ Log.i("wangcan","wallpapseManager-getLockBitmapAsUser FLAG_LOCK");
+ return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_LOCK, userId);
+ }
+
+
/**
* Get an open, readable file descriptor to the given wallpaper image file.
* The caller is responsible for closing the file descriptor when done ingesting the file.
@@ -1829,11 +1846,10 @@ public class WallpaperManager {
final String whichProp;
final int defaultResId;
if (which == FLAG_LOCK) {
- /* Factory-default lock wallpapers are not yet supported
+ /* Factory-default lock wallpapers are not yet supported*/
whichProp = PROP_LOCK_WALLPAPER;
defaultResId = com.android.internal.R.drawable.default_lock_wallpaper;
- */
- return null;
+ //return null;
} else {
whichProp = PROP_WALLPAPER;
defaultResId = com.android.internal.R.drawable.default_wallpaper;
diff --git a/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index e44a47220..25993c55b 100644
--- a/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -109,10 +109,10 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
selectedUser != null ? selectedUser.getIdentifier() : currentUserId;
ParcelFileDescriptor fd = mWallpaperManager.getWallpaperFile(
WallpaperManager.FLAG_LOCK, lockWallpaperUserId);
- if (fd == null && mBar.getPowerSaveModeInternal() == PowerManagerEx.MODE_ULTRASAVING) {
- fd = mWallpaperManager.getWallpaperFile(
- WallpaperManager.FLAG_SYSTEM, lockWallpaperUserId);
- }
+ //if (fd == null && mBar.getPowerSaveModeInternal() == PowerManagerEx.MODE_ULTRASAVING) {
+ // fd = mWallpaperManager.getWallpaperFile(
+ // WallpaperManager.FLAG_SYSTEM, lockWallpaperUserId);
+ //}
if (fd != null) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
@@ -128,11 +128,13 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
if (selectedUser != null) {
// Show the selected user's static wallpaper.
return LoaderResult.success(
- mWallpaperManager.getBitmapAsUser(selectedUser.getIdentifier()));
+ mWallpaperManager.getLockBitmapAsUser(selectedUser.getIdentifier()));
} else {
// When there is no selected user, show the system wallpaper
- return LoaderResult.success(null);
+ //return LoaderResult.success(null);
+ return LoaderResult.success(
+ mWallpaperManager.getLockBitmapAsUser(mCurrentUserId));
}
}
}
diff --git a/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 22d0bed37..b9ee91f84 100644
--- a/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -381,7 +381,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private static final boolean ONLY_CORE_APPS;
/** If true, the lockscreen will show a distinct wallpaper */
- private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = SystemProperties.getBoolean("ro.lockwallpaper.enable", true);
+ private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
/* If true, the device supports freeform window management.
* This affects the status bar UI. */