React Native: Cannot access location using geolocation API - react-native

Error: Looks like the app doesn't have the permission to access location. Add the following line to your app's AndroidManifest.xml
Even though I have added the permissions in manifest.xml and asking for runtime permissions I cannot access GPS.
My AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.location">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
.....
.....
complete code:
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View,
PermissionsAndroid } from 'react-native';
export default class App extends Component {
async requestLocationPermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
'title': 'Location Access Permission',
'message': 'Expensify would like to use your location ' +
'so you we track you.'
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can use the location")
} else {
console.log("Location permission denied")
}
} catch (err) {
console.warn(err)
}
}
componentDidMount() {
console.log("compdidmount");
this.requestLocationPermission();
//Crashes here on getCurrentPosition
navigator.geolocation.getCurrentPosition(
(position) => {
console.log(position.coords.latitude);
},
(error) => {
console.log(error)
},
{enableHighAccuracy: true, timeout: 20000, maximumAge: 10000}
);
}
render() {
return (
<View style>
<Text style>
Tracking App
</Text>
</View>
);
}
}

I got the same issue with the CameraRoll. I fixed this asking for permission when the app starts. You should use this :
import { PermissionsAndroid } from 'react-native';
async function requestCameraPermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
'title': 'Location Permission',
'message': 'Location Permission' +
'so you can use GPS location.'
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can use GPS")
} else {
console.log("GPS location denied")
}
} catch (err) {
console.warn(err)
}
}

I solved this problem by deleting and reinstalling the application.

Related

How do I overcome "Permission Denial....obtain access using ACTION_OPEN_DOCUMENT or related APIs"?

