# Basic integration steps
# Webview
Since the built-in WebView of React has been removed, there are different webview implementations options available. The official third-party webview react-native-webview is perfectly suitable for the purpose of integrating the StoryHunt web app.
In our reference implementation, we have created a class called the MainWebView, which encapsulate the web view details. This section list the overall requirements for integrating the StoryHunt Web App through react-native-webview in Expo.
The following reference implementation shows a minimum integration setup. In order to gain permissions to integrate the StoryHunt App and configure different customer specific settings in the web app, the native app must inject an STORY_HUNT_APP_ID as shown in the example below. The customer specific app integration id can be found under API Access ➜ APP Integration under worlds in StoryHunt Studio (opens new window). You can also find STORY_HUNT_URL (start url) under worlds in Studio.
// main-web-view.tsx
import { Component } from 'react';
import { WebView } from 'react-native-webview';
// ** Insert real project start url and app id here **
const STORY_HUNT_URL = "https://storyhunt.app/test_project";
const STORY_HUNT_APP_ID = "sh-app-xxxxxxxxxx";
export class MainWebView extends Component {
/**
* Render the StoryHunt web app inside a react webview
*/
public render() {
// Add STORY_HUNT_APP_ID - replace with customer APP_ID
const INJECT_JS = `navigator.STORY_HUNT_APP_ID = ${STORY_HUNT_APP_ID}`;
return (
<WebView
source={{ uri: STORY_HUNT_URL }}
injectedJavaScriptBeforeContentLoaded={INJECT_JS}
geolocationEnabled={true}
/>
);
}
}
This simple webview integration should get the app up and running, however the GPS and Gyroscope might not work properly before setting up the correct permissions, as described in the next section.
# Permissions
# GPS Permissions
The StoryHunt web app uses GPS locations to provide the users with location based content. For this reason the containing native app must setup GPS permission.
When using a module like expo-location, both the ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION are implied and added to the app's permissions automatically. See Expo Permissions Docs (opens new window) for more information.
// app.json
"expo": {
"android": {
"permissions" : [
"ACCESS_FINE_LOCATION",
"ACCESS_COARSE_LOCATION",
"FOREGROUND_SERVICE"
]
// ...
}
// ...
}
WARNING
When deploying your app to the stores with GPS access permissions enabled, you need to explain the permissions properly, otherwise the app might be rejected from the stores.
# Gyro Permissions
The StoryHunt web app utilise the gyroscope, in order for users to see their current heading/direction on the map. As the Webview (react-native-webview) automatically handles these permissions, no further actions or permissions should be needed in order to make this work.
# Browser Navigation
Though running this simple webview setup should work fine, there is an issue with the navigation history and the back buttons found on the majority of Android phones that needs to be addressed.
When the user navigates back and forth in the app (using physical or virtual back/next buttons), the default is to navigate in the native app. However, as the user navigates around in the web app (webview), the back/next buttons should navigate in the webview navigation stack to give the user a more seamless integration experience.
One way to solve this issue could seem to be using the onNavigationStateChange and then save the navigation stack in this way:
// main-web-view.tsx
<WebView
// ...
onNavigationStateChange={ (navState) => { this.handleNavigationState(navState) } }
/>
Unfortunately the canGoBack member of the navState does not reflect the real browser navigation stack of the StoryHunt web app (due to Angulars implementation of navigation). For this reason it is not possible to use this method of detecting when to navigate in the web app navigation stack and when to 'close' the web app and switch to navigation in the native app navigation stack.
Though this might not be the best available solution, we found another way for the reference implementation to handle the navigation stack, however this requires us to store a reference to the web view when it is initialized, as shown below:
export class MainWebView extends Component {
// main-web-view.tsx
private webView: WebView | null = null;
// ...
<WebView
// ...
ref={ (webView) => { this.webView = webView; } }
/>
Using this reference it is possible to call the goBack() function in the webview, that will navigate back in the webview history.
// ...
private onBackButtonPress = () => {
// Let native app handle the button press if the web view navigation stack
// is empty (this will 'close' the web app and let native app take over)
if(!this.webView || !this.webView.canGoBack) return false;
// Navigate back in web view navigation history
this.webView.goBack();
return true;
}
/**
* Init component one time when it is mounted
*/
public async componentDidMount() {
if(Platform.OS != 'android') return;
// Add Android button event listener
BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPress);
}
/**
* Destroy component - remove listeners
*/
public componentWillUnmount() {
if(Platform.OS != 'android') return;
// Clear Android button event listener
BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPress);
}
← Introduction Messages →