Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ This PWA Wrapper documentation section includes the following topics:
* Signing reference: [Sign PWA Wrapper Apps](/refguide/mobile/distributing-mobile-apps/pwa-wrapper/sign-pwa-wrapper-apps/) explains the signing step in the build flow
* Capabilities guide: [PWA Wrapper Capabilities](/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-capabilities/)
* Limitations: [PWA Wrapper Limitations](/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-limitations/)
* Deep linking guide: [PWA Wrapper Deep Linking](/refguide/mobile/pwa-wrapper/pwa-wrapper-deep-linking/) explains how to handle inbound and outbound deep links
* Security and network access reference: [PWA Wrapper Security and Network Access](/refguide/mobile/pwa-wrapper/pwa-wrapper-security/) describes what the extension downloads, what local paths it scans, and which binaries it bundles
* Troubleshooting: [Troubleshoot PWA Wrapper](/refguide/mobile/pwa-wrapper/pwa-wrapper-troubleshooting/) lists known issues and solutions

## Typical Use Cases

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Verify the final packaged app on representative physical devices before release.
| Upload videos from the camera or gallery | Lets the user capture a video or select an existing video for upload. | Yes | No |
| Geolocation | Retrieves the device location for map, tracking, or location-aware flows. | Yes | Yes |
| Local notification | Schedules or shows notifications generated by the app on the device. | No | Yes |
| Push notification (remote) | Receives remote push notifications sent from a server via Firebase Cloud Messaging (FCM). | No | Yes |
| Permissions | Checks or requests supported runtime permissions from the app flow. | No | Yes |
| Biometric authentication | Checks biometric availability and prompts the user for biometric authentication. This depends on device hardware and biometric enrollment. | Yes | No |

Expand Down Expand Up @@ -60,9 +61,14 @@ This mapping is guidance, not a fixed contract. Exact permission prompts can var
| Upload videos from the camera or gallery | `Camera`, `Record Audio` | `Camera Usage`, `Microphone Usage` |
| Geolocation | `Fine Location`, `Coarse Location` | `Location - When In Use Usage` |
| Local notification | `Notifications` | No explicit builder permission message required |
| Push notification (remote) | `Notifications` | No explicit builder permission message required |

When a capability relies on camera, location, or notifications, align the configured builder permissions with the JavaScript actions your app actually calls. For video capture flows, also verify whether the target platform requires microphone permission.

{{% alert color="info" %}}
Push notifications require Firebase Cloud Messaging (FCM) integration through the Push Notifications Connector module. For detailed setup instructions for wrapped PWAs, see [PWA Wrapper: Push Notification Setup](/refguide/mobile/using-mobile-capabilities/push-notifications/notif-pwa-wrapper/).
{{% /alert %}}

## Designing with Capabilities

When you build a Mendix app with PWA Wrapper capabilities, follow these guidelines:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
---
title: "PWA Wrapper Deep Linking"
url: /refguide/mobile/pwa-wrapper/pwa-wrapper-deep-linking/
weight: 40
description: "How to implement deep linking in your PWA Wrapper app to enable inbound and outbound URL handling."
---

## Introduction

Deep linking enables users to jump directly to specific content in your app via URLs or schemes. PWA Wrapper supports two independent deep linking flows:

* **Outbound** — your Mendix app opens a URL or deep link (e.g., jumping to another app)

Check failure on line 12 in content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Mendix.Latin] Use 'for example, ' instead of 'e.g., '. Raw Output: {"message": "[Mendix.Latin] Use 'for example, ' instead of 'e.g., '.", "location": {"path": "content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md", "range": {"start": {"line": 12, "column": 60}}}, "severity": "ERROR"}

Check failure on line 12 in content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead. Raw Output: {"message": "[Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead.", "location": {"path": "content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md", "range": {"start": {"line": 12, "column": 15}}}, "severity": "ERROR"}
* **Inbound** — the operating system launches your wrapped app via a registered deep link scheme, and the wrapper routes it into your app content

