imToken v2.14.1版本的 MD5 值为:83050b2c91219b46832c8336279e7878

以下内容为反编译后的 ViewShot.java 源代码,内容仅作参考


package fr.greweb.reactnativeviewshot;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Base64;
import android.util.Log;
import android.view.PixelCopy;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ScrollView;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.NativeViewHierarchyManager;
import com.facebook.react.uimanager.UIBlock;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.zip.Deflater;
import javax.annotation.Nullable;
public class ViewShot implements UIBlock {
    private static final int ARGB_SIZE = 4;
    public static final String ERROR_UNABLE_TO_SNAPSHOT = "E_UNABLE_TO_SNAPSHOT";
    private static final int PREALLOCATE_SIZE = 65536;
    private static final int SURFACE_VIEW_READ_PIXELS_TIMEOUT = 5;
    private static final String TAG = "ViewShot";
    private final Activity currentActivity;
    private final Executor executor;
    private final String extension;
    private final int format;
    private final boolean handleGLSurfaceView;
    private final Integer height;
    private final File output;
    private final Promise promise;
    private final double quality;
    private final ReactApplicationContext reactContext;
    private final String result;
    private final Boolean snapshotContentContainer;
    private final int tag;
    private final Integer width;
    private static byte[] outputBuffer = new byte[65536];
    private static final Object guardBitmaps = new Object();
    private static final Set<Bitmap> weakBitmaps = Collections.newSetFromMap(new WeakHashMap());

    public @interface Formats {
        public static final int JPEG = 0;
        public static final int PNG = 1;
        public static final int RAW = -1;
        public static final int WEBP = 2;
        public static final Bitmap.CompressFormat[] mapping = {Bitmap.CompressFormat.JPEG, Bitmap.CompressFormat.PNG, Bitmap.CompressFormat.WEBP};
    }

    public @interface Results {
        public static final String BASE_64 = "base64";
        public static final String DATA_URI = "data-uri";
        public static final String TEMP_FILE = "tmpfile";
        public static final String ZIP_BASE_64 = "zip-base64";
    }

    private static <T extends A, A> T cast(A a2) {
        return a2;
    }

    public ViewShot(int i2, String str, int i3, double d2, @Nullable Integer num, @Nullable Integer num2, File file, String str2, Boolean bool, ReactApplicationContext reactApplicationContext, Activity activity, boolean z2, Promise promise, Executor executor) {
        this.tag = i2;
        this.extension = str;
        this.format = i3;
        this.quality = d2;
        this.width = num;
        this.height = num2;
        this.output = file;
        this.result = str2;
        this.snapshotContentContainer = bool;
        this.reactContext = reactApplicationContext;
        this.currentActivity = activity;
        this.handleGLSurfaceView = z2;
        this.promise = promise;
        this.executor = executor;
    }

