I'm trying to open up an external app from my react native app, but it only seems to be working on my iPhone and not my Android. The console.log shows "isInstalled false" for Android but "isInstalled True" for iPhone.
I want the react native app to check if the user has the external app installed on their phones already. If so, open the external app, and if not, the app will redirect the user to Google Play (Android) / App Store (iOS).
import { Linking, Platform } from 'react-native';
import { Header, Card } from 'react-native-elements';
import { SafeAreaView } from 'react-native-safe-area-context';
import { AppInstalledChecker } from 'react-native-check-app-install';
export default function App() {
return (
<SafeAreaView style={styles.container}>
<Card containerStyle={styles.cardStyle}>
<Card.Image
style={styles.image}
source={{
uri:"https://play-lh.googleusercontent.com/T0OPODRs2EciPVEwUHv4Xucn5_MMQ8pHzEII1THqiIa8ef3XaZ1rf-TWW1g10SvJ0w=s180-rw"
}}
onPress={()=>{
const iOSAppStoreUrl = 'https://apps.apple.com/sg/app/hdb-health/id1266210350'
const iOSGoogleStoreUrl = 'https://play.google.com/store/apps/details?id=com.hdb.healthAnd'
if( Platform.OS === 'ios'){
AppInstalledChecker
.checkURLScheme('hdbhealth')
.then((isInstalled) => {
Linking.openURL('hdbhealth://app')
})
.catch(Linking.openURL(iOSAppStoreUrl))
} else { // Android
AppInstalledChecker
.checkURLScheme('com.hdb.healthAnd')
.then((isInstalled) => {
Linking.openURL('hdbhealth://app')
})
.catch(Linking.openURL(iOSGoogleStoreUrl))
}
}}
/>
</Card>
</SafeAreaView>
);
}
You should use isAppInstalledAndroid instead of checkURLScheme for android.
https://github.com/redpandatronicsuk/react-native-check-app-install
Related
I am creating a react native app and i want to send automatic email onpress
i did this in reactjs it is working fine but when applied this in react native, it is not working please tell me how to use in react native
import { View, Text, Button } from 'react-native'
import React from 'react'
import emailjs from '#emailjs/nodejs';
export default function App() {
function emailer() {
const templateParams = {
name: 'James',
notes: 'Check this out!',
};
emailjs
.send('service_hw72nhc','template_h5zuoxb', templateParams, {
publicKey: 'AYhHEr8nhLs3irJSN',
privateKey: '_6ql6C0rLYo1aWnsCaxKD', // optional, highly recommended for security reasons
})
.then(
(response) => {
console.log('SUCCESS!', response.status, response.text);
},
(err) => {
console.log('FAILED...', err);
},
);
console.log("buton pressed")
}
return (
<View style={{justifyContent:'center', alignItems:'center'}}>
<Button title='Send Email' onPress={emailer} />
</View>
)
}
I have tried this now please help
I have created a react-native app in VS Code. The app is running fine in the browser with expo. Generated a keystore file and created an .apk with gradlew assembleRelease.
The .apk can be installed on my Android tablet. But after starting the app, it is not running and the splash screen is shown (see image below).
The SDK version on the tablet (30) is higher than the minSdkVersion (21) of the app.
Also added <uses-feature android:name="android.hardware.telephony" android:required="false" /> to the AndroidManifest.xml file.
Code is as follows.
index.js:
import { registerRootComponent } from 'expo';
import App4 from './App4';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in Expo Go or in a native build,
// the environment is set up appropriately
registerRootComponent(App4);
App4.js:
import React from 'react'
import List from './List.js'
const App = () => {
return (
<List />
)
}
export default App
List.js:
import React, { Component } from 'react'
import { Text, View, TouchableOpacity, StyleSheet, Image } from 'react-native'
class List extends Component {
state = {
products: []
}
componentDidMount() {
this.GetAllProducts();
}
GetAllProducts() {
//fetch("http://192.168.2.14:3000/getallproducts")
fetch("https://categoriesexpress444.herokuapp.com/getallproducts")
.then(res => res.json())
.then(jsonresult => {
this.setState({
products: jsonresult
});
console.log(this.state.products);
});
}
getsrcPath(string) { // this function distinguishes between images in UserImages folder and images on Cloudinary
var firstChar = string.charAt(0);
if (firstChar == '~') { // image is in UserImages folder and item.picture path starts wih ~/UserImages/
return string.substring(1, string.length);
}
else { // image is at Cloudinary and item.picture starts with http://
return string;
}
}
render() {
return (
<View>
{
this.state.products.map((item, index) => (
<TouchableOpacity
key = {item.id}
style = {styles.container}>
<Text style = {styles.text}>{item.productname}</Text>
<Text>{item.description}</Text>
<Text>€ {item.price}</Text>
<img src={this.getsrcPath(item.picture)} />
<Text style = {styles.text}>
{item.name}
</Text>
</TouchableOpacity>
))
}
</View>
)
}
}
export default List
const styles = StyleSheet.create ({
container: {
padding: 10,
marginTop: 3,
backgroundColor: '#ffffff',
alignItems: 'center',
cursor: 'none'
},
text: {
color: '#4f603c'
}
})
If you are using expo to create react native app then
you have to build an app over the expo using this command
expo build:adroid or expo build:ios
once the build will successfully create you will get one URL then you can use the URL to install the app on your device.
If you are using react-native-cli to create react native app then
you have to build an app over the expo using this command
./gradlew assembleRelease or ./gradlew assembleDebug in MacOs
I have troubles having audio permissions to work on android build. It works fine in expo go, but not in android build.
In the given code, the permission for the camera is asked properly, but when accepted the permission for audio shows only for a fraction of a second and return a not granted status.
Once again, it works fine in expo go.
Is there anything i’m doing wrong ? do you have an idea on how to solve this ?
Thanks you very much community !
SDK Version: 41
Platforms(Android/iOS/web/all): Android (samsung A20e)
import {Camera} from 'expo-camera'
import {Audio} from 'expo-av';
export default () => {
return (
<View>
<Button
onPress={() => {
Camera.requestPermissionsAsync().then((status) => {
// audio permission request is only shown for half a second in build mode and is automatically denied permission
Audio.requestPermissionsAsync().then((status) => {
console.log('ok');
});
});
}}>
Test
</Button>
</View>
);
};
Use it like this
Working Example Here
import { Camera } from 'expo-camera';
import { Audio } from 'expo-av';
const GetPermissions = async () => {
try {
console.log('Requesting permissions..');
const CameraPerm = await Camera.requestPermissionsAsync();
if (CameraPerm.status === 'granted') {
console.log('Camera Permission Granted');
}
const AudioPerm = await Audio.requestPermissionsAsync();
if (AudioPerm.status === 'granted') {
console.log('Audio Permission Granted');
}
} catch (err) {
console.error('Failed to get permissions', err);
}
};
return (
<View style={styles.container}>
<Button title="Get Permissions" onPress={GetPermissions} />
</View>
);
Make sure all the imports are correct
be sure to have either both or none in your app.json
that was my problem !
This basic postMessage example works for IOS but does not work for Android.
The React Native app on Android fails to receives the post message send from the js code (const simple) injected into the WebView.
import React, {Component} from 'react';
import {
WebView
} from 'react-native';
export default class App extends Component<{}> {
render() {
const simple = function() { window.postMessage('my message from Webview to RN');}
const postMessageCode = '(' + String(simple) + ')();';
return (
<WebView
source={{uri: 'https://github.com/facebook/react-native'}}
injectedJavaScript={postMessageCode}
onMessage={this.onWebViewMessage}
/>
);
}
onWebViewMessage(event) {
alert(event);
}
}
This has been tested with:
react-native-cli: 2.0.1
react-native: 0.50.4
On:
- Android emulator version 26.0.0-3833124, Android 7.1.1, API 25
- Android native device ONE E1005 (One plusX), Android version 6.0.1, API 23
Who has been able to get postMessage working (WebView --> RN) on an Android device / emulator or thinks they know how to?
I experienced the same issue. There seems to be a delay in the Android browser on React Native attaching listeners to postMessage. See https://github.com/facebook/react-native/issues/11594
I use this little helper on my web pages to get around it:
var message = 'some message string';
window.parent.postMessage(message,"*");
function whenRNPostMessageReady(cb) {
if (postMessage.length === 1) cb();
else setTimeout(function() { whenRNPostMessageReady(cb) }, 100);
}
whenRNPostMessageReady(function() {
//react native accepts strings only
window.parent.postMessage(JSON.stringify(message),"*");
});
Use WebView ref postMessage instead.
import React, {Component} from 'react';
import {
WebView
} from 'react-native';
export default class App extends Component<{}> {
sendMessage = () => {
this.webViewRef.postMessage('my message from Webview to RN');
}
render() {
return (
<WebView
source={{uri: 'theURL'}}
ref={(ref) => { this.webViewRef = ref }}
onMessage={this.onWebViewMessage}
/>
);
}
onWebViewMessage(event) {
alert(event);
}
}
I'm using react-native-fs to download a file(pdf, word, excel, png etc.) and I need to open it in other application. Is it possible to open downloaded file with Linking or better open a dialog with possible apps like when using Sharing? Linking in the code below tries to open the file but it closes immediately without any notification, but my app is still working fine. Is there some special way to build URLs for deep linking for a specific file type? Any ideas for the best solution?
I see that there is old package react-native-file-opener but it's no longer maintained. This solution would be great.
Simplified code for download component:
import React, { Component } from 'react';
import { Text, View, Linking, TouchableOpacity } from 'react-native';
import { Icon } from 'react-native-elements';
import RNFS from 'react-native-fs';
import { showToast } from '../../services/toasts';
class DownloadFile extends Component {
state = {
isDone: false,
};
handleDeepLinkPress = (url) => {
Linking.openURL(url).catch(() => {
showToast('defaultError');
});
};
handleDownloadFile = () => {
RNFS.downloadFile({
fromUrl: 'https://www.toyota.com/content/ebrochure/2018/avalon_ebrochure.pdf',
toFile: `${RNFS.DocumentDirectoryPath}/car.pdf`,
}).promise.then(() => {
this.setState({ isDone: true });
});
};
render() {
const preview = this.state.isDone
? (<View>
<Icon
raised
name="file-image-o"
type="font-awesome"
color="#f50"
onPress={() => this.handleDeepLinkPress(`file://${RNFS.DocumentDirectoryPath}/car.pdf`)}
/>
<Text>{`file://${RNFS.DocumentDirectoryPath}/car.pdf`}</Text>
</View>)
: null;
return (
<View>
<TouchableOpacity onPress={this.handleDownloadFile}>
<Text>Download File</Text>
</TouchableOpacity>
{preview}
</View>
);
}
}
export default DownloadFile;
After some research, I decided to use react-native-fetch-blob. From version 0.9.0 it's possible to open downloaded file with Intent and use Download Manager. It also has API for iOS for opening documents.
Code now:
...
const dirs = RNFetchBlob.fs.dirs;
const android = RNFetchBlob.android;
...
handleDownload = () => {
RNFetchBlob.config({
addAndroidDownloads: {
title: 'CatHat1.jpg',
useDownloadManager: true,
mediaScannable: true,
notification: true,
description: 'File downloaded by download manager.',
path: `${dirs.DownloadDir}/CatHat1.jpg`,
},
})
.fetch('GET', 'http://www.swapmeetdave.com/Humor/Cats/CatHat1.jpg')
.then((res) => {
this.setState({ path: res.path() });
})
.catch((err) => console.log(err));
};
...
render() {
...
<Icon
raised
name="file-pdf-o"
type="font-awesome"
color="#f50"
onPress={() => android.actionViewIntent(this.state.path, 'image/jpg')}
...
}