Install Guides
React Native
this article provides instructions on adding the ditto package to your project by importing, initializing, and preparing ditto to be integrated successfully with your react native apps /#react native cli support docid\ spsytnqhwpjyhm1j8lfgl docid\ spsytnqhwpjyhm1j8lfgl /#configuring sync /#enabling small peer info /#setting up presence /#setting logs to debug level docid\ spsytnqhwpjyhm1j8lfgl react native cli support the ditto sdk is designed for apps built with https //reactnative dev/docs/getting started without a framework expo go is not supported, and other expo workflows (such as development builds) have yet to be added to the sdk once you've confirmed that you have the necessary prerequisites, integrate ditto within your react native app set up a react native cli project ( /#creating your project ) install the ditto package into your project ( /#installing the ditto sdk ) install the project dependencies ( /#installing dependencies ) enable your app to sync with nearby devices ( /#configuring permissions ) import the previously installed ditto sdk package in your app ( /#initializing ditto ) set up permissions handling ( /#handling permissions ) set up authentication ( /#setting up authentication ) specify how ditto should handle sync ( /#creating a new instance of ditto ) set up transport configurations ( /#setting transport configurations ) initiate sync at global scope ( docid\ spsytnqhwpjyhm1j8lfgl ) if desired, enable the small peer information feature ( /#enabling small peer info ) if desired, monitor the activity of remote peers in the mesh by logging relevant information in logs or using ditto ’s presence viewer app ( /#setting up presence ) if desired, set the log level to debug ( /#setting logs to debug level ) create your subscription logic ( docid\ spsytnqhwpjyhm1j8lfgl ) creating your project first, set up your environment and initialize your react native project, seeing it build successfully for instructions, see react native's official documentation on https //reactnative dev/docs/set up your environment then, proceed by https //reactnative dev/docs/getting started without a framework to verify that you’ve set up your environment correctly, install and run the react native cli doctor for more information, see the official https //reactnative dev/blog/2019/11/18/react native doctor blog post installing the ditto sdk from a terminal, navigate to the folder containing your react native project, and then, using your preferred package manager, install the ditto package yarn yarn add @dittolive/ditto npm npm install @dittolive/ditto installing dependencies from the root of your project, install project dependencies based on the package json file yarn yarn install npm npm install configuring permissions once you've added dependencies, set up the prerequisites to enable ditto transports for ios and android ios from xcode, enable bluetooth low energy (ble) and local network services in your app install pods and make sure you use a compatible minimum ios version from the ios/podfile file in your project, set the minimum deployment target for ios platform \ ios, 14 tip no version changes are needed for rn 0 76+ projects that already have min ios version supported set to 14 be sure to reinstall pods afterward pod install from your project's info plist file, add the following key value pairs \<?xml version="1 0" encoding="utf 8"?> \<!doctype plist public " //apple//dtd plist 1 0//en" "http //www apple com/dtds/propertylist 1 0 dtd"> \<plist version="1 0"> \<dict> \<key>nsbluetoothalwaysusagedescription\</key> \<string>uses bluetooth to connect and sync with nearby devices \</string> \<key>nslocalnetworkusagedescription\</key> \<string>uses wifi to connect and sync with nearby devices \</string> \<key>nsbonjourservices\</key> \<array> \<string> http alt tcp \</string> \</array> \<! your other keys > \</dict> \</plist> tip to view info plist as source code, right click the file from the left sidebar in xcode > click open as > and then select source code from the menu if desired, customize the default values for the permission prompts by replacing them with your preferred text for example, if your end users prefer a language other than english, you can replace the default english strings with their language equivalents once implemented, these string values display to your end users as dismissable prompts explaining why the app requires certain permissions ensure your app continues to sync while it runs in the background by enabling bluetooth le background modes once enabled, your app continuously syncs in the background, even while the device is locked for official instructions, see https //developer apple com/documentation/xcode/configuring background execution modes from apple from the left sidebar, click to select your project click signing & capabilities click + capability, and then from the modal that appears, search and select background modes from targets , select your app from the list from background modes , toggle the following uses bluetooth le accessories acts as a bluetooth le accessory android from android studio, set up transport configurations for the android target use a compatible android minimum sdk version open the project level build gradle located in the android root directory set the minsdkversion to 24 other projects might require setting the sdk version in android/gradle properties configuring permissions the android operating system limits access to some device functionality for end user control and privacy in order to use this functionality , configure your app to declare and request permissions from end users at runtime declar ing permissions in the android manifest android requires the app to explicitly request certain permissions to access features like bluetooth low energy and wi fi aware these permissions must be declared in the app's manifest file and requested from the end user at runtime the ditto sdk's androidmanifest xml includes all the necessary permissions to enable its mesh network capabilities these permissions will automatically be merged with your app's permissions, so you should be aware of them androidmanifest xml \<uses permission android\ name="android permission bluetooth" android\ maxsdkversion="30" /> \<uses permission android\ name="android permission bluetooth admin" android\ maxsdkversion="30" /> \<uses permission android\ name="android permission bluetooth advertise" tools\ targetapi="s" /> \<uses permission android\ name="android permission bluetooth connect" tools\ targetapi="s" /> \<uses permission android\ name="android permission bluetooth scan" android\ usespermissionflags="neverforlocation" tools\ targetapi="s" /> \<uses permission android\ name="android permission access fine location" android\ maxsdkversion="32" /> \<uses permission android\ name="android permission access coarse location" android\ maxsdkversion="30" /> \<uses permission android\ name="android permission internet" /> \<uses permission android\ name="android permission access wifi state" /> \<uses permission android\ name="android permission access network state" /> \<uses permission android\ name="android permission change network state" /> \<uses permission android\ name="android permission change wifi multicast state" /> \<uses permission android\ name="android permission change wifi state" /> \<uses permission android\ name="android permission nearby wifi devices" android\ usespermissionflags="neverforlocation" tools\ targetapi="tiramisu" /> some of these permissions have an android\ maxsdkversion attribute, which means they are not used on devices running newer versions of android this is a best practice for respecting users' privacy when those permissions are unnecessary however, some apps may still need to use one or more of the above permissions across more versions of android this can be accomplished by overriding the permission configuration in your app's androidmanifest xml to override any of these permission limitations in your app, do the following open the androidmanifest xml located in your project's app/src/main directory within the same \<manifest> tag, just before the \<application> tag, add the relevant permissions you want to configure (location example) androidmanifest xml \<uses permission android\ name="android permission access fine location" tools\ remove="android\ maxsdkversion" /> \<uses permission android\ name="android permission access coarse location" tools\ remove="android\ maxsdkversion" /> note the additional tools\ remove the attribute this tells the manifest merger to selectively remove the android\ maxsdkversion behavior from the associated permissions, changing them to apply to all android versions if using https //reactnative dev/docs/the new architecture/landing page , you must add the following code snippet to the module level build gradle located in the android/app directory android { packagingoptions { pickfirst 'lib/x86/libjsi so' pickfirst 'lib/x86 64/libjsi so' pickfirst 'lib/armeabi v7a/libjsi so' pickfirst 'lib/arm64 v8a/libjsi so' pickfirst 'lib/x86/libdittoffi so' pickfirst 'lib/x86 64/libdittoffi so' pickfirst 'lib/armeabi v7a/libdittoffi so' pickfirst 'lib/arm64 v8a/libdittoffi so' } // rest of the file } start the app in metro yarn start initializing ditto within the top most scope of your app, import the ditto package with the necessary modules and components from the ditto's sdk library import {ditto} from '@dittolive/ditto'; handling permissions within your default react component ( app ), use this helper function to request permissions if developing for the android target import {useeffect} from 'react'; import {permissionsandroid} from 'react native'; export default function app() { async function requestpermissions() { const granted = await permissionsandroid requestmultiple(\[ permissionsandroid permissions bluetooth connect, permissionsandroid permissions bluetooth advertise, permissionsandroid permissions nearby wifi devices, permissionsandroid permissions bluetooth scan, ]); object entries(granted) foreach((\[permission, result]) => { if (result === permissionsandroid results granted) { console log(`${permission} granted`); } else { console log(`${permission} denied`); } }); } useeffect(() => { requestpermissions(); }, \[]); } configuring sync using an asynchronous function, let's say, startsync() , do the following define an identity configuration with authentication settings ( /#setting up authentication ) instantiate a ditto object with the specified identity ( /#creating a new instance of ditto ) configure peer to peer transport settings and enable transports ( /#setting transport configurations ) initiate sync ( docid\ spsytnqhwpjyhm1j8lfgl ) setting up authentication create an identity object, define your authentication type , and provide access credentials to sync, each instance of ditto running in your app must prove its identity to other peers there are two types of identities you can use to authenticate onlineplayground — explore platform features and functionality without setting up your authentication mechanism onlinewithauthentication — if developing a production level app, integrate your own identity provider, such as auth0, identify users, give users read or write control, and integrate with your existing authentication systems for more information, see docid 6exkalkyxp2fcbsoan6 q onlineplayground use an online playground identity for development you can find authentication details for your app on the https //portal ditto live use these to set up your identity import type {identity} from '@dittolive/ditto'; const identity = { type 'onlineplayground', appid '\<your app id>', token '\<your online playground token>', }; onlinewithauthentication use the onlinewithauthentication identity when developing a production app for deployment const identity = { type 'onlinewithauthentication', appid '\<your app id>', authhandler { authenticationrequired(authenticator) { if (authenticator loginsupported) { authenticator loginwithtoken( 'will accept any password', 'auth webhook' ); console log('successfully logged in'); } }, authenticationexpiringsoon function (authenticator) { authenticator loginwithtoken('will accept any password', 'auth webhook'); console log('successfully relogged'); }, }, }; creating a new instance of ditto within a try statement, instantiate a new ditto object with the identity you’ve specified import {ditto, dittoerror} from '@dittolive/ditto'; try { const ditto = new ditto(identity); } catch (error) { if (error instanceof dittoerror) { // handle errors starting ditto } throw error } setting transport configurations using a transportconfig instance, do the following to set up transport configurations in your app c onfigure peer to peer transport settings so that all desired transport types available on the end user device are available to ditto s pecify how you want ditto to handle which transports to sync data across the mesh import {transportconfig} from '@dittolive/ditto'; import {platform} from 'react native'; const transportsconfig = new transportconfig(); transportsconfig peertopeer bluetoothle isenabled = true; transportsconfig peertopeer lan isenabled = true; transportsconfig peertopeer lan ismdnsenabled = true; // apple wireless direct link is only available on apple devices if (platform os === 'ios') { transportsconfig peertopeer awdl isenabled = true; } ditto settransportconfig(transportsconfig); constructing sync subscription logic create the logic that performs sync and data operations in your app, including registering subscriptions, executing store operations, and observing changes in the given collection for more information, see docid\ kp b7z 3t6pzqt2wryyxm and docid 6fiopaeonmv1kfc90smho for example, the following snippet defines a document object ( document ), creates a subscription for the cars collection, executes database operations and logs the results, registers an observer for watching changes in the cars collection ditto sync registersubscription(`select from cars`); const document = { id 987654, id 123131, model "cx 5", make "mazda", color "blue", }; const queryresult = await ditto store execute( "insert into cars documents (\ document) on id conflict do update", { document } ); console log(queryresult items map((item) => item value)); console log( "mutated", queryresult mutateddocumentids() map((docid) => docid value) ); } ditto store registerobserver(`select from cars`, (response) => { const parseddocuments = response items map((doc) => { return doc value; }); // save state or other use cases }); starting the sync process to start syncing with other peers in the mesh ditto startsync(); enabling small peer info enabling the smallpeerinfo feature allows you to gather and store peer to peer sync and network details automatically rather than continuously query ditto for this data once enabled, collected details are available within the ditto portal for more information, see docid\ ld343 2lgt0 3nkaw2qnr you can configure smallpeerinfo directly on the ditto instance ditto smallpeerinfo isenabled = true; await ditto smallpeerinfo getsyncscope(); await ditto smallpeerinfo setsyncscope('bigpeeronly'); ditto smallpeerinfo metadata = { test 'metadata' }; setting up presence monitor remote peers in the logs or using ditto’s presence viewer app for more information, see the blog post “ https //ditto live/blog/ditto presence viewer ” to set up presence observations // this closure is called every time the mesh of // connected ditto peers changes ditto presence observe((graph) => { console log('peers ', graph remotepeers); }); setting logs to debug level capture database debug logs by setting the ditto log level to debug mode that way, any potential issues are tracked to set the minimum log level to debug logger minimumloglevel = 'debug'; known issues https //reactnative dev/docs/fast refresh will throw an error with the current ditto architecture, insisting you provide a different persistence directory name currently, no workaround is available; however, developers can disable fast refresh to avoid this issue our team is actively working on a fix, and we appreciate your patience as we address this challenge