## Use the plugin in your app
1. Install Background Sync Plugin from the Forge.
2. In your mobile app module, add a dependency to BackgroundSyncPlugin and select the actions and the EventListenners block you use.
3. Generate a new native build (Android and/or iOS). The plugin is added by the module's extensibility configuration; no manual permissions or iOS background modes are needed.
### Minimal flow
**1. Initialize (OnApplicationReady)**
Call `InitSyncEngine` with:
- `ServerUrl`: base URL of your API, for example `https://<env>/MyApp/rest/Sync`.
- `HeaderJSON`: headers sent with every request, for example `{"Authorization": "Bearer ..."}`.
- `Notifications`: texts of the progress/success/failure notifications (placeholders `{current}`, `{total}`, `{percentage}`, `{error}`).
- `SyncOnlyOnWifi` (default True), `SyncOnlyWhenCharging`, `EnableNotifications`, `AutoDeleteCompleted`, `EncryptDatabase`, `ShowDebugLogs`.
Then call `RequestNotificationsPermission` (Android 13+).
**2. Queue a record**
`EnqueueUpload(RecordId, Payload, Endpoint, filePath?, UploadStrategy?)`
- `RecordId`: your own unique id (recommended): the server can use it to ignore a record sent twice.
- `Payload`: JSON text (for example the result of JSON Serialize of a structure).
- `Endpoint`: path relative to ServerUrl, for example `photos`.
- `filePath`: `file://` URI or plain path of a file in the app's storage. `content://` URIs are not supported: copy the file into the app's data directory first (File Plugin).
**3. Start the sync**
`TriggerSync`. Pending and failed records are sent, in order.
**4. Follow progress**
Place the `EventListenners` block on the screen that shows progress and handle `OnStarted`, `OnProgress`, `OnFailed` and `OnCompleted` (all 7 events are mandatory; the download events can go to an empty action). The events only reach a screen that is open; the queue itself keeps running. To update your own data, read the queue with `GetQueuedUploads` / `GetCompletedUploads` when the screen opens and on `OnCompleted`.
### Server side
Expose a REST method (POST) that receives:
```json
{
"payload": { ...your JSON... },
"file": { "filename": "photo.jpg", "contentType": "image/jpeg", "base64Data": "..." }
}
```
- Use a structure whose attribute names are the JSON keys (`payload`, `file`, `filename`, `contentType`, `base64Data`). Make `base64Data` a Binary Data attribute: OutSystems decodes the base64 for you.
- Return any 2xx when the record is stored; any other status marks it as failed and it is retried.
- BGS Sample Backoffice is a working example of this API.
Full contract: docs/rest-api-signature.md. Pre-signed uploads: docs/presigned-url-uploads.md. Downloads: docs/background-downloads.md.
### Limitations
- One sequential queue: a very large or slow item delays the next ones.
- iOS: about 30 seconds in the background, then the run pauses until the app is opened again.
- Android: force-stopping the app cancels the scheduled work until the app is opened.
- Not available in PWA or in the browser (`IsPluginAvailable` returns False).
See docs/limitations.md for details and per-record limits.
## Run the demo (BGS Sample Mobile)
### Requirements
- **BGS Sample Backoffice**, installed and configured first (its DeviceApiKey site property set).
- Camera Plugin, File Plugin and OutSystems UI (Forge dependencies of the demo).
- An environment that can generate native mobile builds.
### Setup
1. Install Background Sync Plugin together with its demo, BGS Sample Mobile.
2. In Service Center > Factory > Modules > BGSSampleMobile > Site Properties, set **SyncServerUrl** to
`https://<your environment>/BGSSampleBackoffice/rest/FieldAuditSync`
The API key needs no setup here: the app reads it from BGS Sample Backoffice (GetDeviceApiKey).
3. Generate the Android or iOS build of BGS Sample Mobile and install it on a device or emulator.
4. Open the app once while online. It caches the server URL and the key, so later starts work offline.
### Run it
1. In the app, tap **New demo audit**. It creates an audit with three findings.
2. On each finding, tap **+5 sample photos** (JPEGs of 1 to 2 MB generated on the device, so it works on an emulator) or **Take photo**.
3. Tap **Sync audit**. The app queues one record per photo and opens the Sync screen.
4. In BGS Sample Backoffice, open the audit: the photo grid fills as the uploads arrive.
5. Send the app to the background or lock the screen: on Android the uploads and the progress notification continue.
6. Turn on airplane mode during a run: the Sync screen shows the failure, the photos stay queued, and the upload resumes on its own when the connection is back. A photo sent twice is stored once and shown as re-sent.
7. **Reset demo data** in the backoffice deletes everything received.
### Where to look in the demo code
| What | Where (BGS Sample Mobile) |
| --- | --- |
| Plugin initialization | OnApplicationReady > RefreshSyncSettings, StartSyncEngine |
| Saving photos as files | AddCameraPhoto, AddSamplePhotos |
| Queueing and starting the sync | QueueAuditForSync |
| Following the sync | SyncStatus screen (EventListenners block), GetQueueCounts |
| Updating local data from the queue | ReconcilePhotosWithQueue |
| Receiving the uploads | BGS Sample Backoffice > FieldAuditSync REST API > photos, StorePhoto |