react-native-image-compression-kit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +562 -0
- package/android/build.gradle +63 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/com/imagecompressionkit/ImageCompressionKitModule.kt +1127 -0
- package/android/src/main/java/com/imagecompressionkit/ImageCompressionKitPackage.kt +33 -0
- package/android/src/main/java/com/imagecompressionkit/ImageCompressionOutput.kt +396 -0
- package/android/src/main/java/com/imagecompressionkit/JpegExifMetadata.kt +233 -0
- package/ios/RCTImageCompressionKit.h +10 -0
- package/ios/RCTImageCompressionKit.mm +72 -0
- package/lib/NativeImageCompressionKit.d.ts +55 -0
- package/lib/NativeImageCompressionKit.d.ts.map +1 -0
- package/lib/NativeImageCompressionKit.js +5 -0
- package/lib/NativeImageCompressionKit.js.map +1 -0
- package/lib/api.d.ts +4 -0
- package/lib/api.d.ts.map +1 -0
- package/lib/api.js +25 -0
- package/lib/api.js.map +1 -0
- package/lib/errors.d.ts +9 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +53 -0
- package/lib/errors.js.map +1 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +14 -0
- package/lib/index.js.map +1 -0
- package/lib/nativeModule.d.ts +7 -0
- package/lib/nativeModule.d.ts.map +1 -0
- package/lib/nativeModule.js +73 -0
- package/lib/nativeModule.js.map +1 -0
- package/lib/types.d.ts +59 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +23 -0
- package/lib/types.js.map +1 -0
- package/lib/validation.d.ts +3 -0
- package/lib/validation.d.ts.map +1 -0
- package/lib/validation.js +108 -0
- package/lib/validation.js.map +1 -0
- package/package.json +106 -0
- package/react-native-image-compression-kit.podspec +21 -0
- package/react-native.config.js +12 -0
- package/src/NativeImageCompressionKit.ts +81 -0
- package/src/api.ts +28 -0
- package/src/errors.ts +91 -0
- package/src/index.ts +25 -0
- package/src/nativeModule.ts +130 -0
- package/src/types.ts +88 -0
- package/src/validation.ts +181 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 react-native-image-compression-kit contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
<h1 align="center">React Native Image Compression Kit</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
Compress any supported image. Return it in the format you choose.
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
A planned native image compression and transcoding pipeline for React Native Android and iOS.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<img alt="Status: Android Image MVP" src="https://img.shields.io/badge/Status-Android%20Image%20MVP-blue" />
|
|
13
|
+
<img alt="Platforms: Android | iOS" src="https://img.shields.io/badge/Platforms-Android%20%7C%20iOS-green" />
|
|
14
|
+
<img alt="React Native" src="https://img.shields.io/badge/React%20Native-planned-61dafb" />
|
|
15
|
+
<img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-planned-3178c6" />
|
|
16
|
+
<img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow" />
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
React Native Image Compression Kit is a native image compression and transcoding pipeline that loads any supported image format, compresses it, and returns it in a supported format selected by the developer.
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
React Native image compression workflows are often split across format-specific or feature-specific modules. Compression, resizing, HEIC conversion, WebP handling, metadata policy, and platform capability checks can become separate decisions instead of one predictable pipeline.
|
|
24
|
+
|
|
25
|
+
This project is designed to make compression the center of the API. It will combine detect, decode, auto-orient, resize, transcode, and encode steps behind one consistent React Native interface.
|
|
26
|
+
|
|
27
|
+
Format conversion is treated as part of the compression result. Developers choose the supported output format they want, and the native pipeline handles the work needed to produce it.
|
|
28
|
+
|
|
29
|
+
## Status
|
|
30
|
+
|
|
31
|
+
This project is currently in the design and early Android MVP phase. The TypeScript API contract, React Native Codegen spec, Android native module, Android example app, iOS stub, unit test foundation, and npm package metadata for the initial `0.1.0` release are in place, but the package has not been published to npm yet.
|
|
32
|
+
|
|
33
|
+
Android includes an image compression MVP for `file://` and `content://` JPEG, PNG, WebP, GIF, HEIC, HEIF, and AVIF inputs, JPEG EXIF orientation correction, optional resize, metadata `preserve` / privacy-filtered `safe` / `strip` handling for JPEG source to JPEG output, and JPEG, PNG, or WebP output encoding. GIF input is decoded as a static first frame. HEIC / HEIF input is Android SDK and device-codec dependent: API 28+ uses `ImageDecoder`, API 26-27 attempts a guarded `BitmapFactory` fallback, and earlier Android versions reject HEIC / HEIF with `ERR_UNSUPPORTED_FORMAT`. AVIF input is Android 14+ only and uses `ImageDecoder`. GIF output, GIF animation preservation, HEIC / HEIF output, AVIF output, iOS compression, and broader input format support are not implemented yet.
|
|
34
|
+
|
|
35
|
+
## Current Implementation Scope
|
|
36
|
+
|
|
37
|
+
The current implementation is intentionally small:
|
|
38
|
+
|
|
39
|
+
- Android only.
|
|
40
|
+
- `file://` and `content://` local URI input.
|
|
41
|
+
- JPEG, PNG, WebP, GIF, HEIC, HEIF, and AVIF input. GIF input is static first-frame only, HEIC / HEIF input depends on Android SDK and device codec support, and AVIF input requires Android 14+ baseline image support.
|
|
42
|
+
- JPEG, PNG, and WebP output.
|
|
43
|
+
- Quality-based compression for JPEG and WebP output. PNG output ignores `quality`.
|
|
44
|
+
- Target-size compression with `maxBytes` for JPEG and WebP output. PNG output rejects `maxBytes`.
|
|
45
|
+
- JPEG EXIF orientation correction before resize and selected output encoding.
|
|
46
|
+
- Optional resize with `maxWidth`, `maxHeight`, and `contain`, `cover`, or `stretch` mode.
|
|
47
|
+
- Metadata `preserve`, privacy-filtered `safe`, and `strip` policies for JPEG source to JPEG output. PNG/WebP/GIF/HEIC/HEIF/AVIF sources and PNG/WebP output do not preserve source EXIF metadata.
|
|
48
|
+
- Output file written to the Android app cache directory.
|
|
49
|
+
- `CompressionResult` returns `uri`, `format`, final `width`, final `height`, `byteSize`, `originalByteSize`, and `compressionRatio`.
|
|
50
|
+
|
|
51
|
+
The following remain planned and are not implemented in the MVP:
|
|
52
|
+
|
|
53
|
+
- iOS compression.
|
|
54
|
+
- AVIF output.
|
|
55
|
+
- HEIC / HEIF output.
|
|
56
|
+
- GIF output and GIF/WebP animation preservation.
|
|
57
|
+
- Metadata support for non-JPEG formats and iOS.
|
|
58
|
+
|
|
59
|
+
## Why
|
|
60
|
+
|
|
61
|
+
Image handling in React Native can become fragmented when compression, HEIC conversion, WebP processing, resizing, and metadata handling live in separate tools. That fragmentation can lead to:
|
|
62
|
+
|
|
63
|
+
- Different APIs for different formats.
|
|
64
|
+
- Platform-specific behavior that is difficult to predict.
|
|
65
|
+
- Limited support for target file size compression.
|
|
66
|
+
- Image processing logic coupled too tightly to upload logic.
|
|
67
|
+
- Extra application code for capability checks and fallback paths.
|
|
68
|
+
|
|
69
|
+
React Native Image Compression Kit aims to provide one native-first API for image compression while staying composable with any uploader or storage layer.
|
|
70
|
+
|
|
71
|
+
## Core Concept
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
Supported input image
|
|
75
|
+
↓
|
|
76
|
+
Detect and decode
|
|
77
|
+
↓
|
|
78
|
+
Auto-orient
|
|
79
|
+
↓
|
|
80
|
+
Resize when needed
|
|
81
|
+
↓
|
|
82
|
+
Compress
|
|
83
|
+
↓
|
|
84
|
+
Encode in selected format
|
|
85
|
+
↓
|
|
86
|
+
Local output URI
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Any supported image in. A compressed image out, in your chosen supported format.
|
|
90
|
+
|
|
91
|
+
## Planned Features
|
|
92
|
+
|
|
93
|
+
The following product features are planned or only partially implemented.
|
|
94
|
+
|
|
95
|
+
- Automatic format detection.
|
|
96
|
+
- Quality-based compression.
|
|
97
|
+
- Target file size compression with `maxBytes`. Android MVP support is implemented for JPEG and WebP output.
|
|
98
|
+
- Optional resize during compression. Android MVP support is implemented.
|
|
99
|
+
- Output format selection. Android MVP supports JPEG, PNG, WebP, static first-frame GIF, SDK-gated HEIC / HEIF, and Android 14+ AVIF input with JPEG, PNG, and WebP output.
|
|
100
|
+
- Automatic EXIF orientation correction. Android MVP support is implemented for JPEG input.
|
|
101
|
+
- Metadata preservation and stripping policies. Android MVP supports `preserve`, `safe`, and `strip` for JPEG source to JPEG output.
|
|
102
|
+
- Alpha-channel handling.
|
|
103
|
+
- Local URI input and output.
|
|
104
|
+
- Compression statistics.
|
|
105
|
+
- Cancellation.
|
|
106
|
+
- Runtime capability inspection.
|
|
107
|
+
- Android and iOS support.
|
|
108
|
+
- React Native New Architecture-first design.
|
|
109
|
+
|
|
110
|
+
## Planned Format Support
|
|
111
|
+
|
|
112
|
+
The table below describes planned input and output support. Actual availability may depend on platform codecs and will be reported through runtime capability APIs.
|
|
113
|
+
|
|
114
|
+
| Format | Planned input | Planned output | Notes |
|
|
115
|
+
|---|---:|---:|---|
|
|
116
|
+
| JPEG | Yes | Yes | Lossy compression |
|
|
117
|
+
| PNG | Yes | Yes | Lossless compression |
|
|
118
|
+
| WebP | Yes | Yes | Lossy and lossless |
|
|
119
|
+
| HEIC / HEIF | Yes | Optional / later | Android input implemented with SDK and codec gating |
|
|
120
|
+
| AVIF | Yes | Later | Android input implemented on API 34+ with ImageDecoder |
|
|
121
|
+
| GIF | Yes | Later | Static first-frame support before animation preservation |
|
|
122
|
+
|
|
123
|
+
Current Android MVP support is narrower than the planned table: JPEG, PNG, WebP, static first-frame GIF, SDK-gated HEIC, SDK-gated HEIF, and Android 14+ AVIF input are implemented, and JPEG, PNG, and WebP output are implemented. GIF output, GIF animation preservation, animated WebP, HEIC / HEIF output, and AVIF output remain planned. HEIC / HEIF inputs on Android versions below 8.0 and AVIF inputs on Android versions below 14 reject as `ERR_UNSUPPORTED_FORMAT`. Corrupt supported-format inputs, including corrupt GIF, HEIC / HEIF, and AVIF candidates on supported SDKs, reject as `ERR_DECODE_FAILED`.
|
|
124
|
+
|
|
125
|
+
Animation preservation for GIF, animated WebP, and animated AVIF is not planned as an initial-version guarantee.
|
|
126
|
+
|
|
127
|
+
## Android HEIC / HEIF Input
|
|
128
|
+
|
|
129
|
+
Android platform documentation lists [HEIF decode support on Android 8.0+](https://developer.android.com/media/platform/supported-formats) for `.heic` and `.heif` files, while the Java [`ImageDecoder` API](https://developer.android.com/reference/android/graphics/ImageDecoder) is available from API 28 and explicitly supports decoding HEIF into drawable or bitmap outputs. The Android implementation route is:
|
|
130
|
+
|
|
131
|
+
- Use `ImageDecoder` on API 28+ for HEIC / HEIF input and force software bitmap allocation before resize and output encoding.
|
|
132
|
+
- Attempt a guarded `BitmapFactory` HEIF decode fallback on API 26-27, because platform HEIF decode support exists there but remains device codec dependent.
|
|
133
|
+
- Reject HEIC / HEIF inputs with `ERR_UNSUPPORTED_FORMAT` below Android 8.0.
|
|
134
|
+
- Keep HEIC / HEIF output unsupported unless a later goal explicitly designs it.
|
|
135
|
+
|
|
136
|
+
Runtime capabilities currently expose HEIC / HEIF with `input=true` and `output=false`, plus notes that describe the Android 8.0+ platform decode condition, the API 28+ `ImageDecoder` route, the API 26-27 guarded `BitmapFactory` fallback, and the unsupported output state. The main CI validates the version-gated structure and rejection boundaries, and the separate Android Instrumentation workflow validates committed HEIC / HEIF sample decoding on an API 35 emulator.
|
|
137
|
+
|
|
138
|
+
## Android AVIF Input
|
|
139
|
+
|
|
140
|
+
Android platform documentation lists AVIF baseline image support as mandatory on Android 14+. The Android implementation route is:
|
|
141
|
+
|
|
142
|
+
- Use `ImageDecoder` on API 34+ for AVIF input and force software bitmap allocation before resize and output encoding.
|
|
143
|
+
- Reject AVIF inputs with `ERR_UNSUPPORTED_FORMAT` below Android 14.
|
|
144
|
+
- Keep AVIF output unsupported unless a later goal explicitly designs it.
|
|
145
|
+
|
|
146
|
+
Runtime capabilities currently expose AVIF with `input=true` and `output=false`, plus notes that describe the Android 14+ `ImageDecoder` route, static image support, no EXIF metadata copy, unsupported animation preservation, and unsupported output state. The main CI validates the API-gated unsupported boundary and corrupt-candidate decode failure behavior, and the separate Android Instrumentation workflow validates committed AVIF sample decoding on an API 35 emulator.
|
|
147
|
+
|
|
148
|
+
## HEIC / HEIF / AVIF Codec Sample Validation Strategy
|
|
149
|
+
|
|
150
|
+
This repository now commits tiny HEIC / HEIF / AVIF samples generated from repo-owned PNG sources. The fixture paths are:
|
|
151
|
+
|
|
152
|
+
- Use `android/src/test/assets/heic-heif/source.png`, a repo-owned 16x12 RGB PNG pattern with no user-photo content.
|
|
153
|
+
- Track source and generated output metadata in `android/src/test/assets/heic-heif/manifest.json`.
|
|
154
|
+
- Validate the source image, manifest fields, and committed sample files with `pnpm fixtures:heic-heif:check`.
|
|
155
|
+
- Generate or refresh committed fixtures with `pnpm fixtures:heic-heif`, which uses `heif-enc --quality 80 source.png -o sample.heic` and `heif-enc --quality 80 source.png -o sample.heif`.
|
|
156
|
+
- Generated fixtures are committed because they are tiny, repo-owned derivative assets, and covered by MIT provenance in the manifest.
|
|
157
|
+
- Store committed fixtures under `android/src/test/assets/heic-heif/` so Android runtime tests can load them without depending on network access.
|
|
158
|
+
- When regenerating with a different `libheif` / `heif-enc` version, update byte size, SHA-256, generator version, dimensions, generation command, and license/provenance in the manifest.
|
|
159
|
+
- Use `android/src/test/assets/avif/source.png` and `android/src/test/assets/avif/sample.avif` for AVIF runtime validation.
|
|
160
|
+
- Validate the AVIF source image, manifest fields, and committed sample file with `pnpm fixtures:avif:check`.
|
|
161
|
+
- Generate or refresh the committed AVIF fixture with `pnpm fixtures:avif`, which uses `heif-enc --quality 80 --avif source.png -o sample.avif`.
|
|
162
|
+
|
|
163
|
+
Current lightweight coverage is intentionally narrower than real codec validation. `pnpm verify`, `pnpm example:android-unit-test`, and the main GitHub Actions CI validate the HEIC / HEIF / AVIF MIME and extension routing, SDK gates, capability notes, corrupt-candidate rejection boundaries, and committed fixture metadata. They verify the fixture files and metadata, but they do not boot an emulator.
|
|
164
|
+
|
|
165
|
+
A separate Android Instrumentation workflow enables KVM permissions, boots an API 35 Google APIs emulator with an extended boot timeout, and runs `pnpm example:android-instrumentation`. That task executes `:react-native-image-compression-kit:connectedDebugAndroidTest` and validates the committed `sample.heic`, `sample.heif`, and `sample.avif` fixtures through their `ImageDecoder` routes, asserting JPEG, PNG, and WebP output success with 16x12 result dimensions and byte-signature checks.
|
|
166
|
+
|
|
167
|
+
Manual codec validation beyond CI should use a codec-backed Android device or emulator on API 28+ first, because that also exercises the `ImageDecoder` route through the example app. After installing the example app, copy a fixture into the app-private files directory and paste the resulting file URI into the example screen:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
pnpm example:android
|
|
171
|
+
adb shell run-as com.imagecompressionkit.example mkdir -p files/rnick-codec
|
|
172
|
+
adb shell run-as com.imagecompressionkit.example sh -c 'cat > files/rnick-codec/sample.heic' < android/src/test/assets/heic-heif/sample.heic
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Then use `file:///data/data/com.imagecompressionkit.example/files/rnick-codec/sample.heic` as the source URI and verify JPEG, PNG, and WebP outputs. Repeat with `sample.heif`. API 26-27 should still be checked separately for the guarded `BitmapFactory` fallback because emulator/device codec availability can differ from API 28+.
|
|
176
|
+
|
|
177
|
+
For AVIF manual validation, use an API 34+ device or emulator and repeat the copy/paste flow with `android/src/test/assets/avif/sample.avif`.
|
|
178
|
+
|
|
179
|
+
## Proposed API
|
|
180
|
+
|
|
181
|
+
The API below is proposed and is not available in a published package yet.
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
import { compressImage } from 'react-native-image-compression-kit';
|
|
185
|
+
|
|
186
|
+
const result = await compressImage({
|
|
187
|
+
source: {
|
|
188
|
+
uri: imageUri,
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
resize: {
|
|
192
|
+
maxWidth: 2048,
|
|
193
|
+
maxHeight: 2048,
|
|
194
|
+
mode: 'contain',
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
output: {
|
|
198
|
+
format: 'webp',
|
|
199
|
+
quality: 80,
|
|
200
|
+
maxBytes: 500_000,
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
metadata: 'safe',
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Example proposed result:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
{
|
|
211
|
+
uri: 'file:///...',
|
|
212
|
+
format: 'webp',
|
|
213
|
+
width: 2048,
|
|
214
|
+
height: 1365,
|
|
215
|
+
byteSize: 482_319,
|
|
216
|
+
originalByteSize: 3_814_220,
|
|
217
|
+
compressionRatio: 0.126,
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Compression Modes
|
|
222
|
+
|
|
223
|
+
### 1. Quality-based compression
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
output: {
|
|
227
|
+
format: 'jpeg',
|
|
228
|
+
quality: 80,
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### 2. Compression with resize
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
resize: {
|
|
236
|
+
maxWidth: 2048,
|
|
237
|
+
maxHeight: 2048,
|
|
238
|
+
mode: 'contain',
|
|
239
|
+
},
|
|
240
|
+
output: {
|
|
241
|
+
format: 'jpeg',
|
|
242
|
+
quality: 80,
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Android MVP resize supports `contain`, `cover`, and `stretch`. JPEG EXIF orientation is applied before resize, and the result `width` and `height` describe the final encoded image dimensions after orientation correction and resize.
|
|
247
|
+
|
|
248
|
+
### 3. Target-size compression
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
output: {
|
|
252
|
+
format: 'webp',
|
|
253
|
+
maxBytes: 500_000,
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Android MVP target-size compression treats `quality` as the upper quality bound when both `quality` and `maxBytes` are provided. If `quality` is omitted, Android starts from the default quality. It searches for the highest JPEG or WebP quality that fits under `maxBytes`; if even the lowest quality cannot fit, it returns the smallest generated output instead. PNG output does not support `maxBytes`. `maxBytes` is not intended to guarantee an exact byte size for every source image, format, platform, or codec.
|
|
258
|
+
|
|
259
|
+
### 4. Compression with format conversion
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
output: {
|
|
263
|
+
format: 'webp',
|
|
264
|
+
quality: 65,
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Metadata Policy
|
|
269
|
+
|
|
270
|
+
The proposed API includes three metadata policies:
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
metadata: 'preserve'
|
|
274
|
+
metadata: 'safe'
|
|
275
|
+
metadata: 'strip'
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Android MVP currently supports `preserve`, `safe`, and `strip` for JPEG source to JPEG output. JPEG EXIF orientation is applied to pixels before encoding, so output orientation metadata is normalized instead of preserving the original rotation flag. PNG/WebP/GIF/HEIC/HEIF/AVIF sources and PNG/WebP output do not copy source EXIF metadata.
|
|
279
|
+
|
|
280
|
+
`safe` is the default policy. In the Android MVP it copies a privacy-filtered JPEG EXIF allowlist into JPEG output, including common camera, date/time, exposure, lens, and color-space attributes. It excludes GPS/location, owner/serial identifiers, maker note, user comment, image-unique ID, XMP, and other broad free-form metadata.
|
|
281
|
+
|
|
282
|
+
`strip` removes metadata from the encoded output where possible through JPEG re-encode.
|
|
283
|
+
|
|
284
|
+
`preserve` copies supported source EXIF attributes into the output JPEG, including camera, date/time, exposure, lens, GPS, and XMP attributes. Output orientation is set to normal after pixels are transformed, and output EXIF width/height tags are updated to the final encoded dimensions. ICC color profile preservation remains planned.
|
|
285
|
+
|
|
286
|
+
## Design Principles
|
|
287
|
+
|
|
288
|
+
- Compression first.
|
|
289
|
+
- One decode and encode pipeline.
|
|
290
|
+
- Native processing.
|
|
291
|
+
- Predictable output.
|
|
292
|
+
- Explicit capability reporting.
|
|
293
|
+
- No silent animation loss.
|
|
294
|
+
- No silent alpha-channel loss.
|
|
295
|
+
- Safe defaults.
|
|
296
|
+
- Composable with any uploader.
|
|
297
|
+
|
|
298
|
+
The target architecture avoids moving full pixel data through JavaScript. Native code should do decode, transform, compress, and encode work, then return a local output URI and result metadata to JavaScript.
|
|
299
|
+
|
|
300
|
+
## Non-goals
|
|
301
|
+
|
|
302
|
+
This project is not intended to handle:
|
|
303
|
+
|
|
304
|
+
- Uploading images.
|
|
305
|
+
- Remote image downloading.
|
|
306
|
+
- Rendering or caching images.
|
|
307
|
+
- Replacing an image picker.
|
|
308
|
+
- Supporting every existing image format or camera RAW format.
|
|
309
|
+
- Providing a full image editor.
|
|
310
|
+
- Guaranteeing identical encoded bytes across Android and iOS.
|
|
311
|
+
- CDN optimization, lazy loading, gallery UI, or photo management workflows.
|
|
312
|
+
|
|
313
|
+
## Roadmap
|
|
314
|
+
|
|
315
|
+
- [x] Repository and API design.
|
|
316
|
+
- [x] Initial TypeScript public API contract.
|
|
317
|
+
- [x] Unit test foundation for API and validation.
|
|
318
|
+
- [x] React Native Codegen and native module foundation.
|
|
319
|
+
- [x] Android JPEG to JPEG quality compression MVP.
|
|
320
|
+
- [x] Android JPEG EXIF orientation correction.
|
|
321
|
+
- [x] Android JPEG resize support.
|
|
322
|
+
- [x] Android JPEG target-size compression.
|
|
323
|
+
- [x] Android JPEG input to PNG and WebP output encoding.
|
|
324
|
+
- [x] Android PNG and WebP input support.
|
|
325
|
+
- [x] Android JPEG-input output format behavior and byte signature JVM tests.
|
|
326
|
+
- [x] Android JPEG-input module-level compression integration JVM tests.
|
|
327
|
+
- [x] Android `content://` JPEG source module-level JVM tests.
|
|
328
|
+
- [x] Android PNG/WebP input module-level JVM tests.
|
|
329
|
+
- [x] Android PNG/WebP input resize, target-size, and metadata no-copy regression JVM tests.
|
|
330
|
+
- [x] Android AVIF unsupported input and HEIC/HEIF SDK-gated decode-boundary JVM tests.
|
|
331
|
+
- [x] Android HEIC/HEIF input decode path and capability notes.
|
|
332
|
+
- [x] Android HEIC/HEIF real codec sample validation strategy.
|
|
333
|
+
- [x] Android HEIC/HEIF committed sample fixtures and manifest metadata.
|
|
334
|
+
- [x] Android AVIF input decode path, fixture manifest, and emulator validation.
|
|
335
|
+
- [x] Android GIF static first-frame input support.
|
|
336
|
+
- [x] Android GIF input module-level JVM tests for file/content URI, resize, target-size, and metadata no-copy behavior.
|
|
337
|
+
- [x] Android JPEG-input resize/orientation module-level JVM tests.
|
|
338
|
+
- [x] Android JPEG/WebP target-size module-level JVM tests.
|
|
339
|
+
- [x] Android JPEG metadata `safe` / `strip` policy basics.
|
|
340
|
+
- [x] Android JPEG metadata `preserve` EXIF copy.
|
|
341
|
+
- [x] Android JPEG metadata `safe` privacy-filtered EXIF copy.
|
|
342
|
+
- [x] Android JPEG metadata policy unit tests with real EXIF read/write.
|
|
343
|
+
- [x] Example application.
|
|
344
|
+
- [x] Example metadata policy selector and result summary.
|
|
345
|
+
- [x] Example output format selector for JPEG, PNG, and WebP.
|
|
346
|
+
- [x] Android HEIC / HEIF input.
|
|
347
|
+
- [x] Android HEIC / HEIF emulator/instrumentation validation.
|
|
348
|
+
- [x] Android AVIF input.
|
|
349
|
+
- [ ] AVIF output.
|
|
350
|
+
- [ ] Metadata support for non-JPEG formats and iOS.
|
|
351
|
+
- [ ] Cancellation and progress.
|
|
352
|
+
- [x] Public npm release.
|
|
353
|
+
|
|
354
|
+
## Installation
|
|
355
|
+
|
|
356
|
+
The initial `0.1.0` public release is distributed under `react-native-image-compression-kit`, with repository, issue tracker, homepage, MIT license, React Native peer dependency, CommonJS entrypoint, TypeScript declarations, React Native Codegen source, Android main sources, and the iOS stub included in the packed package. Development scripts, Android JVM tests, instrumentation tests, and codec fixtures are intentionally excluded from the publish tarball.
|
|
357
|
+
|
|
358
|
+
The repository contains an initial TypeScript API scaffold and an Android image MVP with JPEG/PNG/WebP/GIF/HEIC/HEIF/AVIF input, GIF static first-frame decoding, HEIC/HEIF SDK-gated input decoding, Android 14+ AVIF input decoding, JPEG EXIF orientation correction, optional resize, JPEG/PNG/WebP output encoding, JPEG/WebP target-size compression, and metadata `preserve` / privacy-filtered `safe` / `strip` handling for JPEG source to JPEG output. iOS compression, HEIC/HEIF output, AVIF output, and broader input format support are not implemented yet.
|
|
359
|
+
|
|
360
|
+
Install from npm:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
npm install react-native-image-compression-kit
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Example Application
|
|
367
|
+
|
|
368
|
+
The repository includes an Android React Native example app in `example/`. It links this local package through the pnpm workspace and exercises the Android JPEG/PNG/WebP/GIF input MVP against a `file://` or `content://` source URI.
|
|
369
|
+
|
|
370
|
+
Install dependencies from the repository root:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
pnpm install
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
Start Metro:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
pnpm example:start
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
In another terminal, run the Android app:
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
pnpm example:android
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
The example screen copies a bundled `sample.jpg` asset into the app cache and uses that cache file URI by default. You can also paste another local `file://` or `content://` JPEG, PNG, WebP, GIF, HEIC, HEIF, or AVIF URI. The screen calls:
|
|
389
|
+
|
|
390
|
+
```ts
|
|
391
|
+
compressImage({
|
|
392
|
+
source: { uri },
|
|
393
|
+
resize: {
|
|
394
|
+
maxWidth,
|
|
395
|
+
maxHeight,
|
|
396
|
+
mode,
|
|
397
|
+
},
|
|
398
|
+
output: {
|
|
399
|
+
format,
|
|
400
|
+
quality,
|
|
401
|
+
maxBytes,
|
|
402
|
+
},
|
|
403
|
+
metadata,
|
|
404
|
+
});
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
The example lets you choose JPEG, PNG, or WebP output and `preserve`, `safe`, or `strip` metadata handling before compression. It displays the current native output format capability list, the current native `metadataPolicies` capability list, the selected output format, the selected metadata policy, the compressed output URI, result format, final width and height, compressed byte size, original byte size, compression ratio, the metadata policy used for the latest result, and native error code/message when the call fails.
|
|
408
|
+
|
|
409
|
+
Android Codegen and native build checks can also be run through the example app:
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
pnpm example:codegen
|
|
413
|
+
pnpm example:android-unit-test
|
|
414
|
+
pnpm example:android-instrumentation
|
|
415
|
+
pnpm example:build
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
These commands require a Java runtime and Android SDK. `pnpm example:android-unit-test` runs Robolectric-backed Android JVM unit tests for the package, including real JPEG EXIF read/write coverage for metadata policies, native-graphics JPEG/PNG/WebP output checks for file byte signatures, and module-level `compressImage` coverage for file URI results, `content://` source parity and read failures, AVIF API-gated decode boundaries, HEIC/HEIF SDK-gated decode boundaries, HEIC/HEIF/AVIF capability notes, corrupt supported-format decode failures, PNG/WebP/GIF input, GIF static first-frame decoding, PNG/WebP/GIF input resize modes, PNG/WebP/GIF input target-size `maxBytes`, PNG/WebP/GIF metadata no-copy behavior, result metadata, resize modes, EXIF orientation normalization, JPEG/WebP target-size `maxBytes`, target-size fallback metadata, and PNG `maxBytes` rejection. `pnpm example:android-instrumentation` requires a connected API 34+ emulator or device and runs the committed HEIC/HEIF/AVIF sample-to-JPEG/PNG/WebP instrumentation test. `pnpm android:doctor` also validates the HEIC/HEIF and AVIF source and committed sample fixture manifests, byte sizes, SHA-256 hashes, and instrumentation wiring. `pnpm example:android` still requires a connected emulator/device.
|
|
419
|
+
|
|
420
|
+
## Continuous Integration
|
|
421
|
+
|
|
422
|
+
GitHub Actions runs the repository checks and Android example build on pushes to `master` and pull requests. The lightweight workflow is defined in `.github/workflows/ci.yml`.
|
|
423
|
+
|
|
424
|
+
The CI job uses Node.js 24, pnpm 11.7.0, Temurin JDK 21, Android SDK platform 36, Android build tools 36.0.0, and Android NDK 27.1.12297006. The GitHub Actions workflow actions are kept on Node 24 runtime-compatible majors: `actions/checkout@v7`, `actions/setup-node@v6`, `actions/setup-java@v5`, `android-actions/setup-android@v4`, `pnpm/action-setup@v6`, and `gradle/actions/setup-gradle@v6`. It enables pnpm and Gradle caching, then runs:
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
pnpm install --frozen-lockfile
|
|
428
|
+
pnpm verify
|
|
429
|
+
pnpm example:typecheck
|
|
430
|
+
pnpm example:codegen
|
|
431
|
+
pnpm example:android-unit-test
|
|
432
|
+
pnpm example:build
|
|
433
|
+
pnpm smoke:consumer
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
`pnpm example:codegen` runs React Native Codegen through the example app's Android Gradle project. `pnpm example:android-unit-test` runs Robolectric-backed Android JVM unit tests for native metadata policy behavior, native-graphics JPEG/PNG/WebP/GIF input and JPEG/PNG/WebP output format and byte-signature behavior, and module-level `compressImage` file URI, content URI, AVIF API-gated decode boundaries, HEIC/HEIF SDK-gated decode boundaries, HEIC/HEIF/AVIF capability-note structure, corrupt supported-format decode failure, GIF static first-frame decoding, PNG/WebP/GIF input resize, EXIF orientation, target-size, and metadata no-copy integration behavior. `pnpm example:build` assembles the Android debug build, which verifies the package can be compiled inside a real React Native app with the JPEG, PNG, WebP, GIF, HEIC, HEIF, and AVIF input paths and JPEG, PNG, and WebP output paths.
|
|
437
|
+
|
|
438
|
+
`pnpm smoke:consumer` builds the TypeScript output, creates a `pnpm pack` tarball, installs that tarball into a separate temporary React Native consumer project, and typechecks imports from `react-native-image-compression-kit` against the packed package. This pre-release smoke test verifies the npm package shape without publishing to npm or running Metro/native device builds. Set `RNICK_CONSUMER_SMOKE_KEEP=1` to keep the temporary project for inspection, or `RNICK_CONSUMER_SMOKE_TMPDIR=/path/to/tmp` to choose its parent directory.
|
|
439
|
+
|
|
440
|
+
The separate `.github/workflows/android-instrumentation.yml` workflow enables KVM permissions, boots an API 35 Google APIs emulator with an extended boot timeout, and runs `pnpm example:android-instrumentation`. This workflow validates that the committed HEIC, HEIF, and AVIF fixtures decode on the Android `ImageDecoder` paths and can be compressed to JPEG, PNG, and WebP. It stays separate from the lightweight CI because emulator startup and codec execution are slower and more environment-sensitive than JVM tests.
|
|
441
|
+
|
|
442
|
+
## Docker Android Build/Test Environment
|
|
443
|
+
|
|
444
|
+
The repository includes a Docker-based Android build/test environment for machines that do not have Java, Android SDK, build tools, CMake, or NDK installed locally. The root `Dockerfile` mirrors the lightweight CI environment with Node.js 24, pnpm 11.7.0, Temurin JDK 21, Android SDK platform 36, Android build tools 36.0.0, Android build tools 35.0.0 for React Native/AGP compatibility, CMake 3.22.1, and Android NDK 27.1.12297006.
|
|
445
|
+
|
|
446
|
+
Build the image:
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
pnpm docker:android:build
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
Run the full non-emulator Android verification flow in Docker:
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
pnpm docker:android:ci
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
That command installs dependencies inside Docker-managed volumes, then runs:
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
pnpm verify
|
|
462
|
+
pnpm example:typecheck
|
|
463
|
+
pnpm example:codegen
|
|
464
|
+
pnpm example:android-unit-test
|
|
465
|
+
pnpm example:build
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
You can also run individual Docker-backed checks:
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
pnpm docker:android:verify
|
|
472
|
+
pnpm docker:android:example:typecheck
|
|
473
|
+
pnpm docker:android:example:codegen
|
|
474
|
+
pnpm docker:android:example:android-unit-test
|
|
475
|
+
pnpm docker:android:example:build
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
The Docker runner uses `linux/amd64` by default so Android SDK build tools behave like the GitHub Actions Linux environment. It bind-mounts the repository at `/workspace`, disables Gradle VFS watching for Docker bind-mount stability, and uses named Docker volumes for `node_modules`, the pnpm store, and the Gradle home cache so container dependencies do not overwrite the host install. Override the image, platform, or volume prefix with `RNICK_ANDROID_DOCKER_IMAGE`, `RNICK_ANDROID_DOCKER_PLATFORM`, or `RNICK_ANDROID_DOCKER_VOLUME_PREFIX` if needed.
|
|
479
|
+
|
|
480
|
+
Docker covers repository checks, Android Codegen, Android JVM unit tests, and the example Android debug build. It does not run an Android emulator, `pnpm example:android`, or `pnpm example:android-instrumentation`; those still require a connected API 34+ emulator/device or the separate GitHub Actions instrumentation workflow.
|
|
481
|
+
|
|
482
|
+
## Development Verification
|
|
483
|
+
|
|
484
|
+
Run the JavaScript and TypeScript checks:
|
|
485
|
+
|
|
486
|
+
```bash
|
|
487
|
+
pnpm verify
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
`pnpm verify` runs type checking, unit tests, the TypeScript build, and the Android verification doctor.
|
|
491
|
+
|
|
492
|
+
Run the pack-based consumer smoke test before release-oriented changes:
|
|
493
|
+
|
|
494
|
+
```bash
|
|
495
|
+
pnpm smoke:consumer
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
This command builds the package, creates a local tarball with `pnpm pack`, installs it into a separate temporary React Native consumer project, and typechecks public API imports from the packed package.
|
|
499
|
+
|
|
500
|
+
To run only the Android repository checks:
|
|
501
|
+
|
|
502
|
+
```bash
|
|
503
|
+
pnpm android:doctor
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
Android Codegen and native compilation require a React Native app build environment. React Native Codegen is run through the React Native app build, so point the verification scripts at an app's Android project:
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
RNICK_ANDROID_APP_DIR=/path/to/App/android pnpm android:codegen
|
|
510
|
+
RNICK_ANDROID_APP_DIR=/path/to/App/android pnpm android:build
|
|
511
|
+
RNICK_ANDROID_APP_DIR=/path/to/App/android RNICK_ANDROID_GRADLE_TASK=:react-native-image-compression-kit:testDebugUnitTest pnpm android:build
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
For the bundled example app, use `pnpm example:codegen`, `pnpm example:android-unit-test`, and `pnpm example:build`.
|
|
515
|
+
Use `pnpm example:android-instrumentation` only when an API 34+ emulator or device is connected.
|
|
516
|
+
|
|
517
|
+
`pnpm android:codegen` runs `generateCodegenArtifactsFromSchema` in the app Android project. `pnpm android:build` runs `assembleDebug` by default. To use a different Gradle task:
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
RNICK_ANDROID_APP_DIR=/path/to/App/android RNICK_ANDROID_GRADLE_TASK=:app:assembleDebug pnpm android:build
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
The executable Android checks require a Java runtime, Android SDK, and a Gradle wrapper or `gradle` command in the target app. If those are not installed locally, use `pnpm docker:android:build` followed by `pnpm docker:android:ci` to run the non-emulator Android verification flow in the reproducible Docker environment.
|
|
524
|
+
|
|
525
|
+
## Release Dry Run Checklist
|
|
526
|
+
|
|
527
|
+
Actual npm publishing requires an authenticated npm registry session and is intentionally outside the dry-run checklist. See [RELEASE.md](RELEASE.md) for the v0.1.0 release notes, tag preparation checklist, and publish operator checklist. Before publishing, review the intended version and package metadata, then run the dry-run release gate from the repository root:
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
pnpm release:dry-run
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
That command does not publish to npm. It runs the required pre-publish checks in this order:
|
|
534
|
+
|
|
535
|
+
```bash
|
|
536
|
+
pnpm verify
|
|
537
|
+
pnpm example:typecheck
|
|
538
|
+
git diff --check
|
|
539
|
+
pnpm pack --dry-run
|
|
540
|
+
pnpm smoke:consumer
|
|
541
|
+
pnpm publish --dry-run --no-git-checks
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
The final `pnpm publish --dry-run --no-git-checks` step exercises the publish packaging path without uploading a package. The `--no-git-checks` flag keeps the dry run usable before the release commit or tag exists; the actual publish decision should still wait for a clean working tree, the intended version, reviewed v0.1.0 release notes, a pushed `v0.1.0` tag, and a successful GitHub Actions CI run on the pushed release commit. Tag and npm publish commands are documented in `RELEASE.md` and should only be run manually after those checks pass.
|
|
545
|
+
|
|
546
|
+
### Local Commit Hook
|
|
547
|
+
|
|
548
|
+
Install the repository git hooks once per clone:
|
|
549
|
+
|
|
550
|
+
```bash
|
|
551
|
+
pnpm hooks:install
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
The `pre-commit` hook runs `git diff --cached --check`, `pnpm verify`, and `pnpm example:typecheck`. Commits should only be created after these checks pass. After each completed development task, keep `README.md` aligned with the current implementation status before committing.
|
|
555
|
+
|
|
556
|
+
## Contributing
|
|
557
|
+
|
|
558
|
+
The project is in its initial design phase. Issues and discussions about the proposed API, format priorities, platform behavior, metadata policy, and native implementation strategy are welcome once the repository is ready for public collaboration.
|
|
559
|
+
|
|
560
|
+
## License
|
|
561
|
+
|
|
562
|
+
MIT License. See [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
def kotlinVersion = rootProject.ext.has("kotlinVersion")
|
|
3
|
+
? rootProject.ext.get("kotlinVersion")
|
|
4
|
+
: "2.0.21"
|
|
5
|
+
|
|
6
|
+
repositories {
|
|
7
|
+
google()
|
|
8
|
+
mavenCentral()
|
|
9
|
+
gradlePluginPortal()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
dependencies {
|
|
13
|
+
classpath("com.android.tools.build:gradle:8.7.3")
|
|
14
|
+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
apply plugin: "com.android.library"
|
|
19
|
+
apply plugin: "com.facebook.react"
|
|
20
|
+
apply plugin: "org.jetbrains.kotlin.android"
|
|
21
|
+
|
|
22
|
+
def safeExtGet(prop, fallback) {
|
|
23
|
+
return rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
android {
|
|
27
|
+
namespace "com.imagecompressionkit"
|
|
28
|
+
compileSdkVersion safeExtGet("compileSdkVersion", 35)
|
|
29
|
+
|
|
30
|
+
defaultConfig {
|
|
31
|
+
minSdkVersion safeExtGet("minSdkVersion", 23)
|
|
32
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
testOptions {
|
|
36
|
+
unitTests.returnDefaultValues = true
|
|
37
|
+
unitTests.includeAndroidResources = true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
sourceSets {
|
|
41
|
+
main.java.srcDirs += [
|
|
42
|
+
"src/main/java",
|
|
43
|
+
"build/generated/source/codegen/java"
|
|
44
|
+
]
|
|
45
|
+
androidTest.assets.srcDirs += ["src/test/assets"]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
repositories {
|
|
50
|
+
google()
|
|
51
|
+
mavenCentral()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
dependencies {
|
|
55
|
+
implementation "com.facebook.react:react-android"
|
|
56
|
+
implementation "androidx.exifinterface:exifinterface:1.4.2"
|
|
57
|
+
testImplementation "junit:junit:4.13.2"
|
|
58
|
+
testImplementation "org.robolectric:robolectric:4.16.1"
|
|
59
|
+
androidTestImplementation "junit:junit:4.13.2"
|
|
60
|
+
androidTestImplementation "androidx.test:core:1.6.1"
|
|
61
|
+
androidTestImplementation "androidx.test:runner:1.6.2"
|
|
62
|
+
androidTestImplementation "androidx.test.ext:junit:1.2.1"
|
|
63
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
|