0.2.2 • Published 8 months ago

react-native-remote-update v0.2.2

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

react-native-remote-update

What is this?

react-native-remote-update is a module for React Native that allows you to update your application remotely. It uses a JSON file to store the application's version and the commit hash of the latest version. When the app starts, it checks if there is an available update and downloads the new version if there is one.

Installation 📦

Install the module using one of the following commands:

npm install react-native-remote-update
yarn add react-native-remote-update
bun add react-native-remote-update

Direct to your Android project at the path android/app/src/main/java/com/yourapp/MainActivity.java. Import this line:

    import com.remoteupdate.BundleFileManager

add this fragment of code to the reactNativeHost block

override fun getJSBundleFile(): String? {
                return BundleFileManager.getJSBundleFile(applicationContext)
 }

your archvo should look like this

package com.remote

import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.soloader.SoLoader
import java.io.File
import com.remoteupdate.BundleFileManager // <-- 👈 Import the BundleFileManager module

class MainApplication : Application(), ReactApplication {

    override val reactNativeHost: ReactNativeHost =
        object : DefaultReactNativeHost(this) {
            override fun getPackages(): List<ReactPackage> =
                PackageList(this).packages.apply {
                    // Packages that cannot be autolinked yet can be added manually here

                }

            override fun getJSMainModuleName(): String = "index"

            override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG

            override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
            override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
        //================== add this =================
            override fun getJSBundleFile(): String? {
                return BundleFileManager.getJSBundleFile(applicationContext)
            }
        //===============================
        }

    override val reactHost: ReactHost
        get() = getDefaultReactHost(applicationContext, reactNativeHost)

    override fun onCreate() {
        super.onCreate()
        SoLoader.init(this, false)
        if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
            // Load the native entry point for this app if the new architecture is enabled
            load()
        }
    }
}

¡Atención! La función de actualizaciones remotas actualmente no está disponible en iOS. Estamos trabajando en implementarla y te informaremos tan pronto como esté lista. Gracias por tu comprensión.

Uso

Here is an example of a test server test server

To use the react-native-remote-update module, follow these steps:

  1. Import the module in your application:

    import {
      RemoteUpdate,
      RemoteUpdateProvider,
    } from 'react-native-remote-update';

⚠ IMPORTANT WARNING ⚠

Download links MUST BE DIRECT and must not return a JSON response.

  1. Configure the update URL that returns the JSON with the version information:

    const uri = 'https://your-server.com/update.json';
  2. Call the RemoteUpdate function inside a useEffect hook to check for updates when your application starts:

useEffect(() => {
  RemoteUpdate({ uri }, (error, success) => {
    if (error) {
      console.error('Error al actualizar:', error);
    } else {
      console.log('Actualización exitosa:', success);
    }
  });
}, []);
  1. Wrap your application in the RemoteUpdateProvider component. This component handles the update state and captures errors. If an error prevents the application from starting, the RemoteUpdateProvider component will display an error or update component as desired. This also provides the opportunity to send a new version and delete bundles that cause this error system:
const App = () => {
  return (
    <RemoteUpdateProvider
      fallback={<Text>Error reverting to previous version, etc...</Text>} // <-- 👈 Fallback component to display if an error occurs in the app when updating the new version
      dev={!__DEV__}
    >
      <YourMainComponent />
    </RemoteUpdateProvider>
  );
};

export default App;

Example Usage

Here is an example of how to implement react-native-remote-update in your application:

import React, { useEffect } from 'react';
import { Text, ToastAndroid, View } from 'react-native';
import { RemoteUpdate, RemoteUpdateProvider } from 'react-native-remote-update';

const uri = 'https://your-server.com/update'; // <-- 👈 URL de actualización directa para descargar el archivo JSON

const MainComponent = () => {
  return (
    <View
      style={{
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'pink',
      }}
    >
      <Text
        style={{
          fontSize: 30,
          textAlign: 'center',
          color: 'white',
          fontWeight: 'bold',
        }}
      >
        ¡Hola Mundo!
      </Text>
    </View>
  );
};

