Curzibn / Luban

Luban(鲁班)—Image compression with efficiency very close to WeChat Moments/可能是最接近微信朋友圈的图片压缩算法
Apache License 2.0
13.58k stars 2.25k forks source link

android Q适配 #401

Open yongshengdev opened 2 years ago

yongshengdev commented 2 years ago

android Q上若传文件Uri,使用Uri类型的InputStreamProvider

new InputStreamProvider() {
@Override
                public InputStream open() throws IOException {
                    return context.getContentResolver().openInputStream(uri);
                }

                @Override
                public String getPath() {
                    return uri.getPath();
                }

                @Override
                public boolean isUri() {
                    return true;
                }

                @Override
                public long getLength() {
                    try {
                        switch (uri.getScheme()) {
                            case ContentResolver.SCHEME_FILE:
                                return new File(uri.getPath()).length();
                            case ContentResolver.SCHEME_CONTENT:
                                Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
                                long tempLength = 0;
                                if (cursor != null && cursor.moveToFirst()) {
                                    tempLength = new File(cursor.getString(cursor.getColumnIndex("_data"))).length();
                                    cursor.close();
                                }
                                return tempLength;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return 0;
                }
            }

在原Luban compress方法中

private File compress(Context context, InputStreamProvider path) throws IOException {
        File result;

        File outFile = getImageCacheFile(context, Checker.SINGLE.extSuffix(path));

        if (mRenameListener != null) {
            String filename = mRenameListener.rename(path.getPath());
            outFile = getImageCustomFile(context, filename);
        }

        if (mCompressionPredicate != null) {
            if (mCompressionPredicate.apply(path.getPath())
                    && Checker.SINGLE.needCompress(mLeastCompressSize, path)) {
                result = new Engine(path, outFile, focusAlpha).compress();
            } else {
                result = new File(path.getPath());
            }
        } else {
            result = Checker.SINGLE.needCompress(mLeastCompressSize, path) ?
                    new Engine(path, outFile, focusAlpha).compress() :
                    new File(path.getPath());
        }

        return result;
    }

若Checker.SINGLE.needCompress()返回false,直接返回uri.getPath() = eg:/external/images/media/1947 这个路径是公共目录,不能直接通过uri访问 但通过根据InputStreamProvider的open方法返回的InputStream,可以获取到源文件数据,copy到私有目录即可

private File compress(Context context, InputStreamProvider path) throws IOException {
        File result;

        File outFile = getImageCacheFile(context, Checker.SINGLE.extSuffix(path));

        if (mRenameListener != null) {
            String filename = mRenameListener.rename(path.getPath());
            outFile = getImageCustomFile(context, filename);
        }

        if (mCompressionPredicate != null) {
            if (mCompressionPredicate.apply(path.getPath())
                    && Checker.SINGLE.needCompress(mLeastCompressSize, path)) {
                result = new Engine(path, outFile, focusAlpha).compress();
            } else {
                // android Q后拷贝文件到私有目录
                result = path.isUri() ? new Mold(path, outFile).copy() : new File(path.getPath());
            }
        } else {
            result = Checker.SINGLE.needCompress(mLeastCompressSize, path) ?
                    new Engine(path, outFile, focusAlpha).compress() :
                    // android Q后拷贝文件到私有目录
                    (path.isUri() ? new Mold(path, outFile).copy() : new File(path.getPath()));
        }

        return result;
    }

/**

class Mold {
    private InputStreamProvider srcImg;
    private File tagImg;

    Mold(InputStreamProvider srcImg, File tagImg) {
        this.tagImg = tagImg;
        this.srcImg = srcImg;
    }

    File copy() throws IOException {
        InputStream inputStream = srcImg.open();
        FileOutputStream fos = new FileOutputStream(tagImg);
        byte[] b = new byte[1024];
        while ((inputStream.read(b)) != -1) {
            fos.write(b);// 写入数据
        }
        inputStream.close();
        fos.flush();
        fos.close();
        return tagImg;
    }
}