    @Override
    public void execute(final NativeViewHierarchyManager nativeViewHierarchyManager) {
        this.executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    View findViewById = ViewShot.this.tag == -1 ? ViewShot.this.currentActivity.getWindow().getDecorView().findViewById(16908290) : nativeViewHierarchyManager.resolveView(ViewShot.this.tag);
                    if (findViewById == null) {
                        String str = ViewShot.TAG;
                        Log.e(str, "No view found with reactTag: " + ViewShot.this.tag, new AssertionError());
                        Promise promise = ViewShot.this.promise;
                        promise.reject(ViewShot.ERROR_UNABLE_TO_SNAPSHOT, "No view found with reactTag: " + ViewShot.this.tag);
                        return;
                    }
                    ReusableByteArrayOutputStream reusableByteArrayOutputStream = new ReusableByteArrayOutputStream(ViewShot.outputBuffer);
                    reusableByteArrayOutputStream.setSize(ViewShot.proposeSize(findViewById));
                    byte[] unused = ViewShot.outputBuffer = reusableByteArrayOutputStream.innerBuffer();
                    if (!Results.TEMP_FILE.equals(ViewShot.this.result) || -1 != ViewShot.this.format) {
                        if (!Results.TEMP_FILE.equals(ViewShot.this.result) || -1 == ViewShot.this.format) {
                            if (!Results.BASE_64.equals(ViewShot.this.result) && !Results.ZIP_BASE_64.equals(ViewShot.this.result)) {
                                if (Results.DATA_URI.equals(ViewShot.this.result)) {
                                    ViewShot.this.saveToDataUriString(findViewById);
                                    return;
                                }
                                return;
                            }
                            ViewShot.this.saveToBase64String(findViewById);
                            return;
                        }
                        ViewShot.this.saveToTempFileOnDevice(findViewById);
                        return;
                    }
                    ViewShot.this.saveToRawFileOnDevice(findViewById);
                } catch (Throwable th) {
                    Log.e(ViewShot.TAG, "Failed to capture view snapshot", th);
                    ViewShot.this.promise.reject(ViewShot.ERROR_UNABLE_TO_SNAPSHOT, "Failed to capture view snapshot");
                }
            }
        });
    }

    public void saveToTempFileOnDevice(View view) throws IOException {
        captureView(view, new FileOutputStream(this.output));
        this.promise.resolve(Uri.fromFile(this.output).toString());
    }

    public void saveToRawFileOnDevice(View view) throws IOException {
        String uri = Uri.fromFile(this.output).toString();
        FileOutputStream fileOutputStream = new FileOutputStream(this.output);
        ReusableByteArrayOutputStream reusableByteArrayOutputStream = new ReusableByteArrayOutputStream(outputBuffer);
        Point captureView = captureView(view, reusableByteArrayOutputStream);
        outputBuffer = reusableByteArrayOutputStream.innerBuffer();
        int size = reusableByteArrayOutputStream.size();
        fileOutputStream.write(String.format(Locale.US, "%d:%d|", Integer.valueOf(captureView.x), Integer.valueOf(captureView.y)).getBytes(Charset.forName("US-ASCII")));
        fileOutputStream.write(outputBuffer, 0, size);
        fileOutputStream.close();
        this.promise.resolve(uri);
    }

    public void saveToDataUriString(View view) throws IOException {
        ReusableByteArrayOutputStream reusableByteArrayOutputStream = new ReusableByteArrayOutputStream(outputBuffer);
        captureView(view, reusableByteArrayOutputStream);
        outputBuffer = reusableByteArrayOutputStream.innerBuffer();
        String encodeToString = Base64.encodeToString(outputBuffer, 0, reusableByteArrayOutputStream.size(), 2);
        String str = "jpg".equals(this.extension) ? "jpeg" : this.extension;
        Promise promise = this.promise;
        promise.resolve("data:image/" + str + ";base64," + encodeToString);
    }

    public void saveToBase64String(View view) throws IOException {
        String str;
        boolean z2 = -1 == this.format;
        boolean equals = Results.ZIP_BASE_64.equals(this.result);
        ReusableByteArrayOutputStream reusableByteArrayOutputStream = new ReusableByteArrayOutputStream(outputBuffer);
        Point captureView = captureView(view, reusableByteArrayOutputStream);
        outputBuffer = reusableByteArrayOutputStream.innerBuffer();
        int size = reusableByteArrayOutputStream.size();
        String format = String.format(Locale.US, "%d:%d|", Integer.valueOf(captureView.x), Integer.valueOf(captureView.y));
        if (!z2) {
            format = "";
        }
        if (equals) {
            Deflater deflater = new Deflater();
            deflater.setInput(outputBuffer, 0, size);
            deflater.finish();
            ReusableByteArrayOutputStream reusableByteArrayOutputStream2 = new ReusableByteArrayOutputStream(new byte[32]);
            byte[] bArr = new byte[1024];
            while (!deflater.finished()) {
                reusableByteArrayOutputStream2.write(bArr, 0, deflater.deflate(bArr));
            }
            str = format + Base64.encodeToString(reusableByteArrayOutputStream2.innerBuffer(), 0, reusableByteArrayOutputStream2.size(), 2);
        } else {
            str = format + Base64.encodeToString(outputBuffer, 0, size, 2);
        }
        this.promise.resolve(str);
    }

    private List<View> getAllChildren(View view) {
        if (!(view instanceof ViewGroup)) {
            ArrayList arrayList = new ArrayList();
            arrayList.add(view);
            return arrayList;
        }
        ArrayList arrayList2 = new ArrayList();
        ViewGroup viewGroup = (ViewGroup) view;
        for (int i2 = 0; i2 < viewGroup.getChildCount(); i2++) {
            arrayList2.addAll(getAllChildren(viewGroup.getChildAt(i2)));
        }
        return arrayList2;
    }

    private Point captureView(View view, OutputStream outputStream) throws IOException {
        try {
            return captureViewImpl(view, outputStream);
        } finally {
            outputStream.close();
        }
    }

    private Point captureViewImpl(final View view, OutputStream outputStream) {
        int i2;
        Bitmap bitmap;
        OutputStream outputStream2;
        Paint paint;
        Bitmap bitmap2;
        Point point;
        int i3;
        Canvas canvas;
        Paint paint2;
        SurfaceView surfaceView;
        View view2 = view;
        int width = view.getWidth();
        int height = view.getHeight();
        if (width <= 0 || height <= 0) {
            throw new RuntimeException("Impossible to snapshot the view: view is invalid");
        }
        boolean z2 = false;
        if (this.snapshotContentContainer.booleanValue()) {
            ScrollView scrollView = (ScrollView) view2;
            int i4 = 0;
            for (int i5 = 0; i5 < scrollView.getChildCount(); i5++) {
                i4 += scrollView.getChildAt(i5).getHeight();
            }
            i2 = i4;
        } else {
            i2 = height;
        }
        Point point2 = new Point(width, i2);
        Bitmap bitmapForScreenshot = getBitmapForScreenshot(width, i2);
        final Paint paint3 = new Paint();
        int i6 = 1;
        paint3.setAntiAlias(true);
        paint3.setFilterBitmap(true);
        paint3.setDither(true);
        Canvas canvas2 = new Canvas(bitmapForScreenshot);
        view2.draw(canvas2);
        for (final View view3 : getAllChildren(view)) {
            if (view3 instanceof TextureView) {
                if (view3.getVisibility() == 0) {
                    TextureView textureView = (TextureView) view3;
                    textureView.setOpaque(z2);
                    Bitmap bitmap3 = textureView.getBitmap(getExactBitmapForScreenshot(view3.getWidth(), view3.getHeight()));
                    int save = canvas2.save();
                    applyTransformations(canvas2, view2, view3);
                    canvas2.drawBitmap(bitmap3, 0.0f, 0.0f, paint3);
                    canvas2.restoreToCount(save);
                    recycleBitmap(bitmap3);
                }
            } else if ((view3 instanceof SurfaceView) && this.handleGLSurfaceView) {
                SurfaceView surfaceView2 = (SurfaceView) view3;
                final CountDownLatch countDownLatch = new CountDownLatch(i6);
                if (Build.VERSION.SDK_INT >= 24) {
                    final Bitmap exactBitmapForScreenshot = getExactBitmapForScreenshot(view3.getWidth(), view3.getHeight());
                    try {
                        final Canvas canvas3 = canvas2;
                        surfaceView = surfaceView2;
                        point = point2;
                        canvas = canvas2;
                        i3 = 1;
                        paint = paint3;
                        bitmap2 = bitmapForScreenshot;
                        try {
                            PixelCopy.request(surfaceView, exactBitmapForScreenshot, new PixelCopy.OnPixelCopyFinishedListener() {
                                @Override
                                public void onPixelCopyFinished(int i7) {
                                    int save2 = canvas3.save();
                                    ViewShot.this.applyTransformations(canvas3, view, view3);
                                    canvas3.drawBitmap(exactBitmapForScreenshot, 0.0f, 0.0f, paint3);
                                    canvas3.restoreToCount(save2);
                                    ViewShot.recycleBitmap(exactBitmapForScreenshot);
                                    countDownLatch.countDown();
                                }
                            }, new Handler(Looper.getMainLooper()));
                            countDownLatch.await(5L, TimeUnit.SECONDS);
                        } catch (Exception e2) {
                            e = e2;
                            Log.e(TAG, "Cannot PixelCopy for " + surfaceView, e);
                            paint2 = paint;
                            view2 = view;
                            paint3 = paint2;
                            i6 = i3;
                            canvas2 = canvas;
                            point2 = point;
                            bitmapForScreenshot = bitmap2;
                            z2 = false;
                        }
                    } catch (Exception e3) {
                        e = e3;
                        surfaceView = surfaceView2;
                        paint = paint3;
                        bitmap2 = bitmapForScreenshot;
                        point = point2;
                        i3 = 1;
                        canvas = canvas2;
                    }
                } else {
                    paint = paint3;
                    bitmap2 = bitmapForScreenshot;
                    point = point2;
                    i3 = 1;
                    canvas = canvas2;
                    if (surfaceView2.getDrawingCache() != null) {
                        paint2 = paint;
                        canvas.drawBitmap(surfaceView2.getDrawingCache(), 0.0f, 0.0f, paint2);
                        view2 = view;
                        paint3 = paint2;
                        i6 = i3;
                        canvas2 = canvas;
                        point2 = point;
                        bitmapForScreenshot = bitmap2;
                        z2 = false;
                    }
                }
                paint2 = paint;
                view2 = view;
                paint3 = paint2;
                i6 = i3;
                canvas2 = canvas;
                point2 = point;
                bitmapForScreenshot = bitmap2;
                z2 = false;
            }
            i3 = i6;
            paint2 = paint3;
            bitmap2 = bitmapForScreenshot;
            point = point2;
            canvas = canvas2;
            view2 = view;
            paint3 = paint2;
            i6 = i3;
            canvas2 = canvas;
            point2 = point;
            bitmapForScreenshot = bitmap2;
            z2 = false;
        }
        boolean z3 = i6;
        Bitmap bitmap4 = bitmapForScreenshot;
        Point point3 = point2;
        Integer num = this.width;
        if (num == null || this.height == null || (num.intValue() == width && this.height.intValue() == i2)) {
            bitmap = bitmap4;
        } else {
            bitmap = Bitmap.createScaledBitmap(bitmap4, this.width.intValue(), this.height.intValue(), z3);
            recycleBitmap(bitmap4);
        }
        if (-1 == this.format) {
            outputStream2 = outputStream;
            if (outputStream2 instanceof ReusableByteArrayOutputStream) {
                int i7 = width * i2 * 4;
                ReusableByteArrayOutputStream reusableByteArrayOutputStream = (ReusableByteArrayOutputStream) cast(outputStream);
                bitmap.copyPixelsToBuffer(reusableByteArrayOutputStream.asBuffer(i7));
                reusableByteArrayOutputStream.setSize(i7);
                recycleBitmap(bitmap);
                return point3;
            }
        } else {
            outputStream2 = outputStream;
        }
        bitmap.compress(Formats.mapping[this.format], (int) (this.quality * 100.0d), outputStream2);
        recycleBitmap(bitmap);
        return point3;
    }

    public Matrix applyTransformations(Canvas canvas, View view, View view2) {
        Matrix matrix = new Matrix();
        LinkedList linkedList = new LinkedList();
        View view3 = view2;
        do {
            linkedList.add(view3);
            view3 = (View) view3.getParent();
        } while (view3 != view);
        Collections.reverse(linkedList);
        Iterator it = linkedList.iterator();
        while (it.hasNext()) {
            View view4 = (View) it.next();
            canvas.save();
            int i2 = 0;
            float left = view4.getLeft() + (view4 != view2 ? view4.getPaddingLeft() : 0) + view4.getTranslationX();
            int top = view4.getTop();
            if (view4 != view2) {
                i2 = view4.getPaddingTop();
            }
            float translationY = top + i2 + view4.getTranslationY();
            canvas.translate(left, translationY);
            canvas.rotate(view4.getRotation(), view4.getPivotX(), view4.getPivotY());
            canvas.scale(view4.getScaleX(), view4.getScaleY());
            matrix.postTranslate(left, translationY);
            matrix.postRotate(view4.getRotation(), view4.getPivotX(), view4.getPivotY());
            matrix.postScale(view4.getScaleX(), view4.getScaleY());
        }
        return matrix;
    }

    public static int proposeSize(View view) {
        return Math.min(view.getWidth() * view.getHeight() * 4, 32);
    }

    public static void recycleBitmap(Bitmap bitmap) {
        synchronized (guardBitmaps) {
            weakBitmaps.add(bitmap);
        }
    }

    private static Bitmap getBitmapForScreenshot(int i2, int i3) {
        synchronized (guardBitmaps) {
            for (Bitmap bitmap : weakBitmaps) {
                if (bitmap.getWidth() == i2 && bitmap.getHeight() == i3) {
                    weakBitmaps.remove(bitmap);
                    bitmap.eraseColor(0);
                    return bitmap;
                }
            }
            return Bitmap.createBitmap(i2, i3, Bitmap.Config.ARGB_8888);
        }
    }

    private static Bitmap getExactBitmapForScreenshot(int i2, int i3) {
        synchronized (guardBitmaps) {
            for (Bitmap bitmap : weakBitmaps) {
                if (bitmap.getWidth() == i2 && bitmap.getHeight() == i3) {
                    weakBitmaps.remove(bitmap);
                    bitmap.eraseColor(0);
                    return bitmap;
                }
            }
            return Bitmap.createBitmap(i2, i3, Bitmap.Config.ARGB_8888);
        }
    }

    public static class ReusableByteArrayOutputStream extends ByteArrayOutputStream {
        private static final int MAX_ARRAY_SIZE = 2147483639;

        public ReusableByteArrayOutputStream(byte[] bArr) {
            super(0);
            this.buf = bArr;
        }

        public byte[] innerBuffer() {
            return this.buf;
        }

        public ByteBuffer asBuffer(int i2) {
            if (this.buf.length < i2) {
                grow(i2);
            }
            return ByteBuffer.wrap(this.buf);
        }

        public void setSize(int i2) {
            this.count = i2;
        }

        protected void grow(int i2) {
            int length = this.buf.length << 1;
            if (length - i2 < 0) {
                length = i2;
            }
            if (length - MAX_ARRAY_SIZE > 0) {
                length = hugeCapacity(i2);
            }
            this.buf = Arrays.copyOf(this.buf, length);
        }

        protected static int hugeCapacity(int i2) {
            if (i2 >= 0) {
                if (i2 > MAX_ARRAY_SIZE) {
                    return Integer.MAX_VALUE;
                }
                return MAX_ARRAY_SIZE;
            }
            throw new OutOfMemoryError();
        }
    }
}