const App = () => {
  // ==== this implementation will automatically update when the app starts and if there is a change, the changes will be reflected when the app is restarted ====

  useEffect(() => {
    RemoteUpdate({ uri }, (error, success) => {
      if (error) {
        console.error(error);
        ToastAndroid.show('Error en la actualización', ToastAndroid.SHORT);
      } else {
        console.log(success);
        ToastAndroid.show('Actualización completa', ToastAndroid.SHORT);
      }
    });
  }, []);

  return (
    <RemoteUpdateProvider // <-- 👈 this is not mandatory but it is recommended
      fallback={<Text>Error Regresando a una version anterior etc...</Text>} // <-- 👈 Fallback component to display if an error occurs in the app when updating the new version
      dev={!__DEV__} // <-- 👈 Enable development mode to view the fallback component
    >
      <MainComponent />
    </RemoteUpdateProvider>
  );
};

export default App;

⚠ WARNING ⚠

this dosn't work in development to test your implementation you need to generate an apk and test it there

cd android

and run this command

./gradlew assembleRelease

this will leave an apk in the android/app/build/outputs/apk/release path the file is called app-release.apk

creation of bundle file

⚠ WARNING ⚠

modify everything you want in your app at the javascript level you can install new packages that are only javascript and don't act if you install packages that require native code because that code is not compiled into the bundle only javascript

go to your project native folder in a console and run this command

npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output ./dist/index.bundle --assets-dest ./assets/

this will create a bundle in the dist folder ./dist/index.bundle

 "bundle": {
    "uri": "https://your-server.com/bundle" // <-- 👈 URL to download the bundle directly
  }

⚠ warning ⚠

Do not update the app if you have used non-native code. You can only modify the JSON in the app. If you install or configure packages that overwrite native functions, these changes will not work in the app that is already published. You will need to generate a new file and publish it as you would normally do. However, if you only modified the JavaScript or installed packages that are purely JavaScript, the update will work perfectly.

JSON structure

This should be a downloadable JSON file. Here is an example of the structure of the JSON that should be returned by your server: __ json example:

{
  "version": "1.0.0", // <-- 👈 version number
  "versionCode": 4, // <-- 👈 version code of the app this is exlusive to make the app increment this every update begins at 0
  "commit": "4444", // <-- 👈  hash of the last version
  "fallback": true, // <-- 👈 allow the system to automatically fallback
  "fallbackDetails": {
    "commit": "3333", // <-- 👈 hash of the last version or the hash of the version specified that should be returned
    "enable": false // <-- 👈 activate or deactivate the fallback
  },
  "bundle": {
    "uri": "https://your-server.com/bundle" // <-- 👈 URL to download the bundle directly
  }
}

Explanation of JSON fields

FieldTypeDescription
versionstringThe version number of the application
versionCodenumberThe version code used for the application's update.
commitstringThe hash of the commit for the latest version.
fallbackbooleanIndicates if a fallback is available.
fallbackDetailsobjectContains details about the fallback version.
bundleobjectContains information about the bundle for the update.
uristringURL to download the bundle file.

Methods and Parameters

MethodParametersDescription
RemoteUpdate{ uri: string, callback?: (error, result) => void }Initiates a remote update check.
getCurrentJsoncallback: (error, result) => voidRetrieves the current JSON configuration from the remote source.
getBackupBundlescallback: (error, result) => voidRetrieves the backup bundles if available.
getCurrentBundlecallback: (error, result) => voidGets information about the current bundle.

Tips and Warnings

  • Ensure that your server is properly configured to host the JSON file and the bundle.
  • Use HTTPS for secure communications when retrieving updates.
  • Remember to thoroughly test the integration on both platforms, Android and iOS.
  • Keep in mind that iOS integration for remote updates will be available soon and may currently be unavailable.

Contributing

Check the contribution guide to learn how to contribute to the repository and the development workflow.