I'm using react-native-firebase and react-native-document-picker and I'm trying to follow the face detection tutorial.
Currently getting the following error despite having read access through PermissionsAndroid:
Permission Denial: reading com.android.provides.media.MediaDocumentsProvider uri [uri] from pid=4746, uid=10135 requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs
I am able to display the selected image by the user on the screen but the react-native-firebase functions seems to not be able to have permission. The error happens at this call: const faces = await vision().faceDetectorProcessImage(localPath);.
Any suggestions on how to give the face detection function access or what am I doing wrong?
My AndroidManifest.xml file contains the following:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Here is all the code in that component for reference:
import React, {useState} from 'react';
import { Button, Text, Image, PermissionsAndroid } from 'react-native';
import vision, { VisionFaceContourType } from '#react-native-firebase/ml-vision';
import DocumentPicker from 'react-native-document-picker';
async function processFaces(localPath) {
console.log(localPath)
const faces = await vision().faceDetectorProcessImage(localPath);
console.log("Got faces")
faces.forEach(face => {
console.log('Head rotation on Y axis: ', face.headEulerAngleY);
console.log('Head rotation on Z axis: ', face.headEulerAngleZ);
console.log('Left eye open probability: ', face.leftEyeOpenProbability);
console.log('Right eye open probability: ', face.rightEyeOpenProbability);
console.log('Smiling probability: ', face.smilingProbability);
face.faceContours.forEach(contour => {
if (contour.type === VisionFaceContourType.FACE) {
console.log('Face outline points: ', contour.points);
}
});
});
}
async function pickFile () {
// Pick a single file
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.images],
});
console.log(
res.uri,
res.type, // mime type
res.name,
res.size
);
return res
} catch (err) {
if (DocumentPicker.isCancel(err)) {
// User cancelled the picker, exit any dialogs or menus and move on
console.log("User cancelled")
} else {
console.log("Error picking file or processing faces")
throw err;
}
}
}
const requestPermission = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
{
title: "Files Permission",
message:
"App needs access to your files " +
"so you can run face detection.",
buttonNeutral: "Ask Me Later",
buttonNegative: "Cancel",
buttonPositive: "OK"
}
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("We can now read files");
} else {
console.log("File read permission denied");
}
return granted
} catch (err) {
console.warn(err);
}
};
function FaceDetectionScreen ({navigation}) {
const [image, setImage] = useState("");
return (
<>
<Text>This is the Face detection screen.</Text>
<Button title="Select Image to detect faces" onPress={async () => {
const permission = await requestPermission();
if (permission === PermissionsAndroid.RESULTS.GRANTED) {
const pickedImage = await pickFile();
const pickedImageUri = pickedImage.uri
setImage(pickedImageUri);
processFaces(pickedImageUri).then(() => console.log('Finished processing file.'));
}
}}/>
<Image style={{flex: 1}} source={{ uri: image}}/>
</>
);
}
export default FaceDetectionScreen;
Thanks to this comment on a github issue I was able to update my code and get it to work by updating the first three lines of processFaces as:
async function processFaces(contentUri) {
const stat = await RNFetchBlob.fs.stat(contentUri)
const faces = await vision().faceDetectorProcessImage(stat.path);
after importing import RNFetchBlob from 'rn-fetch-blob'.
rn-fetch-blob

How to pass api data from react native to html and vice-versa in react-native-html-to-pdf

i am using react-native-html-to-pdf package to create a pdf file i want to pass the api response from react-native to html and receive the data from html. the options available for this npm package is very minimum
There is no options in the package so that i can use it, can someone help me with this ?
Below is my code.
import React, { Component } from 'react';
import { Text, TouchableOpacity, View, StyleSheet, Image, PermissionsAndroid, Platform,} from 'react-native';
import RNHTMLtoPDF from 'react-native-html-to-pdf';
import htmlContent from './htmlContent'
export default class App extends Component {
constructor(props) {
super(props)
this.state = {
apiData: [],
filePath: ''
}
}
askPermission() {
var that = this;
async function requestExternalWritePermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
{
title: 'External Storage Write Permission',
message:
'App needs access to Storage data in your SD Card ',
}
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
that.createPDF();
} else {
alert('WRITE_EXTERNAL_STORAGE permission denied');
}
} catch (err) {
alert('Write permission err', err);
console.warn(err);
}
}
if (Platform.OS === 'android') {
requestExternalWritePermission();
} else {
this.createPDF();
}
}
componentDidMount(){
fetch(`http://API`)
.then((response) => response.json())
.then((responseJson) => {
**console.log("DATA", responseJson) // NEED TO SEND THIS DATA TO "HTML"**
this.setState(() => ({
apiData: responseJson
}))
})
}
async createPDF() {
let options = {
html:htmlContent, // API DATA SHOULD BE SENT TO HTML
fileName: 'RTT Report',
directory: 'docs',
width: 800,
};
let file = await RNHTMLtoPDF.convert(options);
console.log(file.filePath);
this.setState({filePath:file.filePath});
}
render() {
return (
<View style={styles.MainContainer}>
<TouchableOpacity onPress={this.askPermission.bind(this)}>
<View>
<Image
//We are showing the Image from online
source={{
uri:
'https://raw.githubusercontent.com/AboutReact/sampleresource/master/pdf.png',
}}
//You can also show the image from you project directory like below
//source={require('./Images/facebook.png')}
style={styles.ImageStyle}
/>
<Text style={styles.text}>Create PDF</Text>
</View>
</TouchableOpacity>
<Text style={styles.text}>{this.state.filePath}</Text>
</View>
);
}
}
In createPDF method :
// html:htmlContent, // API DATA SHOULD BE SENT TO HTML
html: this.state.apiData // <-- you have stored your html in the state
EDIT:
Probably I was too fast answering, now I think I got your point , here you have an example :
// html: '<h1>PDF TEST</h1>', <-- example from react-native-html-to-pdf
const exampleData = [
{
title: "Element title",
content: "Element content"
},
{
title: "Other title",
content: "Other element content"
}
]
function generateHTML () {
const data = exampleData
// const data = this.state.apiData // <-- in your case
let htmlContent = '<html><body>'
htmlContent += data.map(entry => {
return `<h5>${entry.title}</h5> <br /> <p>${entry.content}</p>`
}).join(' ')
htmlContent += '</body></html>'
return htmlContent
}

React Native Expo “AppLoading threw an unexpected error when loading” error

