Web AR Experience Integration
-
This document describes how to integrate the Web version of Xense AR into third-party applications using WebView or external browser/App Clip launch.
-
The current version of the Web AR SDK supports:
- VPS (Visual Positioning Service) for registered locations.
- Rendering of basic AR content in GLB, GLTF, and Image formats.
- AR Navigation functionality.
Supported platforms:
- Flutter
- React Native
- Native
1. Integration via WebView
Flutter Project
-
Download the integration template (includes required dependencies):
https://gitlab.com/educationxrmhmp-group/flutter-webar.git -
Follow the setup instructions in the README:
https://gitlab.com/educationxrmhmp-group/flutter-webar/-/blob/main/README.md?ref_type=heads
React Native Project
-
Download the integration template (includes required dependencies):
https://gitlab.com/educationxrmhmp-group/reactnative-webar.git -
Follow the setup instructions in the README:
https://gitlab.com/educationxrmhmp-group/reactnative-webar/-/blob/main/README.md?ref_type=heads
2. Native Project
Android Project
Download the Template project before getting started.
- Open the
AndroidManifest.xmlfile and add the following declaration:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<!-- ... -->
<queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
<!-- ... -->
<application>
<!-- ... -->
</application>
</manifest>- Add the dependency to the app’s build.gradle file.
plugins {
<!-- ... -->
}
android {
<!-- ... -->
}
dependencies {
implementation("androidx.browser:browser:1.8.0")
<!-- ... -->
}- Create a new class named TwaManager and copy its implementation from the Template project.
- To launch the AR experience, create an instance of TwaManager.
- Launch the AR experience using the
launchARfunction of TwaManager, which accepts the following parameters:worldID: Get the corresponding value from the Portal.blockID: Get the corresponding value from the Portal.modelScale: Get the corresponding value from the Portal.indexUrl: Provided by Xense.command: Optional — leave empty if the navigation flow does not need to start immediately.locationID: Optional — additional information for the command.
iOS project
Download the Template project before getting started.
- Create an
XenseARManager.swiftfile and copy the contents from the corresponding file in the Template Project. - Add the
XenseARWebGLframework from the Template Project and set the Embed option to Embed & Sign. - Add the
ZIPFoundationpackage from:https://github.com/weichsel/ZIPFoundation. Then addZIPFoundationto Frameworks, Libraries, and Embedded Content. - To launch the AR experience, use the
XenseARManagerclass.
- To launch the AR experience, call the
launchARfunction ofXenseARManagerwith the following parameters:worldID: Get the corresponding value from the Portal.blockID: Get the corresponding value from the Portal.modelScale: Get the corresponding value from the Portal.indexUrl: Provided by Xense.command: Optional — leave empty if the navigation flow does not need to start immediately.locationID: Optional — additional information for the command.
3. Launch AR Experience Externally
If you do not want to embed the AR module inside your application, you can launch the AR experience externally:
- iOS → via App Clip
- Android → via Chrome browser
All URL parameters (worldID, blockID, command, indexUrl) are provided by Xense.
Flutter Implementation
Add the url_launcher dependency and open the URL using the parameters provided by Xense.
Below is a sample code snippet demonstrating how to launch the AR experience in a Flutter project.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const String worldID = 'blossom';
const String blockID = '3e2a6da2-e248-4dd7-9f09-d5ffbaa17b31';
const String command = 'data~eyJ0eXBlIjoic3RhcnROYXZpZ2F0aW9uIiwibG9jYXRpb25JRCI6IjkwMTcwZGIxLWQ5NTgtNDkyYy04NmNhLTI3NDIyMGQ2NmI3NiJ9';
const String indexUrl = 'cdn.xensear.vn/custom-frontend/threejs_production/benhvienbachmai/HLOCTracking.html';
String experienceUrlIOS =
'https://appclip.apple.com/id'
'?p=com.viettel.mhmp.ARWorld.Clip'
'&worldID=$worldID'
'&blockID=$blockID'
'&command=$command'
'&indexUrl=$indexUrl';
String experienceUrlAndroid =
'https://$indexUrl'
'?worldID=$worldID'
'&blockID=$blockID'
'&command=$command'
'&indexUrl=$indexUrl';
// Above URLs are provided by Xense.
Future<void> _openARExperience() async {
if (Platform.isAndroid) {
experienceUrl = androidExperienceUrl;
}
final Uri url = Uri.parse(experienceUrl);
if (Platform.isAndroid) {
await launchUrl(
url,
mode: LaunchMode.externalApplication,
);
} else {
if (await canLaunchUrl(url)) {
await launchUrl(
url,
mode: LaunchMode.externalApplication,
);
} else {
print("Could not launch AR Experience");
}
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: Text("Open AR Experience")),
body: Center(
child: ElevatedButton(
onPressed: _openARExperience,
child: Text("Open AR Experience"),
),
),
),
);
}
}React Native Implementation
Open the URL using the parameters provided by Xense.
Below is a sample code snippet demonstrating how to launch the AR experience in a React Native project.
import { View, Button, StyleSheet, Platform, Alert } from 'react-native';
import * as Linking from 'expo-linking';
export default function HomeScreen() {
const worldID = "mhmp_blossom";
const blockID = "3e2a6da2-e248-4dd7-9f09-d5ffbaa17b31";
const command = "data~eyJ0eXBlIjoic3RhcnROYXZpZ2F0aW9uIiwibG9jYXRpb25JRCI6IjkwMTcwZGIxLWQ5NTgtNDkyYy04NmNhLTI3NDIyMGQ2NmI3NiJ9";
const indexUrl = "cdn.xensear.vn/custom-frontend/threejs_production/benhvienbachmai/HLOCTracking.html";
const experienceUrlIOS =
`https://appclip.apple.com/id?p=com.viettel.mhmp.ARWorld.Clip` +
`&worldID=${worldID}` +
`&blockID=${blockID}` +
`&command=${command}` +
`&indexUrl=${indexUrl}`;
const experienceUrlAndroid =
`https://${indexUrl}` +
`?worldID=${worldID}` +
`&blockID=${blockID}` +
`&command=${command}` +
`&indexUrl=${indexUrl}`;
const openARExperience = async () => {
const url =
Platform.OS === 'android'
? experienceUrlAndroid
: experienceUrlIOS;
const supported = await Linking.canOpenURL(url);
if (!supported) {
Alert.alert('Error', 'Could not open AR Experience');
return;
}
await Linking.openURL(url);
};
return (
<View style={styles.container}>
<Button title="Open AR Experience" onPress={openARExperience} />
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
});