Check failure on line 13 in content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead. Raw Output: {"message": "[Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead.", "location": {"path": "content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md", "range": {"start": {"line": 13, "column": 14}}}, "severity": "ERROR"}

This guide covers both flows.

## Part 1: Outbound — Opening URLs and Deep Links

Check failure on line 17 in content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead. Raw Output: {"message": "[Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead.", "location": {"path": "content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md", "range": {"start": {"line": 17, "column": 20}}}, "severity": "ERROR"}

Check failure on line 17 in content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Mendix.ListIntroductions] Set off list item introductions with an en dash (–), not an em dash (—). Raw Output: {"message": "[Mendix.ListIntroductions] Set off list item introductions with an en dash (–), not an em dash (—).", "location": {"path": "content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md", "range": {"start": {"line": 17, "column": 12}}}, "severity": "ERROR"}

Use the **OpenDeepLink** JavaScript action to open external URLs or deep links from your nanoflows:

```
OpenDeepLink(url: string): Promise<boolean>
```

### Behavior

**iOS and Android:** Returns `true` or `false` based on success. Catches errors and returns `false` on failure.

### Important Caveat

On both Android and iOS, the result of `OpenDeepLink` (true/false) indicates only that the call succeeded—not whether the target app could actually handle the link. Always test with the actual target apps you expect to open.

## Part 2: Inbound — Registering Deep Link Schemes and Hosts

Check failure on line 33 in content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead. Raw Output: {"message": "[Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead.", "location": {"path": "content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md", "range": {"start": {"line": 33, "column": 19}}}, "severity": "ERROR"}

Check failure on line 33 in content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Mendix.ListIntroductions] Set off list item introductions with an en dash (–), not an em dash (—). Raw Output: {"message": "[Mendix.ListIntroductions] Set off list item introductions with an en dash (–), not an em dash (—).", "location": {"path": "content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md", "range": {"start": {"line": 33, "column": 12}}}, "severity": "ERROR"}

Configure deep link schemes and hosts in the PWA Wrapper Builder during the app info step. The builder includes a **Deep Link editor** where you define which schemes and hosts your app should respond to.

### Adding a Deep Link Entry

Each deep link entry requires:

* **scheme** (required) — e.g., `myapp`, `pwa`, or `https`/`http` for universal/app links

Check failure on line 41 in content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead. Raw Output: {"message": "[Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead.", "location": {"path": "content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md", "range": {"start": {"line": 41, "column": 24}}}, "severity": "ERROR"}
* **host** (required) — domain or authority to match, e.g., `example.com`

Check failure on line 42 in content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead. Raw Output: {"message": "[Mendix.Dashes] Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead.", "location": {"path": "content/en/docs/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-deep-linking.md", "range": {"start": {"line": 42, "column": 22}}}, "severity": "ERROR"}
* **path** fields (optional, pick at most one):
* **path** — exact path to match (e.g., `/profile`)
* **pathStartWith** — path prefix to match (e.g., `/jump` catches `/jump/profile`)
* **linkFeature** — free-text label (metadata only, affects HarmonyOS builds)
* **platform** — `Android`, `iOS`, `HarmonyOS`, `all`, or unset (unset or `all` applies to every platform)

### Common Deep Link Patterns

**Custom scheme (works everywhere, no domain ownership needed):**

* scheme: `myapp`
* host: `example.com`
* path fields: empty
* Result: catches `myapp://example.com/...`

**Universal Link / App Link (requires domain ownership):**

* scheme: `https`
* host: `yourapp.com`
* pathStartWith: `/jump`
* Result: catches `https://yourapp.com/jump/*` from any context that supports it

## Part 3: What the Builder Configures Per Platform

The PWA Wrapper builder automatically registers your configured deep links with the operating system. You do not need to manually edit any native configuration files — the builder handles everything behind the scenes.

## Part 4: Domain Verification Files (Manual Setup Required)

{{% alert color="warning" %}}
For `https` scheme links (Android App Links and iOS Universal Links), the operating system requires verification files hosted on your own domain. The PWA Wrapper builder does NOT generate or host these files—you must create and publish them yourself.