I have a React Native project with Expo, I installed Expo client on my Android phone. It used to work well so far. But even though I didn't change any code, I now get the following error when I scan the QR code from my phone. This error is shown on terminal and phone screen keeps blank.
import React from 'react';
import { Image } from 'react-native';
import { AppLoading } from 'expo';
import { Asset } from 'expo-asset';
import { Block, GalioProvider } from 'galio-framework';
import Screens from './navigation/Screens';
import { Images, articles, ditsTheme } from './constants';
// cache app images
const assetImages = [
Images.Onboarding,
Images.LogoOnboarding,
Images.Logo,
Images.Pro,
Images.DITSLogo,
Images.iOSLogo,
Images.androidLogo
];
// cache product images
articles.map(article => assetImages.push(article.image));
function cacheImages(images) {
return images.map(image => {
if (typeof image === 'string') {
return Image.prefetch(image);
} else {
return Asset.fromModule(image).downloadAsync();
}
});
}
export default class App extends React.Component {
state = {
isLoadingComplete: false,
}
render() {
if(!this.state.isLoadingComplete) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
);
} else {
return (
<GalioProvider theme={ditsTheme}>
<Block flex>
<Screens />
</Block>
</GalioProvider>
);
}
}
_loadResourcesAsync = async () => {
return Promise.all([
...cacheImages(assetImages),
]);
};
_handleLoadingError = error => {
// In this case, you might want to report the error to your error
// reporting service, for example Sentry
warn(error);
};
_handleFinishLoading = () => {
this.setState({ isLoadingComplete: true });
};
}
How can I solve this error?
In your _handleLoadingError method, you're using warn. While you should be using console.warn. This is what's breaking your app.
I was getting this error, the problem was with AppLoading. The issue turned out to be incorrect function name that I was calling from <AppLoading .. />
Note below, I was using Font.loadAsync (with missing c), fixing it made the font load correctly.
const getFonts = () => Font.loadAsyn({
'nanitu-regular' : require('./assets/fonts/EastSeaDokdo-Regular.ttf'),
'nanitu-bold' : require('./assets/fonts/NanumBrushScript-Regular.ttf')
})
;
You should add onError to AppLoading. As a like:
<AppLoading startAsync={getFonts} onFinish={() => {
setFontLoaded(true)
}} onError={console.warn} />

Looks like app doesn't have permission to access location in react native

I am making an app which access user location using gps.That is why i added following lines to the AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
And below is my function which fetches location of user
componentWillMount(){
navigator.geolocation.getCurrentPosition(
position => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
});
},
error => Alert.alert(error.message),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
);
}
But this produces error that app doesn't have permission to access location and i need to declare
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
in manifest file.I tried many ways and found a solution i.e to ask for run time permission. So I also added following lines in my code
try {
const granted = PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
'title': 'Location Permission',
'message': 'This app needs access to your location',
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can use the location")
} else {
console.log("Location permission denied")
}
} catch (err) {
console.warn(err)
}
But problem doesn't go away.What should i do ?
if you are not using Promise ,you should use async-await. in your code its missing. and after getting permission you can get location
async requestLocationPermission(){
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
'title': 'Example App',
'message': 'Example App access to your location '
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can use the location")
alert("You can use the location");
} else {
console.log("location permission denied")
alert("Location permission denied");
}
} catch (err) {
console.warn(err)
}
}
async componentDidMount() {
await requestLocationPermission()
}
The accepted answer worked for me, but since I was using hooks I had to define the requestLocationPermission method differently.
Create a state for locationPermissionGranted which will change after access is granted
const [locationPermissionGranted, setLocationPermissionGranted] = useState(false);
Set the useEffect method like this:
useEffect(() => {
async function requestLocationPermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
'title': 'Example App',
'message': 'Example App access to your location '
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can use the location")
alert("You can use the location");
// Change the value of the locationPermissionGranted to true after
// the user grants location access
setLocationPermissionGranted(true);
} else {
console.log("location permission denied");
alert("Location permission denied");
}
} catch (err) {
console.warn(err);
}
}
// Don't forget to call the method here
requestLocationPermission();
})
Then later in your code, Show the map/location based on the state value, something like this:
{ locationPermissionGranted ? <TestMapComponent /> : <AccessNotGrantedComponent /> }
When the screen loads asks for the user for location permission (for API > 23 as per the documentation). For more refer this link https://facebook.github.io/react-native/docs/permissionsandroid . If the user allows the location permission it shows the position otherwise show default screen.
import React,{useEffect,useState} from 'react';
import {Text,View,StyleSheet,Alert} from 'react-native';
import MapView from 'react-native-maps';
import {PermissionsAndroid} from 'react-native';
const SearchScreen = () => {
const [latitude,setLatitude] = useState('');
const [longitude,setLongitude] = useState('');
const [granted,setGranted] = useState('');
useEffect(async() =>{
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,
{
title: 'Location Permission',
message:'Get your location to post request',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
navigator.geolocation.getCurrentPosition(position => {
setLatitude(position.coords.latitude);
setLongitude(position.coords.longitude);
});
setGranted(true);
}
},[]);
const onUserPinDragEnd = (e) => {
Alert.alert(JSON.stringify(e))
};
if(granted) {
return (
<View style={styles.container}>
<MapView
style={styles.map}
region={{
latitude: Number(latitude),
longitude: Number(longitude),
latitudeDelta: 0.015,
longitudeDelta: 0.0121
}}
>
<MapView.Marker
key={'i29'}
draggable
onDragEnd={() => onUserPinDragEnd()}
title={'You are here'}
coordinate={{
latitude: Number(latitude),
longitude: Number(longitude),
}}
/>
</MapView>
</View>
)
}else{
return(
<View>
<Text>Permission not granted for maps</Text>
</View>
)
}
};
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
height: 400,
width: 400,
justifyContent: 'flex-end',
alignItems: 'center',
},
map: {
...StyleSheet.absoluteFillObject,
},
});
export default SearchScreen;

