11package fr .greweb .reactnativeviewshot ;
22
33import javax .annotation .Nullable ;
4+
45import android .graphics .Bitmap ;
56import android .graphics .Canvas ;
67import android .net .Uri ;
1617import java .io .FileOutputStream ;
1718import java .io .IOException ;
1819import java .io .OutputStream ;
20+ import java .util .concurrent .ExecutorService ;
21+ import java .util .concurrent .Executors ;
1922
2023/**
2124 * Snapshot utility class allow to screenshot a view.
@@ -24,6 +27,8 @@ public class ViewShot implements UIBlock {
2427
2528 static final String ERROR_UNABLE_TO_SNAPSHOT = "E_UNABLE_TO_SNAPSHOT" ;
2629
30+ private final static ExecutorService sExecutor = Executors .newFixedThreadPool (5 );
31+
2732 private int tag ;
2833 private String extension ;
2934 private Bitmap .CompressFormat format ;
@@ -57,59 +62,63 @@ public ViewShot(
5762
5863 @ Override
5964 public void execute (NativeViewHierarchyManager nativeViewHierarchyManager ) {
60- OutputStream os = null ;
6165 View view = nativeViewHierarchyManager .resolveView (tag );
6266 if (view == null ) {
63- promise .reject (ERROR_UNABLE_TO_SNAPSHOT , "No view found with reactTag: " + tag );
67+ promise .reject (ERROR_UNABLE_TO_SNAPSHOT , "No view found with reactTag: " + tag );
6468 return ;
6569 }
66- try {
67- if ("file" .equals (result )) {
68- os = new FileOutputStream (output );
69- captureView (view , os );
70- String uri = Uri .fromFile (output ).toString ();
71- promise .resolve (uri );
72- }
73- else if ("base64" .equals (result )) {
74- os = new ByteArrayOutputStream ();
75- captureView (view , os );
76- byte [] bytes = ((ByteArrayOutputStream ) os ).toByteArray ();
77- String data = Base64 .encodeToString (bytes , Base64 .NO_WRAP );
78- promise .resolve (data );
79- }
80- else if ("data-uri" .equals (result )) {
81- os = new ByteArrayOutputStream ();
82- captureView (view , os );
83- byte [] bytes = ((ByteArrayOutputStream ) os ).toByteArray ();
84- String data = Base64 .encodeToString (bytes , Base64 .NO_WRAP );
85- data = "data:image/" +extension +";base64," + data ;
86- promise .resolve (data );
87- }
88- else {
89- promise .reject (ERROR_UNABLE_TO_SNAPSHOT , "Unsupported result: " +result +". Try one of: file | base64 | data-uri" );
90- }
91- }
92- catch (Exception e ) {
93- e .printStackTrace ();
94- promise .reject (ERROR_UNABLE_TO_SNAPSHOT , "Failed to capture view snapshot" );
95- }
96- finally {
97- if (os != null ) {
70+ final Bitmap bitmap = captureView (view );
71+ sExecutor .execute (new Runnable () {
72+ @ Override
73+ public void run () {
74+ OutputStream os = null ;
9875 try {
99- os .close ();
100- } catch (IOException e ) {
76+ if ("file" .equals (result )) {
77+ os = new FileOutputStream (output );
78+ String uri = Uri .fromFile (output ).toString ();
79+ promise .resolve (uri );
80+ } else if ("base64" .equals (result )) {
81+ os = new ByteArrayOutputStream ();
82+ convertImageToData (bitmap , os );
83+ byte [] bytes = ((ByteArrayOutputStream ) os ).toByteArray ();
84+ String data = Base64 .encodeToString (bytes , Base64 .NO_WRAP );
85+ promise .resolve (data );
86+ } else if ("data-uri" .equals (result )) {
87+ os = new ByteArrayOutputStream ();
88+ convertImageToData (bitmap , os );
89+ byte [] bytes = ((ByteArrayOutputStream ) os ).toByteArray ();
90+ String data = Base64 .encodeToString (bytes , Base64 .NO_WRAP );
91+ data = "data:image/" + extension + ";base64," + data ;
92+ promise .resolve (data );
93+ } else {
94+ promise .reject (ERROR_UNABLE_TO_SNAPSHOT , "Unsupported result: " + result +
95+ ". Try one of: file | base64 | data-uri" );
96+ }
97+ } catch (Exception e ) {
10198 e .printStackTrace ();
99+ promise .reject (ERROR_UNABLE_TO_SNAPSHOT , "Failed to capture view snapshot" );
100+ } finally {
101+ if (os != null ) {
102+ try {
103+ os .close ();
104+ } catch (IOException e ) {
105+ e .printStackTrace ();
106+ }
107+ }
102108 }
103109 }
104- }
110+ });
111+
112+
105113 }
106114
107115 /**
108116 * Screenshot a view and return the captured bitmap.
117+ *
109118 * @param view the view to capture
110- * @return the screenshot or null if it failed.
119+ * @return bitmap drawn by view
111120 */
112- private void captureView (View view , OutputStream os ) {
121+ private Bitmap captureView (View view ) {
113122 int w = view .getWidth ();
114123 int h = view .getHeight ();
115124 if (w <= 0 || h <= 0 ) {
@@ -125,6 +134,17 @@ private void captureView (View view, OutputStream os) {
125134 if (bitmap == null ) {
126135 throw new RuntimeException ("Impossible to snapshot the view" );
127136 }
128- bitmap .compress (format , (int )(100.0 * quality ), os );
137+ return bitmap ;
138+ }
139+
140+ /**
141+ * As Bitmap.compress() may take a long time, it's better to
142+ * call it in a separate thread
143+ *
144+ * @param bitmap image to convert
145+ * @param os output stream
146+ */
147+ private void convertImageToData (Bitmap bitmap , OutputStream os ) {
148+ bitmap .compress (format , (int ) (100.0 * quality ), os );
129149 }
130150}
0 commit comments