Without these verification files, `https` links will open in the browser instead of the app. Android may display a disambiguation dialog; iOS Universal Links will fail silently.
{{% /alert %}}

### Android: assetlinks.json

Create and host `https://yourdomain.com/.well-known/assetlinks.json` on your web server. The file must be:

* Valid JSON
* Served with `Content-Type: application/json`
* Accessible via `https` only (not `http`)

**Example structure:**

```json
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.yourcompany.yourapp",
"sha256_cert_fingerprints": ["AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78"]
}
}
]
```

To find your app's SHA-256 fingerprint, use `jarsigner` or the Android Studio Build Variants panel after signing your APK.

### iOS: apple-app-site-association

Create and host `https://yourdomain.com/.well-known/apple-app-site-association` on your web server. The file must be:

* Valid JSON (no `.json` extension in the path)
* Served with `Content-Type: application/json`
* Accessible via `https` only (not `http`)

**Example structure:**

```json
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAM_ID.com.yourcompany.yourapp",
"paths": ["/jump/*"]
}
]
}
}
```

The `appID` format is `TEAM_ID.BUNDLE_ID`. The `paths` array should match the paths you configured in the PWA Wrapper Builder.

### Hosting the Files

The `.well-known` directory must be accessible at the root of your domain via `https`. The typical approach is:

* **Mendix Cloud:** Upload the verification files to your Mendix Cloud environment's static file directory. Refer to [Mendix Cloud documentation](/developerportal/deploy/) for details on serving static files, or contact Mendix Support.
* **Custom Domain or External Hosting:** If your Mendix app is behind a reverse proxy or hosted on a custom domain, ensure the `.well-known` directory is properly configured to serve these files at the domain root.

### Testing File Accessibility

Verify your files are correctly hosted:

```bash
curl -I https://yourdomain.com/.well-known/assetlinks.json
curl -I https://yourdomain.com/.well-known/apple-app-site-association
```

Both should return HTTP 200 with `Content-Type: application/json`.

## Part 5: How Inbound Links Reach Your App Content

Once a deep link is caught by the wrapper, it is routed into your app's runtime. The exact process depends on the platform:

**Android:**

The wrapper loads the incoming deep link in the webview.

**iOS:**

The wrapper loads the incoming deep link in the webview.

**Implication for your app:** Your Mendix app's routing (pages, deep-link microflows, etc.) must be configured to handle the deep link URL.

## Common Deep Linking Pitfalls

* **Missing verification files** — forgetting to create and host `assetlinks.json` (Android) or `apple-app-site-association` (iOS) for `https` scheme links is the most common integration failure.
* **Using https without domain ownership** — `https` scheme links require that you own and control the domain; do not use `https` for domains you do not own.
* **Misinterpreting the OpenDeepLink return value** — the boolean result only indicates the call succeeded, not whether the target app successfully opened or handled the link.
* **Mismatched path configuration** — ensure your `path` and `pathStartWith` values match the actual Mendix page URLs or deep-link microflow entry points your app exposes.

## Read More

* [PWA Wrapper](/refguide/mobile/distributing-mobile-apps/pwa-wrapper/)
* [PWA Wrapper Capabilities](/refguide/mobile/distributing-mobile-apps/pwa-wrapper/pwa-wrapper-capabilities/)
* [Build PWA Wrapper Apps](/refguide/mobile/distributing-mobile-apps/pwa-wrapper/build-pwa-wrapper-apps/)
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: "PWA Wrapper Security and Network Access"
url: /refguide/mobile/pwa-wrapper/pwa-wrapper-security/
weight: 50
description: "Describes the network access and local filesystem scanning behavior of PWA Wrapper for security and IT reviewers."
---

## Introduction

This page describes two behaviors of PWA Wrapper that are relevant for security reviews and IT governance: what the extension downloads from the network during a build, and what local paths and environment variables it inspects to detect existing developer tool installations.

This information is intended for security engineers, IT administrators, and other reviewers who need a precise account of what the extension does outside its own process boundary. It does not cover general build usage; for that, see [Build PWA Wrapper Apps](/refguide/mobile/distributing-mobile-apps/pwa-wrapper/build-pwa-wrapper-apps/).

