Pārlūkot izejas kodu

added support of RAW image format and zip-base64 packaging of the results

Oleksandr Kucherenko 6 gadus atpakaļ
vecāks
revīzija
de310f1b3d

+ 77
- 59
android/src/main/java/fr/greweb/reactnativeviewshot/RNViewShotModule.java Parādīt failu

@@ -1,35 +1,36 @@
1 1
 
2 2
 package fr.greweb.reactnativeviewshot;
3 3
 
4
+import android.app.Activity;
4 5
 import android.content.Context;
5
-import android.graphics.Bitmap;
6 6
 import android.net.Uri;
7 7
 import android.os.AsyncTask;
8
-import android.os.Environment;
8
+import android.support.annotation.NonNull;
9 9
 import android.util.DisplayMetrics;
10
-import android.view.View;
11
-
12
-import com.facebook.react.bridge.ReactApplicationContext;
13
-import com.facebook.react.bridge.ReactContextBaseJavaModule;
14
-import com.facebook.react.bridge.ReactMethod;
10
+import android.util.Log;
15 11
 
16 12
 import com.facebook.react.bridge.GuardedAsyncTask;
17
-import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
18 13
 import com.facebook.react.bridge.Promise;
14
+import com.facebook.react.bridge.ReactApplicationContext;
19 15
 import com.facebook.react.bridge.ReactContext;
16
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
17
+import com.facebook.react.bridge.ReactMethod;
20 18
 import com.facebook.react.bridge.ReadableMap;
21
-import com.facebook.react.uimanager.UIBlock;
22 19
 import com.facebook.react.uimanager.UIManagerModule;
23 20
 
24 21
 import java.io.File;
25 22
 import java.io.FilenameFilter;
26 23
 import java.io.IOException;
27 24
 import java.util.Collections;
28
-import java.util.HashMap;
29 25
 import java.util.Map;
30 26
 
