React native camera won't work on second invokation in Android. On the second invokation the app crashes.
I am using
react-native: 0.56.0
react-native-camera: 1.6.4
It's the same when I use latest version of the react-native-camera.
I can't update react-native to the latest because I have another package that is not compatible with the latest one and It's work fine on the emulator, only problem with real devices
The --scan result is
My camera screen
class CameraScreen extends Component {
constructor(props) {
super(props);
this.state = {
boltIconIsPressed: false,
};
}
renderError() {
Alert.alert(
'Error',
'Something went wrong, Try again!',
[
{ text: 'Ok', style: 'cancel' },
],
);
this.props.navigation.goBack();
}
render() {
if (this.props.isFocused) {
return (
<View style={styles.container}>
<RNCamera
ref={ref => {
this.camera = ref;
}}
style={styles.preview}
type={RNCamera.Constants.Type.back}
flashMode={this.state.boltIconIsPressed ? RNCamera.Constants.FlashMode.off : RNCamera.Constants.FlashMode.on}
onMountError={this.renderError.bind(this)}
permissionDialogTitle={'Permission to use camera'}
permissionDialogMessage={'We need your permission to use your camera phone'}
/>
<View
style={{ flex: 0,
flexDirection: 'row',
justifyContent: 'center',
backgroundColor: 'transparent' }}
>
<Button
outline
rounded
style={styles.capture}
onPress={() => this.props.navigation.navigate('gallery')}
>
<Icon
type='Entypo'
name='image'
style={{ color: '#862d59', }}
/>
</Button>
<Button
outline
rounded
onPress={this.takePicture.bind(this)}
style={styles.capture}
>
<Icon
type='SimpleLineIcons'
name='camera'
style={{ color: '#862d59', }}
/>
</Button>
<Button
outline
rounded
style={styles.capture}
onPress={() => this.setState({ boltIconIsPressed:
!this.state.boltIconIsPressed })}
>
<Icon
type='MaterialCommunityIcons'
name={this.state.boltIconIsPressed ? "flash-off" : "flash"}
style={{ color: '#862d59', }}
/>
</Button>
</View>
</View>
);
}
return (
<View />
);
}
takePicture = async function () {
let data = null;
if (this.camera) {
const options = {
width: 1800,
base64: true,
};
console.log(data);
data = await this.camera.takePictureAsync(options);
this.props.navigation.navigate('uploadscreen', {
image: data,
});
}
};
}
export default withNavigationFocus(CameraScreen);
Thanks in advance
I got this error because I doesnot have the storage to save the taken image. To make it work, add this in AndroidManifest.xml file
android:largeHeap="true"
Related
I am building a react-native app with expo, I have only 2 components, WelcomeScreen and PhoneLoginScreen. I am trying to implement firebase phone authentication which works fine on the Web but on iOS Simulator I get an error Verifier._reset is not a function. (In 'verifier._reset()', 'verifiier._reset' is undefined and on Android, it just crashes when I click the continue button that navigates to the PhoneLoginScreen component. Codes below:
App.js
import React from "react"
import { NavigationContainer } from "#react-navigation/native"
import { createNativeStackNavigator } from "#react-navigation/native-stack"
import WelcomeScreen from "./components/WelcomeScreen"
import PhoneLoginScreen from "./components/auth/PhoneLoginScreen"
const Stack = createNativeStackNavigator()
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Welcome">
<Stack.Screen
name="Welcome"
component={WelcomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="PhoneLogin"
component={PhoneLoginScreen}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
WelcomeScreen.js
import React from "react"
import { Text, View, Button } from "react-native"
export default function WelcomeScreen({ navigation }) {
return (
<View
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Welcome</Text>
<Button
title="Continue"
onPress={() => navigation.navigate("PhoneLogin")}
/>
</View>
)
}
PhoneLoginScreen.js
import React, { useRef, useState } from "react"
import { firebaseApp, auth } from "../../firebase"
import {
Text,
View,
TextInput,
Button,
StyleSheet,
TouchableOpacity,
} from "react-native"
import {
FirebaseRecaptchaVerifierModal,
FirebaseRecaptchaBanner,
} from "expo-firebase-recaptcha"
import { PhoneAuthProvider, signInWithCredential } from "firebase/auth"
export default function PhoneLoginScreen() {
const recaptchaVerifier = useRef(null)
const [message, showMessage] = useState()
const [phoneNumber, setPhoneNumber] = useState()
const [verificationId, setVerificationId] = useState()
const [verificationCode, setVerificationCode] = useState()
const firebaseConfig = firebaseApp ? firebaseApp.options : undefined
const attemptInvisibleVerification = true
return (
<View style={styles.center}>
<FirebaseRecaptchaVerifierModal
ref={recaptchaVerifier}
firebaseConfig={firebaseConfig}
attemptInvisibleVerification={attemptInvisibleVerification}
/>
<Text style={{ marginTop: 20 }}>Enter phone number</Text>
<TextInput
style={{ marginVertical: 10, fontSize: 17 }}
placeholder="+1 999 999 9999"
autoFocus
autoCompleteType="tel"
keyboardType="phone-pad"
textContentType="telephoneNumber"
onChangeText={phoneNumber => setPhoneNumber(phoneNumber)}
/>
<Button
title="Send Verification Code"
disabled={!phoneNumber}
onPress={async () => {
try {
const phoneProvider = new PhoneAuthProvider(auth)
const verificationId =
await phoneProvider.verifyPhoneNumber(
phoneNumber,
recaptchaVerifier.current
)
setVerificationId(verificationId)
showMessage({
text: "Verification code has been sent to your phone.",
})
} catch (err) {
showMessage({
text: `Error 111: ${err.message}`,
color: "red",
})
}
}}
/>
<Text style={{ marginTop: 20 }}>Enter Verification code</Text>
<TextInput
style={{ marginVertical: 10, fontSize: 17 }}
editable={!!verificationId}
placeholder="123456"
onChangeText={setVerificationCode}
/>
<Button
title="Confirm Verification Code"
disabled={!verificationId}
onPress={async () => {
try {
const credential = PhoneAuthProvider.credential(
verificationId,
verificationCode
)
await signInWithCredential(auth, credential)
showMessage({
text: "Phone authentication successful 👍",
})
} catch (err) {
showMessage({
text: `Error: ${err.message}`,
color: "red",
})
}
}}
/>
{message ? (
<TouchableOpacity
style={[
StyleSheet.absoluteFill,
{
backgroundColor: 0xffffffee,
justifyContent: "center",
},
]}
onPress={() => showMessage(undefined)}>
<Text
style={{
color: message.color || "blue",
fontSize: 17,
textAlign: "center",
margin: 20,
}}>
{message.text}
</Text>
</TouchableOpacity>
) : undefined}
{attemptInvisibleVerification && <FirebaseRecaptchaBanner />}
</View>
)
}
const styles = StyleSheet.create({
center: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
})
firebase.js
import firebase from "firebase/compat/app"
import "firebase/compat/auth"
import "firebase/compat/firestore"
// Initialize Firebase
const firebaseConfig = {
// Config info...
}
let firebaseApp
if (firebase.apps.length === 0) {
firebaseApp = firebase.initializeApp(firebaseConfig)
} else {
firebaseApp = firebase.app()
}
const auth = firebase.auth()
export { auth, firebaseApp }
package.json dependencies
"dependencies": {
"#react-navigation/native": "^6.0.6",
"#react-navigation/native-stack": "^6.2.5",
"expo": "~43.0.2",
"expo-firebase-recaptcha": "~2.0.2",
"expo-status-bar": "~1.1.0",
"firebase": "^9.5.0",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-native": "0.64.3",
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "~3.8.0",
"react-native-web": "0.17.1",
"react-native-webview": "11.13.0"
}
I have googled forever and nothing works. Please advice
This is a bug. The maintainers of "expo-firebase-recaptcha" have yet to publish a fix, so until that day comes, this is how you fix it yourself:
Go to node_modules/expo-firebase-recaptcha, open the build folder and find FirebaseRecaptchaVerifierModal.js.
Inside of FirebaseRecaptchaVerifierModal, add the following function to the component definition:
_reset = () => {}
I've included a snippet of the file after adding the empty function definition:
FirebaseRecaptchaVerifierModal.js
[...]
else {
this.setState({
visible: true,
visibleLoaded: false,
resolve,
reject,
});
}
});
}
/**
* Add the following line anywhere inside of the FirebaseRecaptchaVerifierModal component.
*/
_reset = () => {}
onVisibleLoad = () => {
this.setState({
visibleLoaded: true,
});
};
[...]
Note: You will have to do this after every yarn/npm installl or change in node_modules until the publishers push an update.
Error: verifier._reset is not a function. when trying to Sign in with phone using firebase, react native and Expo
FIX FOR EXPO 45, 46
After Surfing through the internet for answers, i failed and din't find anything to make it work on Expo 45 and Expo 46, finally took it to my hands because We can't ship an app with manual recaptcha as it is very bad UX. So after trying every possible prop in the FirebaseRecaptchaVerifierModal, I FINALLY FOUND THE WORKING FIX
By Combining all the fixes and adding one of my own found, I finally can rest in peace as this is now working.
// Declare the Timeout for Initial Page Load Fix
const [isInit, setisInit] = useState(false)
useEffect(() => {
setTimeout(function () {
setisInit(true)
}, 1000)
return () => {
setisInit(false)
}
}, [])
return(
<View>
...
{isInit && (
<FirebaseRecaptchaVerifierModal
ref={recaptchaVerifier}
firebaseConfig={app.options}
androidHardwareAccelerationDisabled={true}
androidLayerType="software"
attemptInvisibleVerification
/>
)}
...
<FirebaseRecaptchaBanner />
</View>
This was the magical line
androidLayerType="software"
I Hope Expo Updates there Documentation and avoid this painful experience for all of us Developers, I mean I literally never have seen an app with manual Recaptcha until im spamming
FirebaseRecaptchaVerifierModal attemptInvisibleVerification Crashes on Android Emulator look at this. This is help me so well.
I add :
<FirebaseRecaptchaVerifierModal ref={recaptchaVerifierRef}
firebaseConfig={firebaseConfig} androidHardwareAccelerationDisabled
attemptInvisibleVerification />
This line on my FirebaseRecaptchaVerifierModal this gonna help to my to problem.
I am new to react-native as well as to android, upon clicking of button, I get an undefined response when I try to access values referenced in TextInput
Upon looking on previous solution, I tried binding my log in button and still the problem was not solved
function login(event)
{
var email = this.refs.email;
var password = this.refs.password;
console.log(email + ": " + password); // gives undefined: undefined
}
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Image source={require('./logo.png')} />
<Text style={styles.welcome}>Login</Text>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1, width: 300}}
placeholder={'E-mail'}
ref = {this.email}
onChangeText={(text) => this.setState({text})}
/>
<Text>{"\n"}</Text>
<TextInput secureTextEntry={true}
style={{height: 40, borderColor: 'gray', borderWidth: 1, width: 300}}
placeholder={'Password'}
ref = {this.password}
onChangeText={(text) => this.setState({text})}
/>
<Text>{"\n"}</Text>
<Button
title="Log In"
onPress={login.bind(this)}
/>
</View>
);
}
}
Usage of this.refs is deprecated.
Work with refs as function. For example:
export default class App extends Component {
let viewRef = null;
render() {
return (
<View ref={ref => (this.viewRef = ref)}>
<Button
title="Log In"
onPress={() => console.log(this.viewRef)}
/>
</View>
)
}
}
I'm using Picker component of Native-Base for my react-native application. On IOS everything is ok, whereas, on Android side I can not trigger function I added on onValueChange.
Is there anyone faced this issue before?
How did you fix it? I stuck here almost a day.
Here is my code.
<Picker style={{ width: 200, height: 40}}
iosHeader="Branch"
Header="Branch"
mode="dropdown"
textStyle={{color: 'white'}}
placeholder="Branch"
headerBackButtonText="Geri"
selectedValue={this.state.selectedBranch}
onValueChange={(value)=>this.onBranchSelected(value)}
>
{this.state.branches.map((branches, i)=>{
return(
<Picker.Item label={branches.address_line} value={branches.id} key={i}/>
);
}
)}
</Picker>
It does not call the function onBranchSelected on Android.
I tried your code and was working fine for me.
Pasting my code
import React, { Component } from "react";
import { Platform } from "react-native";
import { Container, Header, Title, Content, Button, Icon, Text, Right, Body, Left, Picker, Form } from "native-base";
export default class PickerExample extends Component {
constructor(props) {
super(props);
this.state = {
branches: [
{ address_line: 'address 1', id: 1 },
{ address_line: 'address 2', id: 2 },
{ address_line: 'address 3', id: 3 },
{ address_line: 'address 4', id: 4 },
{ address_line: 'address 5', id: 5 }],
selected1: 1
};
}
onBranchSelected(value) {
this.setState({
selectedBranch: value
});
}
render() {
return (
<Container>
<Header>
<Left>
<Button transparent>
<Icon name="arrow-back" />
</Button>
</Left>
<Body>
<Title>Picker</Title>
</Body>
<Right />
</Header>
<Content>
<Form>
<Picker
style={{ width: 200, height: 40 }}
iosHeader="Branch"
Header="Branch"
mode="dropdown"
textStyle={{ color: 'grey' }}
placeholder='Select branch'
headerBackButtonText='Geri'
selectedValue={this.state.selectedBranch}
onValueChange={(value) => this.onBranchSelected(value)}
>
{this.state.branches.map((branches, i) => {
return (
<Picker.Item label={branches.address_line} value={branches.id} key={i} />
);
}
)}
</Picker>
</Form>
</Content>
</Container>
);
}
}
Dependencies
"native-base": "2.3.5",
"react": "16.0.0",
"react-native": "0.50.0",
This is known issue with Picker. The issue is trying to use .map. I myself couldn't ever get map to work with Picker. The only thing I could find was an npm package called react-native-smart-picker which I was able to use a .map with. There are limitations.
And FYI I also tried other bootstrap frameworks and this is an issue with vanilla react-native.
Heres the link..
https://www.npmjs.com/package/react-native-smart-picker
Heres my github repo...
https://github.com/GavinThomas1192/motoMechanicMeeKanic/blob/master/App/Components/vehicleMakePicker.js
Heres my code where I implemented it.
<ScrollView>
<View style={{ flex: 1, marginTop: 20 }}>
{this.state.makes.length > 1 ?
<ScrollView>
<SmartPicker
expanded={this.state.expanded}
selectedValue={this.state.selectedMake}
label='Select Make'
onValueChange={this.handleChange.bind(this)}>
{
this.state.makes.map((ele) => {
return (<Picker.Item label={ele} value={ele}/>);
})
}
<Picker.Item label='Select Make' value='Toyota'/>
</SmartPicker>
<Button block onPress={() => this.props.vehicleMake(this.state.selectedMake)}>
<Text>Done</Text>
</Button>
</ScrollView> : <Spinner/>
}
</View>
</ScrollView>
Update to show how I handled no expandable button
<Content>
<Text>Vehicle Stats:</Text>
<Text>Year: {this.state.vehicleYear}</Text>
<Text>Make: {this.state.vehicleMake}</Text>
<Text>Model: {this.state.vehicleModel}</Text>
{this.state.vehicleYear === "" ? <VehicleYearPicker vehicleYear={this.yearPicked}/> : undefined}
{this.state.vehicleYear !== "" && this.state.vehicleMake === "" ?
<VehicleMakePicker pickedYear={this.state.vehicleYear} vehicleMake={this.makePicked}/> : undefined}
{this.state.vehicleModel === "" && this.state.vehicleMake !== "" ?
<VehicleModelPicker homeState={this.state} vehicleModel={this.modelPicked}/> : undefined}
</Content>
When i click on the select a photo button, Take a photo and select from gallery options pop up. But when i click at those options nothing happens. I am working on windows right now. I tried the same code in mac, selecting the option simply took me to the home screen. Please help.
import React, { Component } from 'react';
import {AppRegistry,View,Text,Image, StyleSheet,PixelRatio,TouchableOpacity } from 'react-native';
import {
Container,
List,
ListItem,
Content,
Footer,
FooterTab,
Header,
Button,
Icon,
Tabs,
Title,
InputGroup,
Input
} from 'native-base';
import{
Actions,
Scene,
Router
}from 'react-native-router-flux';
import ImagePicker from 'react-native-image-picker';
import Reg from './Reg'
export default class Log extends Component{
state = {
avatarSource: null,
};
selectPhotoTapped() {
const options = {
quality: 1.0,
maxWidth: 500,
maxHeight: 500,
storageOptions: {
skipBackup: true
}
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled photo picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
}
else {
let source = { uri: response.uri };
this.setState({
avatarSource: source
});
}
});
}
render(){
return(
<Container>
<View style={styles.container}>
<TouchableOpacity onPress={this.selectPhotoTapped.bind(this)}>
<View style={[styles.avatar, styles.avatarContainer, {marginBottom: 20}]}>
{ this.state.avatarSource === null ? <Text>Select a Photo</Text> :
<Image style={styles.avatar} source={this.state.avatarSource} />
}
</View>
</TouchableOpacity>
</View>
<Content style={{flex:1, marginTop:80}}>
<List>
<ListItem>
<InputGroup>
<Icon name='ios-at-outline' style={{color:'#5bc0de'}}/>
<Input placeholder="Email" />
</InputGroup>
</ListItem>
<ListItem>
<InputGroup>
<Icon name='ios-lock-outline' style={{color:'#5bc0de'}}/>
<Input placeholder="Password" secureTextEntry />
</InputGroup>
</ListItem>
<View style={{marginTop:10}}>
<Button info style={{alignSelf:'center'}} onPress={Actions.userprofile}>
LOGIN
</Button>
</View>
</List>
</Content>
</Container>
);
}
}
const styles = StyleSheet.create({
container: {
marginTop:50,
justifyContent: 'center',
alignItems: 'center',
},
avatarContainer: {
height:100,
width:100,
borderColor: '#9B9B9B',
borderWidth: 1 / PixelRatio.get(),
justifyContent: 'center',
alignItems: 'center'
},
avatar: {
borderRadius: 75,
width: 150,
height: 150
}
});
Add two permission in AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
I'm pretty sure this is straightforward, but I can't quite see how to bring it together. At the moment my app works perfectly in iOS, but I've used a few controls which are not Android compatible:
<View style={containerStyle}>
<Text style={labelStyle}>Drink:</Text>
<SegmentedControlIOS
tintColor={styleBackground}
style={{ flex: 2 }}
values={['Value1', 'Value2']}
selectedIndex={this.state.drink}
onChange={(event) => {
this.setState({ drink: event.nativeEvent.selectedSegmentIndex });
}}
/>
<View style={{ flex: 1 }} />
</View>
I want to use the React-Native-Segmented-Android library to fix this. I feel like I should be able to do something like:
<View style={containerStyle}>
<Text style={labelStyle}>Drink:</Text>
const Component = Platform.select({
ios: () => require('SegmentedControlIOS'),
android: () => require('react-native-segmented-android'),
})(
tintColor={styleBackground}
style={{ flex: 2 }}
values={['Value1', 'Value2']}
selectedIndex={this.state.drink}
onChange={(event) => {
this.setState({ drink: event.nativeEvent.selectedSegmentIndex });
}}
/>);
<View style={{ flex: 1 }} />
</View>
but that (perhaps unsurprisingly) doesn't work. Can anyone point me to the correct method? I know I can just use two different files for iOS/Android but I'd rather keep it together in one if possible.
I would create a sepeare component and this component would return segment according to platform but you can create an inner function as an alternative. call this function in render to handle decide which platform app runs and return segment according to platform.
_segmentPicker() {
if (Platform.OS == 'android') {
return (
<SegmentedControlIOS
tintColor={styleBackground}
style={{ flex: 2 }}
values={['Value1', 'Value2']}
selectedIndex={this.state.drink}
onChange={(event) => {
this.setState({ drink: event.nativeEvent.selectedSegmentIndex });
}}
/>
);
} else if (Platform.OS == 'ios') {
return (
<SegmentedControlIOS
tintColor={styleBackground}
style={{ flex: 2 }}
values={['Value1', 'Value2']}
selectedIndex={this.state.drink}
onChange={(event) => {
this.setState({ drink: event.nativeEvent.selectedSegmentIndex });
}}
/>
);
}
}
render(){
return (
<View>
{this._segmentPicker()}
.
.
</View>
);
}