I am trying to create a React Native app where a user can be logged in to two or more Cashapp or Instagram accounts simultaneously (within different webviews) and easily toggle between them within the React Native app. This requires each webview to have its own session/cookies and not share them with the other open webviews.
The default behavior of react-native-webview is for webviews to share their cookies with the other webviews.
I have tried the following, but when I log into Cashapp on one webview, then I refresh the other webview, the other webview is also logged in. (For now I am only concerned with getting this working on iOS devices. I am testing this using Expo and an iPhone 11 Pro)
import { StatusBar } from 'expo-status-bar';
import { Button, StyleSheet, Text, View } from 'react-native';
import { useEffect, useState } from 'react';
import { WebView } from 'react-native-webview';
const cashapp1 = <WebView
userAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"
source={{uri: 'https://cash.app/account/mycash'}}
pullToRefreshEnabled={true}
allowsBackForwardNavigationGestures={true}
cacheEnabled={false}
useSharedProcessPool={false}
thirdPartyCookiesEnabled={false}
sharedCookiesEnabled={false}
/>
const cashapp2 = <WebView
userAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"
source={{uri: 'https://cash.app/account/mycash'}}
pullToRefreshEnabled={true}
allowsBackForwardNavigationGestures={true}
cacheEnabled={false}
useSharedProcessPool={false}
thirdPartyCookiesEnabled={false}
sharedCookiesEnabled={false}
/>
export default function App() {
const [screen, setScreen] = useState(1);
const toggler = () => {
screen === 1 ? setScreen(2) : setScreen(1);
return;
}
return (
<View style={styles.container}>
<Button title="hey" onPress={toggler}>Hey</Button>
{screen === 1 ? <Text>Cashapp 1</Text> : <Text>Cashapp 2</Text>}
<View style={{ width: '100%', height: '100%', display: screen === 1 ? "" : "none" }}>
{cashapp1}
</View>
<View style={{ width: '100%', height: '100%', display: screen === 1 ? "none" : "" }}>
{cashapp2}
</View>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
marginTop: 60,
marginBottom: 60,
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
The closest I've gotten to getting the desired behavior is removing these properties
cacheEnabled={false}
useSharedProcessPool={false}
thirdPartyCookiesEnabled={false}
sharedCookiesEnabled={false}
and setting incognito to true. When using incognito, each webview uses its own session/cookies. But if I kill the app and re-open it, I am logged out of everything.
Does anyone have suggestions on how to make this work? Thanks
Related
I've made a sample react native app with this command:
react-native init sampleRN
Code:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow strict-local
*/
import React from 'react';
import type {Node} from 'react';
import {
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
useColorScheme,
View,
} from 'react-native';
import {
Colors,
DebugInstructions,
Header,
LearnMoreLinks,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
const Section = ({children, title}): Node => {
const isDarkMode = useColorScheme() === 'dark';
return (
<View style={styles.sectionContainer}>
<Text
style={[
styles.sectionTitle,
{
color: isDarkMode ? Colors.white : Colors.black,
},
]}>
{title}
</Text>
<Text
style={[
styles.sectionDescription,
{
color: isDarkMode ? Colors.light : Colors.dark,
},
]}>
{children}
</Text>
</View>
);
};
const App: () => Node = () => {
const isDarkMode = useColorScheme() === 'dark';
const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
};
return (
<SafeAreaView style={backgroundStyle}>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={backgroundStyle}>
<Header />
<View
style={{
backgroundColor: isDarkMode ? Colors.black : Colors.white,
}}>
<Section title="Step One">
Edit <Text style={styles.highlight}>App.js</Text> to change this
screen and then come back to see your edits.
</Section>
<Section title="See Your Changes">
<ReloadInstructions />
</Section>
<Section title="Debug">
<DebugInstructions />
</Section>
<Section title="Learn More">
Read the docs to discover what to do next:
</Section>
<LearnMoreLinks />
</View>
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
},
highlight: {
fontWeight: '700',
},
});
export default App;
I added no extra code. I ran it on iOS simulator. After the app is launched and opened, a screen is shown with app's name and the a blank screen is shown. after about 20 second I can see app first page.
screenshots in order from left to right:
I searched and tried differed ways to solve this problem. but it did not work?
What should I do to solve this problem?
the problem was solved after installing react-native-flipper
I am trying to open the Measure iPhone App inside my react native app. I have tried to use linking but as mentioned in this stackoverflow question, Measure does not support URL scheme or Deep Linking. Is there any other way to open the Measure App inside or be redirected to Measure App from my App in react native?
import React, { Component } from 'react';
import { Button, Linking, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Button
title="Open Measure App"
onPress={this._handleOpenWithLinking}
style={styles.button}
/>
</View>
);
}
_handleOpenWithLinking = () => {
// Should open the Measure App
// This does not work as mentioned - Linking.openURL("measure://")
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
button: {
marginVertical: 10,
},
});
I am using the following code. Apple is not pleased that all external links are opening within app. How should I modify my code below so that external links open in outisde app safari instead of within app safari.
My App.js is as following:
import { StatusBar } from 'expo-status-bar';
import React, { useState, useRef } from 'react'
import {ActivityIndicator, Platform, TouchableOpacity, Text, SafeAreaView, StyleSheet, View} from "react-native";
import { WebView } from 'react-native-webview';
import { NavigationContainer } from '#react-navigation/native';
import { Ionicons } from '#expo/vector-icons'
import Constants from 'expo-constants'
const App = () => {
const [canGoBack, setCanGoBack] = useState(false)
const [canGoForward, setCanGoForward] = useState(false)
const [currentUrl, setCurrentUrl] = useState('')
const webviewRef = useRef(null)
backButtonHandler = () => {
if (webviewRef.current) webviewRef.current.goBack()
}
frontButtonHandler = () => {
if (webviewRef.current) webviewRef.current.goForward()
}
return (
<>
<StatusBar barStyle='dark-content' />
<View style={styles.flexContainer}>
<WebView
userAgent="Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Mobile Safari/537.36"
source={{ uri: 'https://www.google.co.in/search?q=restaurants+nearby&ct=ifl&cad=2:hungry&ei=IWHsX_aDGJK0swXew5HgBw&ved=0ahUKEwi2mN_oyfXtAhUS2qwKHd5hBHwQnRsIDg&rct=j' }}
mixedContentMode = "compatibility"
ref={webviewRef}
onNavigationStateChange={navState => {
setCanGoBack(navState.canGoBack)
setCanGoForward(navState.canGoForward)
setCurrentUrl(navState.url)
}}
/>
<View style={styles.tabBarContainer}>
<TouchableOpacity onPress={backButtonHandler}>
<Ionicons name="ios-arrow-back" size={32} color="white" />
</TouchableOpacity>
<TouchableOpacity onPress={frontButtonHandler}>
<Ionicons name="ios-arrow-forward" size={32} color="white" />
</TouchableOpacity>
</View>
</View>
</>
)
}
const styles = StyleSheet.create({
flexContainer: {
flex: 1,
paddingTop:Constants.statusBarHeight
},
tabBarContainer: {
padding: 10,
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: '#000000'
},
button: {
color: 'white',
fontSize: 20
}
})
export default App
Edit: Can you please provide a modified version of App.js above as I have already read through the various help documentation and codes there.
Expo
you can use expo-web-browser because Apple wants is to have it clearly visible that it is an external URL.
Installation
expo install expo-web-browser
expo-web-browser provides access to the system's web browser and supports handling redirects. On iOS, it uses SFSafariViewController or SFAuthenticationSession, depending on the method you call, and on Android it uses ChromeCustomTabs. As of iOS 11, SFSafariViewController no longer shares cookies with Safari, so if you are using WebBrowser for authentication you will want to use WebBrowser.openAuthSessionAsync, and if you just want to open a webpage (such as your app privacy policy), then use WebBrowser.openBrowserAsync
Usage
https://snack.expo.io/#nomi9995/basic-webbrowser-usage
import React, { useState } from 'react';
import { Button, Text, View, StyleSheet } from 'react-native';
import * as WebBrowser from 'expo-web-browser';
import Constants from 'expo-constants';
export default function App() {
const [result, setResult] = useState(null);
const _handlePressButtonAsync = async () => {
let result = await WebBrowser.openBrowserAsync('https://expo.io');
setResult(result);
};
return (
<View style={styles.container}>
<Button title="Open WebBrowser" onPress={_handlePressButtonAsync} />
<Text>{result && JSON.stringify(result)}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
React Native
you can use the following library react-native-inappbrowser
follow the installation from the github page
import { Linking } from 'react-native'
import InAppBrowser from 'react-native-inappbrowser-reborn'
...
async openLink() {
try {
const url = 'https://www.google.com'
if (await InAppBrowser.isAvailable()) {
const result = await InAppBrowser.open(url, {
// iOS Properties
dismissButtonStyle: 'cancel',
preferredBarTintColor: '#453AA4',
preferredControlTintColor: 'white',
readerMode: false,
animated: true,
modalPresentationStyle: 'overFullScreen',
modalTransitionStyle: 'partialCurl',
modalEnabled: true,
// Android Properties
showTitle: true,
toolbarColor: '#6200EE',
secondaryToolbarColor: 'black',
enableUrlBarHiding: true,
enableDefaultShare: true,
forceCloseOnRedirection: false,
// Specify full animation resource identifier(package:anim/name)
// or only resource name(in case of animation bundled with app).
animations: {
startEnter: 'slide_in_right',
startExit: 'slide_out_left',
endEnter: 'slide_in_left',
endExit: 'slide_out_right'
},
headers: {
'my-custom-header': 'my custom header value'
},
waitForRedirectDelay: 0
})
Alert.alert(JSON.stringify(result))
}
else Linking.openURL(url)
} catch (error) {
Alert.alert(error.message)
}
}
...
you can check the example app here
for expo it becomes little bit complicated please check the related tutorial by Medium
if you want reading mode in ios please refer this link
reader-mode-webview-component-for-react-native
You've embedded a webview. What Apple wants, is to have it clearly visible that it is an external URL.
There is what's called Safari UI View Controller on IOS, and Chrome Custom tabs on Android.
There are a couple of plugins out there, but I liked using this one: https://www.npmjs.com/package/react-native-inappbrowser-reborn
I'm Using react 15.2.1 and react-native 0.30.0
I checked out How do I display an animated gif in React Native? and followed the instructions.
<Image source={{ uri: 'http://i.giphy.com/l41YiEvBtjGKNlzby.gif'
style={{ height: 250, width: 250 }} />
Also tried
<Image source={require('./path/to.gif')}
style={{ height: 250, width: 250 }} />
But the gif isn't showing. If I switch out the link for an image it works fine.
I checked this working example https://rnplay.org/apps/739mzQ but can't test it with 0.30.0 so I'm wondering if something has changed since then.
Maybe add gif to your project and use require function.
please try this example
import React, {Component} from 'react';
import { StyleSheet, View} from 'react-native';
const SplashGif = require('./images/Wallpaper.gif');
export default class App extends Component {
render() {
const { container, imageStyles } = styles;
return (
<View style={container}>
<Image source={SplashGif} style={imageStyles} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
imageStyles: {
resizeMode: 'stretch',
width: '100%',
height: '100%'
}
});
Use this code:
import React, {Component} from 'react';
import { StyleSheet, Image,Text, View} from 'react-native';
const Splash = require('./images/testGif.gif')
class SplashSrceen extends Component {
render() {
const { container, splashgif } = styles;
return (
<View style={container}>
<Image source={Splash} style={splashgif} />
<Text>or</Text>
<Image source={{uri:'https://media.tenor.com/images/0a1652de311806ce55820a7115993853/tenor.gif'}}style={splashgif} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
splashgif: {
resizeMode: 'stretch',
width: '100%',
height: '50%'
}
});
export default SplashSrceen ;
Android
To correct for this, we included the following libraries:
dependencies {
implementation 'com.facebook.fresco:fresco:1.10.0'
implementation 'com.facebook.fresco:animated-gif:1.10.0'
}
I am a newbie in react native.
I have one similar problem in different projects. When I try to compile my project, I see this problem. Why this error is appear?
P.S. I am learning react-native by tutorials like a appcoda.com
Picture of my error
Featured.js
'use strict';
var React = require('react-native');
var{
StyleSheet,
View,
Text,
Component
} = React;
var styles = StyleSheet.create({
description:{
fontSize: 20,
backgroundColor: 'white'
},
container:{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
});
class Featured extends Component{
render() {
return(
<View style = {styles.container}>
<Text style = {styles.description}>
Featured tab
</Text>
</View>
);
}
}
module.exports = Featured;
Change your import statement as below
import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
} from 'react-native';