react-native-update 10.44.0 → 10.46.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/android/jni/Android.mk +0 -1
- package/android/lib/arm64-v8a/librnupdate.so +0 -0
- package/android/lib/armeabi-v7a/librnupdate.so +0 -0
- package/android/lib/x86/librnupdate.so +0 -0
- package/android/lib/x86_64/librnupdate.so +0 -0
- package/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java +10 -1
- package/android/src/main/java/cn/reactnative/modules/update/ErrorCodes.java +24 -0
- package/android/src/main/java/cn/reactnative/modules/update/StateSerialRunner.java +2 -1
- package/android/src/main/java/cn/reactnative/modules/update/UiThreadRunner.java +2 -1
- package/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java +19 -4
- package/android/src/main/java/cn/reactnative/modules/update/UpdateEventEmitter.java +13 -1
- package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleImpl.java +15 -15
- package/cpp/patch_core/error_codes.h +43 -0
- package/cpp/patch_core/patch_core.cpp +16 -1
- package/cpp/patch_core/patch_core.h +6 -0
- package/cpp/patch_core/tests/patch_core_test.cpp +77 -0
- package/harmony/pushy/src/main/cpp/pushy.cpp +1 -93
- package/harmony/pushy/src/main/ets/DownloadTask.ts +13 -10
- package/harmony/pushy/src/main/ets/NativePatchCore.ts +0 -4
- package/harmony/pushy/src/main/ets/UpdateContext.ts +20 -2
- package/harmony/pushy.har +0 -0
- package/ios/RCTPushy/RCTPushy.mm +223 -132
- package/ios/RCTPushy/RCTPushyDownloader.mm +22 -1
- package/package.json +7 -3
- package/src/client.ts +151 -53
- package/src/context.ts +21 -7
- package/src/core.ts +8 -2
- package/src/endpoint.ts +4 -2
- package/src/error.ts +68 -0
- package/src/index.ts +10 -1
- package/src/locales/en.ts +5 -1
- package/src/locales/zh.ts +3 -1
- package/src/provider.tsx +101 -54
- package/src/type.ts +6 -0
- package/src/utils.ts +56 -16
- package/android/jni/DownloadTask.c +0 -56
- package/android/jni/cn_reactnative_modules_update_DownloadTask.h +0 -21
package/src/provider.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import React, {
|
|
|
2
2
|
ReactNode,
|
|
3
3
|
useCallback,
|
|
4
4
|
useEffect,
|
|
5
|
+
useMemo,
|
|
5
6
|
useRef,
|
|
6
7
|
useState,
|
|
7
8
|
} from 'react';
|
|
@@ -24,7 +25,7 @@ import {
|
|
|
24
25
|
ProgressData,
|
|
25
26
|
UpdateTestPayload,
|
|
26
27
|
} from './type';
|
|
27
|
-
import { UpdateContext } from './context';
|
|
28
|
+
import { ProgressContext, UpdateContext } from './context';
|
|
28
29
|
import { URL } from 'react-native-url-polyfill';
|
|
29
30
|
import { resolveCheckResult } from './resolveCheckResult';
|
|
30
31
|
import { assertWeb, log, noop } from './utils';
|
|
@@ -44,16 +45,6 @@ export const UpdateProvider = ({
|
|
|
44
45
|
const updateInfoRef = useRef(updateInfo);
|
|
45
46
|
const [progress, setProgress] = useState<ProgressData>();
|
|
46
47
|
const [lastError, setLastError] = useState<Error>();
|
|
47
|
-
const lastChecking = useRef(0);
|
|
48
|
-
|
|
49
|
-
const throwErrorIfEnabled = useCallback(
|
|
50
|
-
(e: Error) => {
|
|
51
|
-
if (options.throwError) {
|
|
52
|
-
throw e;
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
[options.throwError],
|
|
56
|
-
);
|
|
57
48
|
|
|
58
49
|
const dismissError = useCallback(() => {
|
|
59
50
|
setLastError(undefined);
|
|
@@ -80,6 +71,25 @@ export const UpdateProvider = ({
|
|
|
80
71
|
[options.updateStrategy],
|
|
81
72
|
);
|
|
82
73
|
|
|
74
|
+
// All client errors flow through this single subscription (regardless of
|
|
75
|
+
// throwError), so the catches below only handle flow control and never
|
|
76
|
+
// duplicate the lastError/Alert surfacing.
|
|
77
|
+
useEffect(
|
|
78
|
+
() =>
|
|
79
|
+
client.onError((e, eventType) => {
|
|
80
|
+
setLastError(e);
|
|
81
|
+
alertError(
|
|
82
|
+
client.t(
|
|
83
|
+
eventType === 'errorChecking'
|
|
84
|
+
? 'error_update_check_failed'
|
|
85
|
+
: 'update_failed',
|
|
86
|
+
),
|
|
87
|
+
e.message,
|
|
88
|
+
);
|
|
89
|
+
}),
|
|
90
|
+
[client, alertError],
|
|
91
|
+
);
|
|
92
|
+
|
|
83
93
|
const switchVersion = useCallback(
|
|
84
94
|
async (info: CheckResult | undefined = updateInfoRef.current) => {
|
|
85
95
|
if (info && info.hash) {
|
|
@@ -117,10 +127,11 @@ export const UpdateProvider = ({
|
|
|
117
127
|
return false;
|
|
118
128
|
}
|
|
119
129
|
if (options.updateStrategy === 'silentAndNow') {
|
|
120
|
-
|
|
130
|
+
// Failures are surfaced via the onError subscription above.
|
|
131
|
+
client.switchVersion(hash).catch(noop);
|
|
121
132
|
return true;
|
|
122
133
|
} else if (options.updateStrategy === 'silentAndLater') {
|
|
123
|
-
client.switchVersionLater(hash);
|
|
134
|
+
client.switchVersionLater(hash).catch(noop);
|
|
124
135
|
return true;
|
|
125
136
|
}
|
|
126
137
|
alertUpdate(client.t('alert_title'), client.t('alert_update_ready'), [
|
|
@@ -128,26 +139,33 @@ export const UpdateProvider = ({
|
|
|
128
139
|
text: client.t('alert_next_time'),
|
|
129
140
|
style: 'cancel',
|
|
130
141
|
onPress: () => {
|
|
131
|
-
client.switchVersionLater(hash);
|
|
142
|
+
client.switchVersionLater(hash).catch(noop);
|
|
132
143
|
},
|
|
133
144
|
},
|
|
134
145
|
{
|
|
135
146
|
text: client.t('alert_update_now'),
|
|
136
147
|
style: 'default',
|
|
137
148
|
onPress: () => {
|
|
138
|
-
client.switchVersion(hash);
|
|
149
|
+
client.switchVersion(hash).catch(noop);
|
|
139
150
|
},
|
|
140
151
|
},
|
|
141
152
|
]);
|
|
142
153
|
return true;
|
|
143
154
|
} catch (e: any) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
155
|
+
// Client pipeline errors carry a code and were already surfaced via
|
|
156
|
+
// the onError subscription; errors thrown by user hooks
|
|
157
|
+
// (afterDownloadUpdate) bypass the pipeline and are surfaced here.
|
|
158
|
+
if (!e?.code) {
|
|
159
|
+
setLastError(e);
|
|
160
|
+
alertError(client.t('update_failed'), e.message);
|
|
161
|
+
}
|
|
162
|
+
if (options.throwError) {
|
|
163
|
+
throw e;
|
|
164
|
+
}
|
|
147
165
|
return false;
|
|
148
166
|
}
|
|
149
167
|
},
|
|
150
|
-
[client, options, alertUpdate, alertError
|
|
168
|
+
[client, options, alertUpdate, alertError],
|
|
151
169
|
);
|
|
152
170
|
|
|
153
171
|
const downloadAndInstallApk = useCallback(
|
|
@@ -161,19 +179,23 @@ export const UpdateProvider = ({
|
|
|
161
179
|
|
|
162
180
|
const checkUpdate = useCallback(
|
|
163
181
|
async ({ extra }: { extra?: Partial<{ toHash: string }> } = {}) => {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
lastChecking.current = now;
|
|
182
|
+
// No throttle here: the client already dedupes checks via its 5s
|
|
183
|
+
// response cache, and a second throttle layer silently returned
|
|
184
|
+
// undefined, indistinguishable from a failed check.
|
|
170
185
|
let rootInfo: CheckResult | undefined;
|
|
171
186
|
try {
|
|
172
187
|
rootInfo = await client.checkUpdate(extra);
|
|
173
188
|
} catch (e: any) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
189
|
+
// Client pipeline errors carry a code and were already surfaced via
|
|
190
|
+
// the onError subscription; errors thrown by user hooks
|
|
191
|
+
// (beforeCheckUpdate) bypass the pipeline and are surfaced here.
|
|
192
|
+
if (!e?.code) {
|
|
193
|
+
setLastError(e);
|
|
194
|
+
alertError(client.t('error_update_check_failed'), e.message);
|
|
195
|
+
}
|
|
196
|
+
if (options.throwError) {
|
|
197
|
+
throw e;
|
|
198
|
+
}
|
|
177
199
|
return;
|
|
178
200
|
}
|
|
179
201
|
if (!rootInfo) {
|
|
@@ -255,10 +277,9 @@ export const UpdateProvider = ({
|
|
|
255
277
|
},
|
|
256
278
|
[
|
|
257
279
|
client,
|
|
258
|
-
alertError,
|
|
259
|
-
throwErrorIfEnabled,
|
|
260
280
|
options,
|
|
261
281
|
alertUpdate,
|
|
282
|
+
alertError,
|
|
262
283
|
downloadAndInstallApk,
|
|
263
284
|
downloadUpdate,
|
|
264
285
|
],
|
|
@@ -274,9 +295,11 @@ export const UpdateProvider = ({
|
|
|
274
295
|
return;
|
|
275
296
|
}
|
|
276
297
|
const { checkStrategy, autoMarkSuccess } = options;
|
|
298
|
+
let markSuccessTimer: ReturnType<typeof setTimeout> | undefined;
|
|
277
299
|
if (autoMarkSuccess) {
|
|
278
|
-
setTimeout(() => {
|
|
279
|
-
|
|
300
|
+
markSuccessTimer = setTimeout(() => {
|
|
301
|
+
// Failures are reported and surfaced via the onError subscription.
|
|
302
|
+
Promise.resolve(markSuccess()).catch(noop);
|
|
280
303
|
}, 1000);
|
|
281
304
|
}
|
|
282
305
|
if (checkStrategy === 'both' || checkStrategy === 'onAppResume') {
|
|
@@ -293,6 +316,9 @@ export const UpdateProvider = ({
|
|
|
293
316
|
checkUpdate().catch(noop);
|
|
294
317
|
}
|
|
295
318
|
return () => {
|
|
319
|
+
if (markSuccessTimer) {
|
|
320
|
+
clearTimeout(markSuccessTimer);
|
|
321
|
+
}
|
|
296
322
|
stateListener.current && stateListener.current.remove();
|
|
297
323
|
};
|
|
298
324
|
}, [checkUpdate, options, dismissError, markSuccess, client]);
|
|
@@ -350,7 +376,8 @@ export const UpdateProvider = ({
|
|
|
350
376
|
try {
|
|
351
377
|
const payload = typeof code === 'string' ? JSON.parse(code) : code;
|
|
352
378
|
return parseTestPayload(payload);
|
|
353
|
-
} catch {
|
|
379
|
+
} catch (e: any) {
|
|
380
|
+
log('parseTestQrCode: invalid payload', e?.message || e);
|
|
354
381
|
return false;
|
|
355
382
|
}
|
|
356
383
|
},
|
|
@@ -391,28 +418,48 @@ export const UpdateProvider = ({
|
|
|
391
418
|
};
|
|
392
419
|
}, [parseTestPayload]);
|
|
393
420
|
|
|
421
|
+
// progress lives in its own context (see context.ts), so this value only
|
|
422
|
+
// changes when the update state itself changes, not on every progress tick.
|
|
423
|
+
const contextValue = useMemo(
|
|
424
|
+
() => ({
|
|
425
|
+
checkUpdate,
|
|
426
|
+
switchVersion,
|
|
427
|
+
switchVersionLater,
|
|
428
|
+
dismissError,
|
|
429
|
+
updateInfo,
|
|
430
|
+
lastError,
|
|
431
|
+
markSuccess,
|
|
432
|
+
client,
|
|
433
|
+
downloadUpdate,
|
|
434
|
+
packageVersion,
|
|
435
|
+
currentHash: currentVersion,
|
|
436
|
+
downloadAndInstallApk,
|
|
437
|
+
getCurrentVersionInfo,
|
|
438
|
+
currentVersionInfo,
|
|
439
|
+
parseTestQrCode,
|
|
440
|
+
restartApp,
|
|
441
|
+
}),
|
|
442
|
+
[
|
|
443
|
+
checkUpdate,
|
|
444
|
+
switchVersion,
|
|
445
|
+
switchVersionLater,
|
|
446
|
+
dismissError,
|
|
447
|
+
updateInfo,
|
|
448
|
+
lastError,
|
|
449
|
+
markSuccess,
|
|
450
|
+
client,
|
|
451
|
+
downloadUpdate,
|
|
452
|
+
downloadAndInstallApk,
|
|
453
|
+
parseTestQrCode,
|
|
454
|
+
restartApp,
|
|
455
|
+
],
|
|
456
|
+
);
|
|
457
|
+
|
|
394
458
|
return (
|
|
395
|
-
<UpdateContext.Provider
|
|
396
|
-
value={
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
switchVersionLater,
|
|
400
|
-
dismissError,
|
|
401
|
-
updateInfo,
|
|
402
|
-
lastError,
|
|
403
|
-
markSuccess,
|
|
404
|
-
client,
|
|
405
|
-
downloadUpdate,
|
|
406
|
-
packageVersion,
|
|
407
|
-
currentHash: currentVersion,
|
|
408
|
-
progress,
|
|
409
|
-
downloadAndInstallApk,
|
|
410
|
-
getCurrentVersionInfo,
|
|
411
|
-
currentVersionInfo,
|
|
412
|
-
parseTestQrCode,
|
|
413
|
-
restartApp,
|
|
414
|
-
}}>
|
|
415
|
-
{children}
|
|
459
|
+
<UpdateContext.Provider value={contextValue}>
|
|
460
|
+
<ProgressContext.Provider value={progress}>
|
|
461
|
+
{children}
|
|
462
|
+
</ProgressContext.Provider>
|
|
416
463
|
</UpdateContext.Provider>
|
|
417
464
|
);
|
|
418
465
|
};
|
package/src/type.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { UpdateErrorCode } from './error';
|
|
2
|
+
|
|
1
3
|
export interface VersionInfo {
|
|
2
4
|
name: string;
|
|
3
5
|
hash: string;
|
|
@@ -52,6 +54,8 @@ export type EventType =
|
|
|
52
54
|
| 'downloadSuccess'
|
|
53
55
|
| 'errorUpdate'
|
|
54
56
|
| 'markSuccess'
|
|
57
|
+
| 'errorMarkSuccess'
|
|
58
|
+
| 'errorSwitchVersion'
|
|
55
59
|
| 'downloadingApk'
|
|
56
60
|
| 'rejectStoragePermission'
|
|
57
61
|
| 'errorStoragePermission'
|
|
@@ -59,6 +63,8 @@ export type EventType =
|
|
|
59
63
|
| 'errorInstallApk';
|
|
60
64
|
|
|
61
65
|
export interface EventData {
|
|
66
|
+
/** Stable machine-readable error code; present on error events */
|
|
67
|
+
code?: UpdateErrorCode;
|
|
62
68
|
currentVersion: string;
|
|
63
69
|
cInfo: {
|
|
64
70
|
rnu: string;
|
package/src/utils.ts
CHANGED
|
@@ -22,6 +22,10 @@ export const DEFAULT_FETCH_TIMEOUT_MS = 5000;
|
|
|
22
22
|
|
|
23
23
|
export function promiseAny<T>(promises: Promise<T>[]) {
|
|
24
24
|
return new Promise<T>((resolve, reject) => {
|
|
25
|
+
if (!promises.length) {
|
|
26
|
+
reject(Error(i18n.t('error_all_promises_rejected')));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
25
29
|
let count = 0;
|
|
26
30
|
|
|
27
31
|
promises.forEach(promise => {
|
|
@@ -118,21 +122,50 @@ export const fetchWithTimeout = (
|
|
|
118
122
|
params: Parameters<typeof fetch>[1],
|
|
119
123
|
timeoutMs = DEFAULT_FETCH_TIMEOUT_MS,
|
|
120
124
|
): Promise<Response> => {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
125
|
+
// AbortController landed in the RN fetch polyfill around 0.60; we support
|
|
126
|
+
// older peers, so fall back to a plain timer race when it is unavailable
|
|
127
|
+
// (the losing fetch keeps running there — old runtimes can't do better).
|
|
128
|
+
if (typeof AbortController === 'undefined') {
|
|
129
|
+
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
|
130
|
+
return Promise.race([
|
|
131
|
+
enhancedFetch(url, params),
|
|
132
|
+
new Promise<Response>((_, reject) => {
|
|
133
|
+
timeoutId = setTimeout(() => {
|
|
134
|
+
log('fetch timeout', url);
|
|
135
|
+
reject(Error(i18n.t('error_ping_timeout')));
|
|
136
|
+
}, timeoutMs);
|
|
137
|
+
}),
|
|
138
|
+
]).finally(() => {
|
|
139
|
+
if (timeoutId) {
|
|
140
|
+
clearTimeout(timeoutId);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Abort the underlying request on timeout instead of racing a timer: with
|
|
146
|
+
// Promise.race the losing fetch kept running (and kept the connection busy)
|
|
147
|
+
// long after the caller had already moved on.
|
|
148
|
+
const controller = new AbortController();
|
|
149
|
+
const timeoutId = setTimeout(() => {
|
|
150
|
+
log('fetch timeout', url);
|
|
151
|
+
controller.abort();
|
|
152
|
+
}, timeoutMs);
|
|
153
|
+
|
|
154
|
+
return enhancedFetch(url, { ...params, signal: controller.signal })
|
|
155
|
+
.catch((e: any) => {
|
|
156
|
+
if (controller.signal.aborted) {
|
|
157
|
+
throw Error(i18n.t('error_ping_timeout'));
|
|
158
|
+
}
|
|
159
|
+
throw e;
|
|
160
|
+
})
|
|
161
|
+
.finally(() => {
|
|
133
162
|
clearTimeout(timeoutId);
|
|
134
|
-
}
|
|
135
|
-
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const isIdempotentRequest = (params: Parameters<typeof fetch>[1]) => {
|
|
167
|
+
const method = params?.method?.toUpperCase() ?? 'GET';
|
|
168
|
+
return method === 'GET' || method === 'HEAD';
|
|
136
169
|
};
|
|
137
170
|
|
|
138
171
|
export const enhancedFetch = async (
|
|
@@ -143,10 +176,17 @@ export const enhancedFetch = async (
|
|
|
143
176
|
return fetch(url, params)
|
|
144
177
|
.catch(e => {
|
|
145
178
|
log('fetch error', url, e);
|
|
146
|
-
if (
|
|
179
|
+
if (
|
|
180
|
+
isRetry ||
|
|
181
|
+
(params as any)?.signal?.aborted ||
|
|
182
|
+
!url.startsWith('https:') ||
|
|
183
|
+
// Never replay non-idempotent requests (e.g. the checkUpdate POST)
|
|
184
|
+
// over plaintext http: the server may have processed the original.
|
|
185
|
+
!isIdempotentRequest(params)
|
|
186
|
+
) {
|
|
147
187
|
throw e;
|
|
148
188
|
}
|
|
149
189
|
log('trying fallback to http');
|
|
150
|
-
return enhancedFetch(url.replace(
|
|
190
|
+
return enhancedFetch(url.replace(/^https:/, 'http:'), params, true);
|
|
151
191
|
});
|
|
152
192
|
};
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Created by DengYun on 3/31/16.
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
#include "cn_reactnative_modules_update_DownloadTask.h"
|
|
6
|
-
|
|
7
|
-
#include "hpatch.h"
|
|
8
|
-
#define _check(v,errInfo) do{ if (!(v)) { _isError=hpatch_TRUE; _errInfo=errInfo; goto _clear; } }while(0)
|
|
9
|
-
|
|
10
|
-
JNIEXPORT jbyteArray JNICALL Java_cn_reactnative_modules_update_DownloadTask_hdiffPatch
|
|
11
|
-
(JNIEnv *env, jobject self, jbyteArray origin, jbyteArray patch){
|
|
12
|
-
hpatch_BOOL _isError=hpatch_FALSE;
|
|
13
|
-
const char* _errInfo="";
|
|
14
|
-
|
|
15
|
-
jbyte* originPtr = (*env)->GetByteArrayElements(env, origin, NULL);
|
|
16
|
-
size_t originLength = (*env)->GetArrayLength(env, origin);
|
|
17
|
-
jbyte* patchPtr = (*env)->GetByteArrayElements(env, patch, NULL);
|
|
18
|
-
size_t patchLength = (*env)->GetArrayLength(env, patch);
|
|
19
|
-
jbyteArray ret = NULL;
|
|
20
|
-
jbyte* outPtr = NULL;
|
|
21
|
-
size_t newsize = 0;
|
|
22
|
-
hpatch_singleCompressedDiffInfo patInfo;
|
|
23
|
-
|
|
24
|
-
_check(((originLength==0)||originPtr) && patchPtr && (patchLength>0),"Corrupt patch");
|
|
25
|
-
_check(kHPatch_ok==hpatch_getInfo_by_mem(&patInfo,(const uint8_t*)patchPtr,patchLength),"Error info in hpatch");
|
|
26
|
-
_check(originLength==patInfo.oldDataSize,"Error oldDataSize in hpatch");
|
|
27
|
-
newsize=(size_t)patInfo.newDataSize;
|
|
28
|
-
if (sizeof(size_t)!=sizeof(hpatch_StreamPos_t))
|
|
29
|
-
_check(newsize==patInfo.newDataSize,"Error newDataSize in hpatch");
|
|
30
|
-
|
|
31
|
-
ret = (*env)->NewByteArray(env,newsize);
|
|
32
|
-
_check(ret,"Error JNIEnv::NewByteArray()");
|
|
33
|
-
if (newsize>0) {
|
|
34
|
-
outPtr = (*env)->GetByteArrayElements(env, ret, NULL);
|
|
35
|
-
_check(outPtr,"Corrupt JNIEnv::GetByteArrayElements");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
_check(kHPatch_ok==hpatch_by_mem((const uint8_t*)originPtr,originLength,(uint8_t*)outPtr,newsize,
|
|
39
|
-
(const uint8_t*)patchPtr,patchLength,&patInfo),"hpacth");
|
|
40
|
-
|
|
41
|
-
_clear:
|
|
42
|
-
if (outPtr) (*env)->ReleaseByteArrayElements(env, ret, outPtr, (_isError?JNI_ABORT:0));
|
|
43
|
-
if (originPtr) (*env)->ReleaseByteArrayElements(env, origin, originPtr, JNI_ABORT);
|
|
44
|
-
if (patchPtr) (*env)->ReleaseByteArrayElements(env, patch, patchPtr, JNI_ABORT);
|
|
45
|
-
if (_isError){
|
|
46
|
-
jclass newExcCls = NULL;
|
|
47
|
-
if (ret){
|
|
48
|
-
(*env)->DeleteLocalRef(env, ret);
|
|
49
|
-
ret = NULL;
|
|
50
|
-
}
|
|
51
|
-
newExcCls = (*env)->FindClass(env, "java/lang/Error");
|
|
52
|
-
if (newExcCls != NULL) // Unable to find the new exception class, give up.
|
|
53
|
-
(*env)->ThrowNew(env, newExcCls, _errInfo);
|
|
54
|
-
}
|
|
55
|
-
return ret;
|
|
56
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/* DO NOT EDIT THIS FILE - it is machine generated */
|
|
2
|
-
#include <jni.h>
|
|
3
|
-
/* Header for class cn_reactnative_modules_update_DownloadTask */
|
|
4
|
-
|
|
5
|
-
#ifndef _Included_cn_reactnative_modules_update_DownloadTask
|
|
6
|
-
#define _Included_cn_reactnative_modules_update_DownloadTask
|
|
7
|
-
#ifdef __cplusplus
|
|
8
|
-
extern "C" {
|
|
9
|
-
#endif
|
|
10
|
-
/*
|
|
11
|
-
* Class: cn_reactnative_modules_update_DownloadTask
|
|
12
|
-
* Method: hdiffPatch
|
|
13
|
-
* Signature: ([B[B)[B
|
|
14
|
-
*/
|
|
15
|
-
JNIEXPORT jbyteArray JNICALL Java_cn_reactnative_modules_update_DownloadTask_hdiffPatch
|
|
16
|
-
(JNIEnv *, jclass, jbyteArray, jbyteArray);
|
|
17
|
-
|
|
18
|
-
#ifdef __cplusplus
|
|
19
|
-
}
|
|
20
|
-
#endif
|
|
21
|
-
#endif
|