gre / react-native-view-shot

Snapshot a React Native view and save it to an image
https://github.com/gre/react-native-view-shot-example
MIT License
2.67k stars 346 forks source link

Only the original thread that created a view hierarchy can touch its views. #426

Open gmass0n opened 2 years ago

gmass0n commented 2 years ago

Get this error when tries to capture in android

Code: Screen Shot 2022-07-20 at 17 53 52

Error:

Screen Shot 2022-07-20 at 17 47 59
ocsby commented 2 years ago

I am getting same issue on Android 5.1. Did you find any solution?

adelnobel commented 2 years ago

Same problem here, was going to post about it then found your issue.

adelnobel commented 2 years ago

Here is the whole stack


E/ViewShot( 8169): Failed to capture view snapshot
E/ViewShot( 8169): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
E/ViewShot( 8169):  at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7146)
E/ViewShot( 8169):  at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1033)
E/ViewShot( 8169):  at android.view.ViewGroup.invalidateChild(ViewGroup.java:4971)
E/ViewShot( 8169):  at android.view.View.invalidateInternal(View.java:12691)
E/ViewShot( 8169):  at android.view.View.invalidate(View.java:12655)
E/ViewShot( 8169):  at android.view.View.invalidate(View.java:12639)
E/ViewShot( 8169):  at android.widget.TextView.checkForRelayout(TextView.java:8094)
E/ViewShot( 8169):  at android.widget.TextView.onRtlPropertiesChanged(TextView.java:11004)
E/ViewShot( 8169):  at android.view.View.resolvePadding(View.java:14305)
E/ViewShot( 8169):  at android.view.View.getPaddingStart(View.java:17620)
E/ViewShot( 8169):  at fr.greweb.reactnativeviewshot.DebugViews.dumpProperties(DebugViews.java:171)
E/ViewShot( 8169):  at fr.greweb.reactnativeviewshot.DebugViews.logViewHierarchy(DebugViews.java:95)
E/ViewShot( 8169):  at fr.greweb.reactnativeviewshot.DebugViews.logViewHierarchy(DebugViews.java:73)
E/ViewShot( 8169):  at fr.greweb.reactnativeviewshot.ViewShot.captureView(ViewShot.java:371)
E/ViewShot( 8169):  at fr.greweb.reactnativeviewshot.ViewShot.saveToTempFileOnDevice(ViewShot.java:271)
E/ViewShot( 8169):  at fr.greweb.reactnativeviewshot.ViewShot.access$1000(ViewShot.java:62)
E/ViewShot( 8169):  at fr.greweb.reactnativeviewshot.ViewShot$2.run(ViewShot.java:253)
E/ViewShot( 8169):  at android.os.Handler.handleCallback(Handler.java:739)
E/ViewShot( 8169):  at android.os.Handler.dispatchMessage(Handler.java:95)
E/ViewShot( 8169):  at android.os.Looper.loop(Looper.java:145)
E/ViewShot( 8169):  at android.os.HandlerThread.run(HandlerThread.java:61)
E/ReactNativeJS( 8169): 'Oops, snapshot failed', [Error: Failed to capture view snapshot]
E/unknown:ReactNative( 8169): console.error: Oops, snapshot failed Error: Failed to capture view snapshot, js engine: hermes, stack:
E/unknown:ReactNative( 8169): _construct@1:143516
E/unknown:ReactNative( 8169): Wrapper@1:143170
E/unknown:ReactNative( 8169): _createSuperInternal@1:141052
E/unknown:ReactNative( 8169): SyntheticError@1:142528
E/unknown:ReactNative( 8169): reactConsoleErrorHandler@1:142161
E/unknown:ReactNative( 8169): anonymous@1:1966810
E/unknown:ReactNative( 8169): tryCallOne@53:15
E/unknown:ReactNative( 8169): anonymous@139:26
E/unknown:ReactNative( 8169): anonymous@1:169478
E/unknown:ReactNative( 8169): _callTimer@1:168422
E/unknown:ReactNative( 8169): _callReactNativeMicrotasksPass@1:168627
E/unknown:ReactNative( 8169): callReactNativeMicrotasks@1:170564
E/unknown:ReactNative( 8169): __callReactNativeMicrotasks@1:149851
E/unknown:ReactNative( 8169): anonymous@1:148983
E/unknown:ReactNative( 8169): __guard@1:149728
E/unknown:ReactNative( 8169): flushedQueue@1:148894
E/unknown:ReactNative( 8169): invokeCallbackAndReturnFlushedQueue@1:148837
VMBindraban commented 1 year ago

I am currently getting the same error on android 4 devices. Works fine in android 10+.

Version 3.7.0.

10-10 14:24:27.186 19779 28028 E ViewShot: Failed to capture view snapshot
10-10 14:24:27.186 19779 28028 E ViewShot: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
10-10 14:24:27.186 19779 28028 E ViewShot:  at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6899)
10-10 14:24:27.186 19779 28028 E ViewShot:  at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1090)
10-10 14:24:27.186 19779 28028 E ViewShot:  at android.view.ViewGroup.invalidateChild(ViewGroup.java:5205)
10-10 14:24:27.186 19779 28028 E ViewShot:  at android.view.View.invalidateInternal(View.java:13664)
10-10 14:24:27.186 19779 28028 E ViewShot:  at android.view.View.invalidate(View.java:13628)
10-10 14:24:27.186 19779 28028 E ViewShot:  at android.view.View.invalidate(View.java:13612)
10-10 14:24:27.186 19779 28028 E ViewShot:  at android.view.TextureView.updateLayerAndInvalidate(TextureView.java:442)
10-10 14:24:27.186 19779 28028 E ViewShot:  at android.view.TextureView.setOpaque(TextureView.java:198)
10-10 14:24:27.186 19779 28028 E ViewShot:  at fr.greweb.reactnativeviewshot.ViewShot.captureViewImpl(ViewShot.java:382)
10-10 14:24:27.186 19779 28028 E ViewShot:  at fr.greweb.reactnativeviewshot.ViewShot.captureView(ViewShot.java:329)
10-10 14:24:27.186 19779 28028 E ViewShot:  at fr.greweb.reactnativeviewshot.ViewShot.saveToBase64String(ViewShot.java:273)
10-10 14:24:27.186 19779 28028 E ViewShot:  at fr.greweb.reactnativeviewshot.ViewShot.-$$Nest$msaveToBase64String(ViewShot.java)
10-10 14:24:27.186 19779 28028 E ViewShot:  at fr.greweb.reactnativeviewshot.ViewShot$1.run(ViewShot.java:213)
10-10 14:24:27.186 19779 28028 E ViewShot:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
10-10 14:24:27.186 19779 28028 E ViewShot:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
10-10 14:24:27.186 19779 28028 E ViewShot:  at java.lang.Thread.run(Thread.java:761)
KodyFintak commented 1 year ago

Also getting the same issue on Nougat, 7.1.1. Is there anything we can do to prevent this issue?

hwvenancio commented 1 year ago

I found a solution. On ViewShot.java where you have the following code:

        final Canvas c = new Canvas(bitmap);
        view.draw(c);

Force it to run on the UI Thread:

        final Canvas c = new Canvas(bitmap);
        CountDownLatch waitLatch = new CountDownLatch(1);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                view.draw(c);
                waitLatch.countDown();
            }
        });

        try {
            waitLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }