IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> android壁纸设置bug -> 正文阅读

[移动开发]android壁纸设置bug

问题描述

设置壁纸A为桌面和锁屏壁纸,设置默认壁纸为桌面壁纸,锁屏壁纸也变为默认壁纸A。

问题分析

设置默认壁纸为桌面壁纸时
vendor/mediatek/proprietary/packages/apps/WallpaperPicker/src/com/android/wallpaperpicker/tileinfo/DefaultWallpaperInfo.java

@Override
    public void onSave(final WallpaperPickerActivity a) {
        CropAndSetWallpaperTask.OnEndCropHandler onEndCropHandler
                = new CropAndSetWallpaperTask.OnEndCropHandler() {
            @Override
            public void run(boolean cropSucceeded) {
                if (cropSucceeded) {
                    a.setResult(Activity.RESULT_OK);
                }
                a.finish();
            }
        };
        CropAndSetWallpaperTask setWallpaperTask = new CropAndSetWallpaperTask(
                null, a, null, -1, -1, -1, onEndCropHandler) {
            @Override
            protected Boolean doInBackground(Integer... params) {
                int whichWallpaper = params[0];
                boolean succeeded;
                //当设置默认壁纸为锁屏壁纸时,走setDefaultOnLock
                //设置默认壁纸为桌面壁纸或者桌面和锁屏壁纸都走的是clearWallpaper,传入whichWallpaper参数
                if (whichWallpaper == WallpaperManagerCompat.FLAG_SET_LOCK) {
                    succeeded = setDefaultOnLock(a);
                } else {
                    succeeded = clearWallpaper(a, whichWallpaper);
                }
                return succeeded;
            }
        };

        DialogUtils.executeCropTaskAfterPrompt(a, setWallpaperTask, a.getOnDialogCancelListener());
    }
思路1

修改wallpaperPick应用,细分默认壁纸设置。
优势:只需要修改app,不需要修改framework层逻辑。
缺点:单独设置默认壁纸为桌面或者锁屏壁纸时,耗时严重

@Override
protected Boolean doInBackground(Integer... params) {
    int whichWallpaper = params[0];
    boolean succeeded;
    if (whichWallpaper == WallpaperManagerCompat.FLAG_SET_LOCK || whichWallpaper == WallpaperManagerCompat.FLAG_SET_SYSTEM) {
        succeeded = setDefaultOnLockOrHome(a,whichWallpaper);
    } else {
        succeeded = clearWallpaper(a, whichWallpaper);
    }
    return succeeded;
}
//这里设置默认壁纸为锁屏壁纸,操作的时候界面会卡很久
//如果我们把FLAG_SET_LOCK换为FLAG_SET_SYSTEM,就是设置主屏幕壁纸
//我们可以添加一个int whichWallpaper参数,决定设置为哪一个
private boolean setDefaultOnLock(WallpaperPickerActivity a) {
        boolean succeeded = true;
        try {
            Bitmap defaultWallpaper = ((BitmapDrawable) WallpaperManager.getInstance(
                    a.getApplicationContext()).getBuiltInDrawable()).getBitmap();
            ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
            if (defaultWallpaper.compress(Bitmap.CompressFormat.PNG, 100, tmpOut)) {
                byte[] outByteArray = tmpOut.toByteArray();
                WallpaperManagerCompat.getInstance(a.getApplicationContext())
                        .setStream(new ByteArrayInputStream(outByteArray), null,
                                true, WallpaperManagerCompat.FLAG_SET_LOCK);
            }
        } catch (IOException e) {
            Log.w(TAG, "Setting wallpaper to default threw exception", e);
            succeeded = false;
        }
        return succeeded;
    }

对setDefaultOnLock方法进行改造,修改后

private boolean setDefaultOnLockOrHome(WallpaperPickerActivity a,int whichWallpaper) {
        boolean succeeded = true;
        try {
            Bitmap defaultWallpaper = ((BitmapDrawable) WallpaperManager.getInstance(
                    a.getApplicationContext()).getBuiltInDrawable()).getBitmap();
            ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
            if (defaultWallpaper.compress(Bitmap.CompressFormat.PNG, 100, tmpOut)) {
                byte[] outByteArray = tmpOut.toByteArray();
                WallpaperManagerCompat.getInstance(a.getApplicationContext())
                        .setStream(new ByteArrayInputStream(outByteArray), null,
                                true, whichWallpaper);
            }
        } catch (IOException e) {
            Log.w(TAG, "Setting wallpaper to default threw exception", e);
            succeeded = false;
        }
        return succeeded;
    }
