Browse Source

Convert image to data in a separate thread

LionelWei 7 years ago
parent
commit
45061cc62a
1 changed files with 60 additions and 40 deletions
  1. 60
    40
      android/src/main/java/fr/greweb/reactnativeviewshot/ViewShot.java

+ 60
- 40
android/src/main/java/fr/greweb/reactnativeviewshot/ViewShot.java View File

@@ -1,6 +1,7 @@
1 1
 package fr.greweb.reactnativeviewshot;
2 2
 
3 3
 import javax.annotation.Nullable;
4
+
4 5
 import android.graphics.Bitmap;
5 6
 import android.graphics.Canvas;
6 7
 import android.net.Uri;
@@ -16,6 +17,8 @@ import java.io.File;
16 17
 import java.io.FileOutputStream;
17 18
 import java.io.IOException;
18 19
 import java.io.OutputStream;
20
+import java.util.concurrent.ExecutorService;
21
+import java.util.concurrent.Executors;
19 22
 
20 23
 /**
21 24
  * Snapshot utility class allow to screenshot a view.
@@ -24,6 +27,8 @@ public class ViewShot implements UIBlock {
24 27
 
25 28
     static final String ERROR_UNABLE_TO_SNAPSHOT = "E_UNABLE_TO_SNAPSHOT";
26 29
 
30
+    private final static ExecutorService sExecutor = Executors.newFixedThreadPool(5);
31
+
27 32
     private int tag;
28 33
     private String extension;
29 34
     private Bitmap.CompressFormat format;
@@ -57,59 +62,63 @@ public class ViewShot implements UIBlock {
57 62
 
58 63
     @Override
59 64
     public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
60
-        OutputStream os = null;
61 65
         View view = nativeViewHierarchyManager.resolveView(tag);
62 66
         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);
64 68
             return;
65 69
         }
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;
98 75
                 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) {
101 98
                     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
+                    }
102 108
                 }
103 109
             }
104
-        }
110
+        });
111
+
112
+
105 113
     }
106 114
 
107 115
     /**
108 116
      * Screenshot a view and return the captured bitmap.
117
+     *
109 118
      * @param view the view to capture
110
-     * @return the screenshot or null if it failed.
119
+     * @return bitmap drawn by view
111 120
      */
112
-    private void captureView (View view, OutputStream os) {
121
+    private Bitmap captureView(View view) {
113 122
         int w = view.getWidth();
114 123
         int h = view.getHeight();
115 124
         if (w <= 0 || h <= 0) {
@@ -125,6 +134,17 @@ public class ViewShot implements UIBlock {
125 134
         if (bitmap == null) {
126 135
             throw new RuntimeException("Impossible to snapshot the view");
127 136
         }
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);
129 149
     }
130 150
 }