JSONStreamabort-controlleracceptsacornacorn-jsxacorn-walkadd-streamagent-baseaggregate-errorajvanseransi-alignansi-escapesansi-fragmentsansi-regexansi-stylesanymatchappdirsjsargargparsearray-buffer-byte-lengtharray-ifyarray-includesarray-unionarray.prototype.findlastarray.prototype.flatarray.prototype.flatmaparray.prototype.maparray.prototype.tosortedarraybuffer.prototype.slicearrifyasapast-typesastral-regexasync-limiterasync-retryavailable-typed-arraysbabel-corebabel-jestbabel-plugin-istanbulbabel-plugin-jest-hoistbabel-plugin-module-resolverbabel-plugin-polyfill-corejs2babel-plugin-polyfill-corejs3babel-plugin-polyfill-regeneratorbabel-plugin-transform-flow-enumsbabel-preset-current-node-syntaxbabel-preset-jestbalanced-matchbase64-jsbasic-ftpbefore-after-hookbig-integerblboxenbplist-parserbrace-expansionbracesbrowserslistbserbufferbuffer-frombundle-namebytescacheable-lookupcacheable-requestcall-bindcaller-callsitecaller-pathcallsitescamelcasecamelcase-keyscaniuse-litechalkchar-regexchardetchrome-launcherchromium-edge-launcherci-infocjs-module-lexerclean-stackcli-boxescli-cursorcli-spinnerscli-widthcliuicloneclone-deepcocollect-v8-coveragecolor-convertcolor-namecolorettecommand-existscommandercommondircompare-funccompressiblecompressionconcat-mapconcat-streamconfig-chainconfigstoreconnectconventional-changelogconventional-changelog-angularconventional-changelog-atomconventional-changelog-codemirrorconventional-changelog-conventionalcommitsconventional-changelog-coreconventional-changelog-emberconventional-changelog-eslintconventional-changelog-expressconventional-changelog-jqueryconventional-changelog-jshintconventional-changelog-preset-loaderconventional-changelog-writerconventional-commits-filterconventional-commits-parserconventional-recommended-bumpconvert-source-mapcore-js-compatcore-util-iscosmiconfigcosmiconfig-typescript-loadercreate-jestcreate-requirecross-spawncrypto-random-stringcsstypedargsdata-uri-to-bufferdata-view-bufferdata-view-byte-lengthdata-view-byte-offsetdateformatdayjsdebugdecamelizedecamelize-keysdecompress-responsededentdeep-extenddeep-isdeepmergedefault-browserdefault-browser-iddefaultsdefer-to-connectdefine-data-propertydefine-lazy-propdefine-propertiesdegeneratordeldenodeifydepddeprecationdestroydetect-newlinediffdiff-sequencesdir-globdoctrinedot-propeastasianwidthee-firstelectron-to-chromiumemitteryemoji-regexencodeurlend-of-streamenv-pathsenvinfoerror-exerror-stack-parsererrorhandleres-abstractes-array-method-boxes-properlyes-define-propertyes-errorses-get-iteratores-iterator-helperses-object-atomses-set-tostringtages-shim-unscopableses-to-primitiveescaladeescape-goatescape-htmlescape-string-regexpescodegeneslint-plugin-eslint-commentseslint-plugin-ft-floweslint-plugin-jesteslint-plugin-reacteslint-plugin-react-hookseslint-plugin-react-nativeeslint-plugin-react-native-globalseslint-scopeeslint-visitor-keysespreeesprimaesqueryesrecurseestraverseesutilsetagevent-target-shimexecaexitexpectexponential-backoffexternal-editorfast-deep-equalfast-difffast-globfast-json-stable-stringifyfast-levenshteinfast-urifast-xml-parserfastqfb-watchmanfetch-blobfiguresfile-entry-cachefill-rangefinalhandlerfind-babel-configfind-cache-dirfind-upflat-cacheflattedflow-enums-runtimeflow-parserfor-eachform-data-encoderformdata-polyfillfreshfs-extrafs.realpathfunction-bindfunction.prototype.namefunctions-have-namesgensyncget-caller-fileget-intrinsicget-package-typeget-pkg-repoget-streamget-symbol-descriptionget-urigit-raw-commitsgit-remote-origin-urlgit-semver-tagsgit-upgit-url-parsegitconfiglocalglobglob-parentglobal-dirsglobalsglobalthisglobbygopdgotgraceful-fsgraphemerhandlebarshard-rejectionhas-bigintshas-flaghas-property-descriptorshas-protohas-symbolshas-tostringtaghas-yarnhasownhermes-estreehermes-parserhosted-git-infohtml-escaperhttp-cache-semanticshttp-errorshttp-proxy-agenthttp2-wrapperhttps-proxy-agenthuman-signalsiconv-liteieee754ignoreimage-sizeimport-freshimport-lazyimport-localimurmurhashindent-stringinflightinheritsiniinquirerinternal-slotinterpretinvariantipip-addressis-absoluteis-argumentsis-array-bufferis-arrayishis-async-functionis-bigintis-boolean-objectis-callableis-ciis-core-moduleis-data-viewis-date-objectis-directoryis-dockeris-extglobis-finalizationregistryis-fullwidth-code-pointis-generator-fnis-generator-functionis-git-dirtyis-git-repositoryis-globis-inside-containeris-installed-globallyis-interactiveis-mapis-negative-zerois-npmis-numberis-number-objectis-objis-path-cwdis-path-insideis-plain-objis-plain-objectis-regexis-relativeis-setis-shared-array-bufferis-sshis-streamis-stringis-symbolis-text-pathis-typed-arrayis-typedarrayis-unc-pathis-unicode-supportedis-weakmapis-weakrefis-weaksetis-windowsis-wslis-yarn-globalisarrayisexeisobjectissue-parseristanbul-lib-coverageistanbul-lib-instrumentistanbul-lib-reportistanbul-lib-source-mapsistanbul-reportsiterate-iteratoriterate-valueiterator.prototypejest-changed-filesjest-circusjest-clijest-configjest-diffjest-docblockjest-eachjest-environment-nodejest-get-typejest-haste-mapjest-leak-detectorjest-matcher-utilsjest-message-utiljest-mockjest-pnp-resolverjest-regex-utiljest-resolvejest-resolve-dependenciesjest-runnerjest-runtimejest-snapshotjest-utiljest-validatejest-watcherjest-workerjoijs-tokensjs-yamljsbnjsc-androidjsc-safe-urljscodeshiftjsescjson-bufferjson-parse-better-errorsjson-parse-even-better-errorsjson-schema-traversejson-stable-stringify-without-jsonifyjson-stringify-safejson5jsonfilejsonparsejsx-ast-utilskeyvkind-ofkleurlatest-versionlevenlevnlighthouse-loggerlines-and-columnsload-json-filelocate-pathlodashlodash.camelcaselodash.capitalizelodash.debouncelodash.escaperegexplodash.isfunctionlodash.ismatchlodash.isplainobjectlodash.isstringlodash.kebabcaselodash.mergelodash.mergewithlodash.snakecaselodash.startcaselodash.throttlelodash.uniqlodash.uniqbylodash.upperfirstlog-symbolslogkittyloose-envifylowercase-keyslru-cachemacos-releasemake-dirmake-errormakeerrormap-objmarkymemoize-onemeowmerge-streammerge2metrometro-babel-transformermetro-cachemetro-cache-keymetro-configmetro-coremetro-file-mapmetro-minify-tersermetro-resolvermetro-runtimemetro-source-mapmetro-symbolicatemetro-transform-pluginsmetro-transform-workermicromatchmimemime-dbmime-typesmimic-fnmimic-responsemin-indentminimatchminimistminimist-optionsminipassmkdirpmodify-valuesmsmute-streamnatural-comparenatural-compare-litenegotiatorneo-asyncnetmasknew-github-release-urlnocachenode-abort-controllernode-dirnode-domexceptionnode-fetchnode-forgenode-int64node-releasesnode-stream-zipnormalize-package-datanormalize-pathnormalize-urlnpm-run-pathnullthrowsob1object-assignobject-inspectobject-keysobject.assignobject.entriesobject.fromentriesobject.valueson-finishedon-headersonceonetimeopenoptionatororaos-nameos-tmpdirp-cancelablep-limitp-locatep-mapp-trypac-proxy-agentpac-resolverpackage-jsonparent-moduleparse-jsonparse-pathparse-urlparseurlpath-existspath-is-absolutepath-keypath-parsepath-scurrypath-typepicocolorspicomatchpifypiratespkg-dirpkg-uppossible-typed-array-namesprelude-lsprettier-linter-helperspretty-formatprocess-nextick-argspromisepromise.allsettledpromptsprop-typesproto-listprotocolsproxy-agentproxy-from-envpumppunycodepupapure-randqqueuequeue-microtaskquick-lrurange-parserrcreact-devtools-corereact-isreact-native-fsreact-refreshread-pkgread-pkg-upreadable-streamreadlinerecastrechoirredentreflect.getprototypeofregenerateregenerate-unicode-propertiesregenerator-runtimeregenerator-transformregexp.prototype.flagsregexpu-coreregistry-auth-tokenregistry-urlregjsgenregjsparserrequire-directoryrequire-from-stringrequire-main-filenamereselectresolveresolve-alpnresolve-cwdresolve-fromresolve-globalresolve.exportsresponselikerestore-cursorretryreusifyrimrafrun-applescriptrun-asyncrun-parallelrxjssafe-array-concatsafe-buffersafe-regex-testsafer-bufferschedulerselfsignedsemversemver-diffsendserialize-errorserve-staticset-blockingset-function-lengthset-function-namesetprototypeofshallow-cloneshebang-commandshebang-regexshell-quoteshelljsside-channelsignal-exitsisteransislashslice-ansismart-buffersockssocks-proxy-agentsource-mapsource-map-supportspdx-correctspdx-exceptionsspdx-expression-parsespdx-license-idssplitsplit2sprintf-jsstack-utilsstackframestacktrace-parserstatusesstdin-discarderstop-iteration-iteratorstring-lengthstring-natural-comparestring-widthstring.prototype.matchallstring.prototype.repeatstring.prototype.trimstring.prototype.trimendstring.prototype.trimstartstring_decoderstrip-ansistrip-bomstrip-final-newlinestrip-indentstrip-json-commentsstrnumsudo-promptsupports-colorsupports-preserve-symlinks-flagsynckittemptersertest-excludetext-extensionstext-tablethroatthroughthrough2titleizetmptmplto-fast-propertiesto-regex-rangetoidentifiertr46trim-newlinests-nodetslibtsutilsturbo-windows-64type-checktype-detecttype-festtyped-array-buffertyped-array-byte-lengthtyped-array-byte-offsettyped-array-lengthtypedarraytypedarray-to-bufferuglify-jsunbox-primitiveunc-path-regexundici-typesunicode-canonical-property-names-ecmascriptunicode-match-property-ecmascriptunicode-match-property-value-ecmascriptunicode-property-aliases-ecmascriptunique-stringuniversal-user-agentuniversalifyunpipeuntildifyupdate-browserslist-dbupdate-notifieruri-jsurl-joinutil-deprecateutils-mergev8-compile-cache-libv8-to-istanbulvalidate-npm-package-licensevaryvlqvm2walkerwcwidthweb-streams-polyfillwebidl-conversionswhatwg-fetchwhatwg-urlwhichwhich-boxed-primitivewhich-builtin-typewhich-collectionwhich-modulewhich-typed-arraywidest-linewildcard-matchwindows-releaseword-wrapwordwrapwrap-ansiwrappywrite-file-atomicwsxdg-basedirxtendy18nyallistyamlyargsyargs-parserynyocto-queue
0.2.1

8 months ago

0.2.2

8 months ago

0.2.0

8 months ago

0.1.9

8 months ago

0.1.8

8 months ago

0.1.7

8 months ago

0.1.6

8 months ago

0.1.5

8 months ago

0.1.4

8 months ago

0.1.3

8 months ago

0.1.2

8 months ago

0.1.1

8 months ago

0.0.1

8 months ago

0.1.0

8 months ago

1.0.0

3 years ago