## Network Downloads During Build

PWA Wrapper itself does not download anything when it is installed or when Studio Pro starts. Network access happens at build time, through platform-standard build tooling, not through custom code in the extension. The following two downloads can occur on the first build for each respective platform.

### Android: Gradle Wrapper Distribution

Android builds are run via the Gradle Wrapper, which is standard for Android and Gradle-based projects. On the first Android build, the Gradle Wrapper checks whether the required Gradle distribution is already cached locally. If it is not, the wrapper downloads the following archive and caches it for all subsequent builds:

| Property | Value |
| --- | --- |
| File | `gradle-8.9-bin.zip` |
| URL | `https://services.gradle.org/distributions/gradle-8.9-bin.zip` |
| Host | `services.gradle.org` (Gradle's official distribution server, operated by Gradle, Inc.) |
| Cache location | `~/.gradle/wrapper/dists/gradle-8.9-bin/` |
| Trigger | First Android build on a machine; not re-downloaded on subsequent builds or on extension install |

This is standard Gradle Wrapper behavior, identical to any Gradle-based Android project. It is not custom logic added by PWA Wrapper.

To avoid this download in air-gapped environments, pre-populate the Gradle wrapper cache directory before running the first build.

## Bundled Binaries Executed Locally

In addition to the runtime downloads above, PWA Wrapper ships the following binaries inside its own extension package. These are not downloaded at build time — they are included in the extension at install time and are invoked as local subprocesses during Android and HarmonyOS build, signing, and packaging steps. They run with the same operating-system privileges as the Studio Pro process.

| Binary | Purpose | Platform |
| --- | --- | --- |
| `apktool.jar` | Decoding and rebuilding Android APKs | Android |
| `bundletool.jar` | Building and manipulating Android App Bundles | Android |
| `aapt2` / `aapt2.exe` | Android Asset Packaging Tool | Android |
| `apksigner.jar` | APK signing | Android |
| `android.jar` | Android SDK stub library used during compilation | Android |

These binaries are third-party open-source tools redistributed with the extension. They are not fetched from the network at runtime.

## Local Filesystem and Environment Scanning

When the builder opens, PWA Wrapper inspects the local machine to auto-detect existing developer tool installations. This is a read-only discovery process: no data leaves the machine, and no files are created or modified. The scan is performed so users do not have to manually configure tool paths.

### JDK Discovery

PWA Wrapper needs a Java runtime to execute the build tools listed above. It searches for an installed JDK in the following order and uses the first usable result it finds.

**On macOS:**

| Step | Method |
| --- | --- |
| 1 | Read the `JAVA_HOME` environment variable, if set |
| 2 | Run `/usr/libexec/java_home` — the operating-system JDK registry |
| 3 | Resolve `java` on the shell `PATH` (equivalent to `which java`) |
| 4 | Scan `/Library/Java/JavaVirtualMachines/` — the standard directory where installers such as Adoptium/Temurin, Oracle, and Azul place JDKs |

**On Windows:**

On Windows, JDK discovery does not scan directories. Instead it reads the output of `mx show-java-version` and inspects the Mendix Studio Pro settings database (`Settings.sqlite`) to find the JDK path configured in Studio Pro.

If no usable JDK is found, the build fails with an error that instructs the user to install a JDK from [Adoptium](https://adoptium.net) or set `JAVA_HOME` manually. PWA Wrapper does not download a JDK on the user's behalf.

### Mendix Studio Pro Discovery

PWA Wrapper needs to locate the Mendix Studio Pro installation to access the runtime and SDK files it uses during the build.

**On macOS:** The extension scans `/Applications/` and `~/Applications/` for app bundles whose names match "Mendix Studio Pro" or "Studio Pro". Among all matches that contain a valid `runtime/` subdirectory, it selects the one with the highest version number.

**On Windows:** Auto-detection is not performed. The Studio Pro path must be provided explicitly via a CLI argument, a `.env` file, or a `.launch` file.

## Summary for Reviewers

| Category | What happens | When | Data leaves machine? |
| --- | --- | --- | --- |
| Gradle distribution download | Downloads `gradle-8.9-bin.zip` from `services.gradle.org` | First Android build only | No (download only; no data sent) |
| Bundled binary execution | Runs `apktool.jar`, `bundletool.jar`, `aapt2`, `apksigner.jar`, `android.jar` locally | Every applicable build | No |
| JDK filesystem scan | Reads `JAVA_HOME`, `/Library/Java/JavaVirtualMachines/`, version manager directories, or Windows Studio Pro settings | When the builder opens | No |
| Studio Pro filesystem scan | Scans `/Applications/` and `~/Applications/` for Studio Pro app bundles (macOS only) | When the builder opens | No |

PWA Wrapper makes no telemetry calls, analytics requests, or other network connections beyond the two build-time package downloads described above.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: "Troubleshoot PWA Wrapper"
url: /refguide/mobile/pwa-wrapper/pwa-wrapper-troubleshooting/
weight: 60
description: "Known issues and solutions for PWA Wrapper."
---

## Introduction

This page describes known issues you may encounter when building or testing PWA Wrapper apps, along with the steps to resolve them.

## Android

### App Cannot Connect to localhost on a Physical Device{#android-localhost}

**Symptom**: When you set the runtime URL to a localhost address (for example, `http://localhost:8080`) and install the app on a physical Android device, the app fails to load and shows the following error:

```
Page Load Error
net::ERR_CACHE_MISS
```

{{< figure src="/attachments/refguide/mobile/pwa-wrapper/localhost-cache-miss-error.png" alt="Page Load Error showing net::ERR_CACHE_MISS on Android" max-width="400px" >}}

**Cause**: Two things are required for a physical Android device to reach a localhost server on your machine:

1. The app must have the `INTERNET` permission. Without it, the Android OS blocks all outbound network traffic.
2. The device must have a port forwarding rule from its own localhost to your machine's localhost. Android devices do not forward ports automatically.

**Solution**:

1. In the PWA Wrapper builder, go to the **Permissions** step and enable the **INTERNET** permission.

For general guidance on permissions, see [Build PWA Wrapper Apps](/refguide/mobile/distributing-mobile-apps/pwa-wrapper/build-pwa-wrapper-apps/).

1. Connect the Android device to your machine via USB and make sure [USB debugging](https://developer.android.com/studio/debug/dev-options) is enabled on the device.

1. Run the following ADB command to forward port 8080 from the device to your machine:

```shell
adb reverse tcp:8080 tcp:8080
```

If your Mendix runtime uses a different port, replace `8080` with the correct port number on both sides.

1. Rebuild and reinstall the app with the localhost runtime URL.

The app can now reach the Mendix runtime running on your development machine.

{{% alert color="info" %}}
The `adb reverse` rule applies only to the current USB session. You must re-run the command each time you reconnect the device or restart ADB.
{{% /alert %}}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ These guides teach you how to configure push notifications (also known as remote
* [Configuring Push Notifications](/refguide/mobile/using-mobile-capabilities/push-notifications/notif-config-push/) – Learn to configure push notifications in the runtime.
* [Implementing Push Notifications in Your Native App](/refguide/mobile/using-mobile-capabilities/push-notifications/notif-implement-native/) – Implement push notifications for a native app.
* [Implementing Push Notifications in Your Progressive Web App](/refguide/mobile/using-mobile-capabilities/push-notifications/notif-implement-pwa/) – Implement push notifications for a progressive web app.
* [PWA Wrapper Push Notification Setup](/refguide/mobile/using-mobile-capabilities/push-notifications/notif-pwa-wrapper/) – Configure notification-related settings when packaging your progressive web app with PWA Wrapper.
* [Sending Your First Test Push Notification](/refguide/mobile/using-mobile-capabilities/push-notifications/notif-send-test/) – Send a test notification to confirm your app is working properly.

After you complete the tasks above, you may wish to do more advanced tasks with notifications. For information on **sending push notifications to multiple devices**, use this documentation:
Expand Down
Loading
Loading