Android 15 实现修改锁屏界面默认壁纸功能

前言

最近遇到一个A15系统项目,客户要求修改锁屏界面的默认壁纸,客户提供了一张壁纸图片,但是从A15系统的源代码查看时才知道谷歌已经去掉了相关的代码,已经不支持了,A13和A14系统好像是支持的,A15系统的WallpaperManager.java有明显不支持的提示如下:

frameworks/base/core/java/android/app/WallpaperManager.java

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static InputStream openDefaultWallpaper(Context context, @SetWallpaperFlags int which) {
        final String whichProp;
        final int defaultResId;
        /* Factory-default lock wallpapers are not yet supported.
        whichProp = which == FLAG_LOCK ? PROP_LOCK_WALLPAPER : PROP_WALLPAPER;
        defaultResId = which == FLAG_LOCK ? R.drawable.default_lock_wallpaper :  ....
        */
        whichProp = PROP_WALLPAPER;
        /*
         * Bug 2586784 - [AR.695.003179.010241.031295] turn off wallpaper zoomed for highrefresh
         */
        if (TextUtils.isEmpty(SystemProperties.get("ro.boot.high_refresh"))) {
            defaultResId = com.android.internal.R.drawable.default_wallpaper;
        } else {
            defaultResId = com.android.internal.R.drawable.default_wallpaper_high_refresh;
        }

方案

所以必须采用其他的方法来实现,具体修改如下:

1.将客户给的锁屏壁纸图片拷贝到源代码中,然后添加一行拷贝代码将图片拷贝到system/media/目录下即可,如下:


diff --git a/device/sprd/generic_mpool/module/generic/animation/boot/default_lock_wallpaper.png

diff --git a/device/sprd/generic_mpool/module/generic/animation/boot/boot.mk b/device/sprd/generic_mpool/module/generic/animation/boot/boot.mk
index 2ad899e3477..9003189e799 100755
--- a/device/sprd/generic_mpool/module/generic/animation/boot/boot.mk
+++ b/device/sprd/generic_mpool/module/generic/animation/boot/boot.mk
@@ -2,5 +2,6 @@
 ANIMATION := device/sprd/generic_mpool/module/generic/animation/boot
 
 PRODUCT_COPY_FILES += \
     $(ANIMATION)/bootanimation.zip:system/media/bootanimation.zip \
+    $(ANIMATION)/default_lock_wallpaper.png:system/media/default_lock_wallpaper.png 
     # $(ANIMATION)/sound.mp3:system/media/bootsound.mp3
  1. 到packages/apps/Settings/src/com/android/settings/SettingsInitialize.java这个类文件中去修改代码,为什么选择在这个文件去修改呢?是因为这个SettingsInitialize.java文件是机器第一次开机进系统时会执行一次,以后的重启或者开机都不会执行了,就不用去添加系统属性标记位去判断是否是第一次开机进系统,具体修改如下:
diff --git a/packages/apps/Settings/src/com/android/settings/SettingsInitialize.java b/packages/apps/Settings/src/com/android/settings/SettingsInitialize.java
index e89ae0e6b90..fe188d35f72 100755
--- a/packages/apps/Settings/src/com/android/settings/SettingsInitialize.java
+++ b/packages/apps/Settings/src/com/android/settings/SettingsInitialize.java
@@ -47,6 +47,15 @@ import com.android.settingslib.utils.ThreadUtils;
 import java.util.ArrayList;
 import java.util.List;
 
+import android.app.WallpaperManager;
+import android.graphics.Bitmap;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import android.os.Handler;
+import android.content.Context;
+import android.graphics.BitmapFactory;
+import java.io.IOException;
+
 /**
  * Listens to {@link Intent.ACTION_PRE_BOOT_COMPLETED} and {@link Intent.ACTION_USER_INITIALIZE}
  * performs setup steps for a managed profile (disables the launcher icon of the Settings app,
@@ -60,6 +69,9 @@ public class SettingsInitialize extends BroadcastReceiver {
             "com.android.settings.PRIMARY_PROFILE_CONTROLLED";
     private static final String WEBVIEW_IMPLEMENTATION_ACTIVITY = ".WebViewImplementation";
 
+    // Create by yeruilai 2025-7-21 14:57:37 Change the default lock screen wallpaper
+    private Context mContext;
+
     @Override
     public void onReceive(Context context, Intent broadcast) {
         final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
@@ -77,6 +89,12 @@ public class SettingsInitialize extends BroadcastReceiver {
         } catch (Exception e) {
             Log.w(TAG, "Init SmartKey default failed", e);
         }
+
+        // Create by yeruilai 2025-7-21 14:57:37 Change the default lock screen wallpaper
+        mContext = context;
+        mLockScreenHandler.removeCallbacks(mLockScreenRunnable);
+        mLockScreenHandler.postDelayed(mLockScreenRunnable,1);
+
     }
 
     private void managedProfileSetup(Context context, final PackageManager pm, Intent broadcast,
@@ -194,4 +212,32 @@ public class SettingsInitialize extends BroadcastReceiver {
             }
         }
     }
+
+    /** Create by yeruilai 2025-7-21 14:57:37 Change the default lock screen wallpaper */
+    private Runnable mLockScreenRunnable = new Runnable() {
+        @Override
+        public void run() {
+           setLockScreenWallpaper();
+        }
+    };
+
+    private Handler mLockScreenHandler = new Handler();
+
+    private void setLockScreenWallpaper() {
+        WallpaperManager wallpaperManager = WallpaperManager.getInstance(mContext);
+        int FLAG_SET_LOCK = 1 << 1;
+        try {
+            Bitmap bitmap = BitmapFactory.decodeFile("system/media/default_lock_wallpaper.png");
+            ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
+            if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, tmpOut)) {
+                byte[] outByteArray = tmpOut.toByteArray();
+                wallpaperManager.setStream(new ByteArrayInputStream(outByteArray), null, true, FLAG_SET_LOCK);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+       }
+       
+     }
+     /**[end] Change the default lock screen wallpaper */
+
 }

总结

本方案通过系统级资源注入和首次启动配置的组合方式,有效解决了A15系统移除锁屏壁纸API的问题。其核心优势在于:

  1. 无需修改framework层代码
  2. 保持系统更新兼容性
  3. 实现真正的出厂预置效果
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容