How to save captured image to custom app specific folder using react-native-camera

I'm using RNCamera from react-native-camera and save photo using CameraRoll react-native API. But saveToCameraRoll method takes only photo uri returned by takePictureAsync.
And it saves photo to DCIM folder. But I want to save it to some app specific folder. How I can reach it?
I've used cool rn-fetch-blob library to reach that. Here the instructions
I am able to create a directory, but i failed to move the images to that folder, however if it helps you
import React from 'react';
//import react in our code.
import { StyleSheet, Text, View,
Alert, ActivityIndicator, PermissionsAndroid } from 'react-native';
//import all the basic components we are going to use.
import { CameraKitCameraScreen } from 'react-native-camera-kit';
//import CameraKitCameraScreen we are going to use.
import RNFetchBlob from 'react-native-fetch-blob'
export default class App extends React.Component {
state = {isPermitted:false}
constructor(props) {
super(props);
var that=this;
async function requestCameraPermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,{
'title': 'CameraExample App Camera Permission',
'message': 'CameraExample App needs access to your camera '
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
//If CAMERA Permission is granted
//Calling the WRITE_EXTERNAL_STORAGE permission function
requestExternalWritePermission();
} else {
alert("CAMERA permission denied");
}
} catch (err) {
alert("Camera permission err",err);
console.warn(err)
}
}
async function requestExternalWritePermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,{
'title': 'CameraExample App External Storage Write Permission',
'message': 'CameraExample App needs access to Storage data in your SD Card '
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
//If WRITE_EXTERNAL_STORAGE Permission is granted
//Calling the READ_EXTERNAL_STORAGE permission function
requestExternalReadPermission();
} else {
alert("WRITE_EXTERNAL_STORAGE permission denied");
}
} catch (err) {
alert("Write permission err",err);
console.warn(err)
}
}
async function requestExternalReadPermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,{
'title': 'CameraExample App Read Storage Write Permission',
'message': 'CameraExample App needs access to your SD Card '
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
//If READ_EXTERNAL_STORAGE Permission is granted
//changing the state to re-render and open the camera
//in place of activity indicator
that.setState({isPermitted:true})
} else {
alert("READ_EXTERNAL_STORAGE permission denied");
}
} catch (err) {
alert("Read permission err",err);
console.warn(err)
}
}
//Calling the camera permission function
requestCameraPermission();
}
onBottomButtonPressed(event) {
if (event.type) {
//const captureImages = JSON.stringify(event.captureImages);
if (event.type == "capture") {
const pictureFolder = RNFetchBlob.fs.dirs.SDCardDir+'/Optimize/';
const captureImageLength = event.captureImages.length;
RNFetchBlob.fs.exists(pictureFolder).then((exists)=>{
if(exists){
RNFetchBlob.fs.isDir(pictureFolder).then((isDir)=>{
if(isDir){
RNFetchBlob.fs.mv(event.captureImages[0].uri, RNFetchBlob.fs.dirs.SDCardDir+'/Optimize/').then(() => {
alert('Image Moved');
}).catch((e)=>{ alert("FAILED:= "+e.message) });
}else{
alert('Some Error Happened');
}
}).catch((e)=>{ alert("Checking Directory Error : "+e.message); });
}else{
RNFetchBlob.fs.mkdir(pictureFolder).then(()=>{
alert('DIRECTORY CREATED');
}).catch((e)=>{ alert("Directory Creating Error : "+e.message); });
}
});
}
}
}
render() {
if(this.state.isPermitted){
return (
<CameraKitCameraScreen
// Buttons to perform action done and cancel
actions={{ rightButtonText: 'Done', leftButtonText: 'Cancel' }}
onBottomButtonPressed={event => this.onBottomButtonPressed(event)}
flashImages={{
// Flash button images
on: require('./assets/flashon.png'),
off: require('./assets/flashoff.png'),
auto: require('./assets/flashauto.png'),
}}
cameraFlipImage={require('./assets/flip.png')}
captureButtonImage={require('./assets/capture.png')}
/>
);
}else{
return (
<ActivityIndicator />
)
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});