27
+import fr.greweb.reactnativeviewshot.ViewShot.Formats;
28
+import fr.greweb.reactnativeviewshot.ViewShot.Results;
29
+
31 30
 public class RNViewShotModule extends ReactContextBaseJavaModule {
32 31
 
32
+    public static final String RNVIEW_SHOT = "RNViewShot";
33
+
33 34
     private final ReactApplicationContext reactContext;
34 35
 
35 36
     public RNViewShotModule(ReactApplicationContext reactContext) {
@@ -39,7 +40,7 @@ public class RNViewShotModule extends ReactContextBaseJavaModule {
39 40
 
40 41
     @Override
41 42
     public String getName() {
42
-        return "RNViewShot";
43
+        return RNVIEW_SHOT;
43 44
     }
44 45
 
45 46
     @Override
@@ -67,30 +68,40 @@ public class RNViewShotModule extends ReactContextBaseJavaModule {
67 68
 
68 69
     @ReactMethod
69 70
     public void captureRef(int tag, ReadableMap options, Promise promise) {
70
-        ReactApplicationContext context = getReactApplicationContext();
71
-        String format = options.getString("format");
72
-        Bitmap.CompressFormat compressFormat =
73
-          format.equals("jpg")
74
-          ? Bitmap.CompressFormat.JPEG
75
-          : format.equals("webm")
76
-          ? Bitmap.CompressFormat.WEBP
77
-          : Bitmap.CompressFormat.PNG;
78
-        double quality = options.getDouble("quality");
79
-        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
80
-        Integer width = options.hasKey("width") ? (int)(displayMetrics.density * options.getDouble("width")) : null;
81
-        Integer height = options.hasKey("height") ? (int)(displayMetrics.density * options.getDouble("height")) : null;
82
-        String result = options.getString("result");
83
-        Boolean snapshotContentContainer = options.getBoolean("snapshotContentContainer");
71
+        final ReactApplicationContext context = getReactApplicationContext();
72
+        final DisplayMetrics dm = context.getResources().getDisplayMetrics();
73
+
74
+        final String extension = options.getString("format");
75
+        final int imageFormat = "jpg".equals(extension)
76
+                ? Formats.JPEG
77
+                : "webm".equals(extension)
78
+                ? Formats.WEBP
79
+                : "raw".equals(extension)
80
+                ? Formats.RAW
81
+                : Formats.PNG;
82
+
83
+        final double quality = options.getDouble("quality");
84
+        final Integer scaleWidth = options.hasKey("width") ? (int) (dm.density * options.getDouble("width")) : null;
85
+        final Integer scaleHeight = options.hasKey("height") ? (int) (dm.density * options.getDouble("height")) : null;
86
+        final String resultStreamFormat = options.getString("result");
87
+        final Boolean snapshotContentContainer = options.getBoolean("snapshotContentContainer");
88
+
84 89
         try {
85
-            File file = null;
86
-            if ("tmpfile".equals(result)) {
87
-              file = createTempFile(getReactApplicationContext(), format);
90
+            File outputFile = null;
91
+            if (Results.TEMP_FILE.equals(resultStreamFormat)) {
92
+                outputFile = createTempFile(getReactApplicationContext(), extension);
88 93
             }
89
-            UIManagerModule uiManager = this.reactContext.getNativeModule(UIManagerModule.class);
90
-            uiManager.addUIBlock(new ViewShot(tag, format, compressFormat, quality, width, height, file, result, snapshotContentContainer,reactContext, getCurrentActivity(), promise));
91
-        }
92
-        catch (Exception e) {
93
-            promise.reject(ViewShot.ERROR_UNABLE_TO_SNAPSHOT, "Failed to snapshot view tag "+tag);
94
+
95
+            final Activity activity = getCurrentActivity();
96
+            final UIManagerModule uiManager = this.reactContext.getNativeModule(UIManagerModule.class);
97
+
98
+            uiManager.addUIBlock(new ViewShot(
99
+                    tag, extension, imageFormat, quality,
100
+                    scaleWidth, scaleHeight, outputFile, resultStreamFormat,
101
+                    snapshotContentContainer, reactContext, activity, promise)
102
+            );
103
+        } catch (final Throwable ignored) {
104
+            promise.reject(ViewShot.ERROR_UNABLE_TO_SNAPSHOT, "Failed to snapshot view tag " + tag);
94 105
         }
95 106
     }
96 107
 
@@ -106,34 +117,41 @@ public class RNViewShotModule extends ReactContextBaseJavaModule {
106 117
      * image files. This is run when the catalyst instance is being destroyed (i.e. app is shutting
107 118
      * down) and when the module is instantiated, to handle the case where the app crashed.
108 119
      */
109
-    private static class CleanTask extends GuardedAsyncTask<Void, Void> {
110
-        private final Context mContext;
120
+    private static class CleanTask extends GuardedAsyncTask<Void, Void> implements FilenameFilter {
121
+        private final File cacheDir;
122
+        private final File externalCacheDir;
111 123
 
112 124
         private CleanTask(ReactContext context) {
113 125
             super(context);
114
-            mContext = context;
126
+
127
+            cacheDir = context.getCacheDir();
128
+            externalCacheDir = context.getExternalCacheDir();
115 129
         }
116 130
 
117 131
         @Override
118 132
         protected void doInBackgroundGuarded(Void... params) {
119
-            cleanDirectory(mContext.getCacheDir());
120
-            File externalCacheDir = mContext.getExternalCacheDir();
133
+            if (null != cacheDir) {
134
+                cleanDirectory(cacheDir);
135
+            }
136
+
121 137
             if (externalCacheDir != null) {
122 138
                 cleanDirectory(externalCacheDir);
123 139
             }
124 140
         }
125 141
 
126
-        private void cleanDirectory(File directory) {
127
-            File[] toDelete = directory.listFiles(
128
-                    new FilenameFilter() {
129
-                        @Override
130
-                        public boolean accept(File dir, String filename) {
131
-                            return filename.startsWith(TEMP_FILE_PREFIX);
132
-                        }
133
-                    });
142
+        @Override
143
+        public final boolean accept(File dir, String filename) {
144
+            return filename.startsWith(TEMP_FILE_PREFIX);
145
+        }
146
+
147
+        private void cleanDirectory(@NonNull final File directory) {
148
+            final File[] toDelete = directory.listFiles(this);
149
+
134 150
             if (toDelete != null) {
135
-                for (File file: toDelete) {
136
-                    file.delete();
151
+                for (File file : toDelete) {
152
+                    if (file.delete()) {
153
+                        Log.d(RNVIEW_SHOT, "deleted file: " + file.getAbsolutePath());
154
+                    }
137 155
                 }
138 156
             }
139 157
         }
@@ -143,26 +161,26 @@ public class RNViewShotModule extends ReactContextBaseJavaModule {
143 161
      * Create a temporary file in the cache directory on either internal or external storage,
144 162
      * whichever is available and has more free space.
145 163
      */
146
-    private File createTempFile(Context context, String ext)
147
-            throws IOException {
148
-        File externalCacheDir = context.getExternalCacheDir();
149
-        File internalCacheDir = context.getCacheDir();
150
-        File cacheDir;
164
+    @NonNull
165
+    private File createTempFile(@NonNull final Context context, @NonNull final String ext) throws IOException {
166
+        final File externalCacheDir = context.getExternalCacheDir();
167
+        final File internalCacheDir = context.getCacheDir();
168
+        final File cacheDir;
169
+
151 170
         if (externalCacheDir == null && internalCacheDir == null) {
152 171
             throw new IOException("No cache directory available");
153 172
         }
173
+
154 174
         if (externalCacheDir == null) {
155 175
             cacheDir = internalCacheDir;
156
-        }
157
-        else if (internalCacheDir == null) {
176
+        } else if (internalCacheDir == null) {
158 177
             cacheDir = externalCacheDir;
159 178
         } else {
160 179
             cacheDir = externalCacheDir.getFreeSpace() > internalCacheDir.getFreeSpace() ?
161 180
                     externalCacheDir : internalCacheDir;
162 181
         }
163
-        String suffix = "." + ext;
164
-        File tmpFile = File.createTempFile(TEMP_FILE_PREFIX, suffix, cacheDir);
165
-        return tmpFile;
166
-    }
167 182
 
183
+        final String suffix = "." + ext;
184
+        return File.createTempFile(TEMP_FILE_PREFIX, suffix, cacheDir);
185
+    }
168 186
 }