思路2

我们注意到,clearWallpaper(a, whichWallpaper);其实是有传入参数的,那么按照这个逻辑,应该是可以分别对锁屏或者桌面壁纸进行清除,使它显示默认壁纸,而不影响另一个。

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

//可以看到,判断当clear参数为FLAG_SYSTEM的时候走了clear,而不是clearWallpaper
public void clear(@SetWallpaperFlags int which) throws IOException {
    if ((which & FLAG_SYSTEM) != 0) {
        clear();
    }
    if ((which & FLAG_LOCK) != 0) {
        clearWallpaper(FLAG_LOCK, mContext.getUserId());
    }
}

修改为:

public void clear(@SetWallpaperFlags int which) throws IOException {
	//如果清除桌面和锁屏壁纸
    if ((which & FLAG_SYSTEM) != 0 && (which & FLAG_LOCK) != 0){
        clear();
    }
    //如果只清除桌面
    if ((which & FLAG_SYSTEM) != 0) {
        clearWallpaper(FLAG_SYSTEM, mContext.getUserId());
    }
    //如果只清除锁屏壁纸
    if ((which & FLAG_LOCK) != 0) {
        clearWallpaper(FLAG_LOCK, mContext.getUserId());
    }
}

按照理解,这样就可以了。但是实际上测下来还是没有效果。
原因
1、桌面壁纸显示为:vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/ImageWallpaper.java
当桌面和锁屏显示不同的壁纸,锁屏壁纸显示为:
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java中的private ImageView mBackdropFront;

2、桌面和锁屏显示同一张壁纸的时候,锁屏其实不显示壁纸,透明过去显示桌面壁纸。
直接清除桌面壁纸,从效果上来说,锁屏不显示壁纸,透过去看到桌面壁纸,所以看上去桌面壁纸和锁屏壁纸都变了。

我们需要在清除壁纸之前,把桌面壁纸设置为锁屏壁纸,再去清除桌面壁纸。

这个思想来自于WallpaperManagerService的setWallpaper。见下文↓

frameworks/base/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java

//桌面壁纸
private final SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
//锁屏壁纸
private final SparseArray<WallpaperData> mLockWallpaperMap = new SparseArray<WallpaperData>();

//当我们设置壁纸时,如果上一次桌面和锁屏壁纸相同,如果直接设置下一张壁纸为桌面壁纸,那么锁屏壁纸会跟着变。
//这时候有一个特殊处理:::
//判断是设置桌面壁纸并且锁屏没有单独设置,先把当前壁纸设置为锁屏壁纸。
//migrateSystemToLockWallpaperLocked
//再把要设置的壁纸设置为桌面壁纸
public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
        Rect cropHint, boolean allowBackup, Bundle extras, int which,
        IWallpaperManagerCallback completion, int userId) {
	...
    synchronized (mLock) {
        if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
        WallpaperData wallpaper;

        /* If we're setting system but not lock, and lock is currently sharing the system
         * wallpaper, we need to migrate that image over to being lock-only before
         * the caller here writes new bitmap data.
         */
        if (which == FLAG_SYSTEM && mLockWallpaperMap.get(userId) == null) {
            Slog.i(TAG, "Migrating current wallpaper to be lock-only before"
                    + "updating system wallpaper");
            migrateSystemToLockWallpaperLocked(userId);
        }
		...
        wallpaper = getWallpaperSafeLocked(userId, which); 
    }
}

//那么,clearWallpaper的时候,我们也这样设计一下
@Override
public void clearWallpaper(String callingPackage, int which, int userId) {
    if (DEBUG) Slog.v(TAG, "clearWallpaper");
    ...
    synchronized (mLock) {
    	//add start如果清除的是桌面壁纸,并且之前锁屏没有壁纸,先把桌面壁纸复制到锁屏壁纸
        if (which == FLAG_SYSTEM && mLockWallpaperMap.get(userId) == null) {
            Slog.i(TAG, "Migrating current wallpaper to be lock-only before"
                    + "clear system wallpaper");
            migrateSystemToLockWallpaperLocked(userId);
        }
        //add end再进行清除系统壁纸
        clearWallpaperLocked(false, which, userId, null);

        if (which == FLAG_LOCK) {
            data = mLockWallpaperMap.get(userId);
        }
        if (which == FLAG_SYSTEM || data == null) {
            data = mWallpaperMap.get(userId);
        }
    }
    ...
}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-28 12:30:08  更:2021-10-28 12:30:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:27:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码