LuckSiege / PictureSelector

Picture Selector Library for Android or 图片选择器
Apache License 2.0
13.23k stars 3k forks source link

在setAddBitmapWatermarkListener内异步处理水印导致的某些机型 图片异常或者丢失 #2854

Open LittleRobotRoad opened 6 months ago

LittleRobotRoad commented 6 months ago

Current use version?

当前使用的版本是多少?

v3.11.2

Will this problem occur in demo?

Demo能否复现这问题?

可以在某些配置低或者平板上可以复现

Describe the problem or provide an error log?

描述问题或提供错误log?

setAddBitmapWatermarkListener api 如果使用异步处理并使用onCallback回调的时候, 虽然从日志来看是按顺序处理并最后调用dispatchWatermarkResult的,但是保存的水印图片会存在保存不完整或者丢失。 如果在直接写水印代码,不使用异步处理,是正常的,但是会导致loading dialog 被卡住。

使用了kotlin协程的普通的线程工具类都会出现

调用代码 1

.setAddBitmapWatermarkListener { context, srcPath, _, call ->
                val path = if (srcPath.startsWith("content://")) {
                    NovaFile.getPathByUri(context, Uri.parse(srcPath))
                } else {
                    srcPath
                }
                GlobalIOScope.launch {
                    val copyUrl = copyFileToNova(albumKey, path)
                    val dateTime = path2Date(path)
                    signWatermark(copyUrl, location, nickName, dateTime)
                    withContext(Dispatchers.Main){
                        call.onCallback(srcPath, copyUrl)
                    }
                }
            }

调用代码2

.setAddBitmapWatermarkListener { context, srcPath, _, call ->
                ThreadUtils.executeByIo(object : SimpleTask<String>() {
                    override fun doInBackground(): String {
                        val path = if (srcPath.startsWith("content://")) {
                            NovaFile.getPathByUri(context, Uri.parse(srcPath))
                        } else {
                            srcPath
                        }
                        val copyUrl = copyFileToNova(albumKey, path)
                        val dateTime = path2Date(path)
                        signWatermark(copyUrl, location, nickName, dateTime)
                    }

                    override fun onSuccess(copyUrl: String?) {
                        call.onCallback(srcPath, copyUrl)
                    }
                })
}

尝试修改addBitmapWatermark的代码,直接让这部分运行在 PictureThreadUtils 的线程里可以正常工作,但是估计违背api涉及初衷。

PictureThreadUtils.executeByIo(new PictureThreadUtils.SimpleTask<ArrayList<LocalMedia>>() {
            @Override
            public ArrayList<LocalMedia> doInBackground() {
                for (LocalMedia localMedia : result) {
                    selectorConfig.onBitmapWatermarkListener.onAddBitmapWatermark(
                            getAppContext(),
                            localMedia.getAvailablePath(),
                            localMedia.getMimeType(),
                            (srcPath, resultPath) -> {
                                if (TextUtils.isEmpty(srcPath)) {
                                    dispatchWatermarkResult(result);
                                } else {
                                    localMedia.setWatermarkPath(resultPath);
                                }
                            }
                    );
                }
                return result;
            }

            @Override
            public void onSuccess(ArrayList<LocalMedia> result) {
                PictureThreadUtils.cancel(this);
                dispatchWatermarkResult(result);
            }
        });

视频内有两张图片的颜色是不对的,其他更严重的情况是有时候图片只有一半或者直接丢失。

https://github.com/LuckSiege/PictureSelector/assets/13929310/c89f04b9-0ae6-4d7b-8ed7-7f76a0d1acb9