dclipca
dclipca

Reputation: 1937

React Native CameraRoll permission denied

After pressing a button the following code is executed:

takePicture = async function() {
    if (this.camera) {
      const options = { quality: 0.5, base64: true }
      const data = await this.camera.takePictureAsync(options)
      CameraRoll.saveToCameraRoll(data.uri)
    }
  }

The debugger shows:

Possible Unhandled Promise Rejection
Error: Permission Denied ...

Apparently CameraRoll requires user's permission to do that, but I already included them in my AndroidManifest.xml file:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.gradualcamera">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:allowBackup="false"
      android:theme="@style/AppTheme">
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>

</manifest>

The code of the whole component:

import React, {Component} from 'react';
import {StyleSheet, View} from 'react-native'
import { RNCamera } from 'react-native-camera'
import { CameraRoll } from 'react-native'
import ActionButton from 'react-native-action-button'
import Icon from 'react-native-vector-icons/Ionicons'

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },

  button: {
    height: 200,

    justifyContent: 'flex-end',
    alignItems: 'center'
  },

  actionButtonIcon: {
    fontSize: 20,
    height: 22,
    color: 'white',
  },

});


export default class Cam extends Component {
  constructor() {
    super()
    this.takePicture = this.takePicture.bind(this)
  }

  takePicture = async function() {
    if (this.camera) {
      const options = { quality: 0.5, base64: true }
      const data = await this.camera.takePictureAsync(options)
      CameraRoll.saveToCameraRoll(data.uri)
    }
  }

  render() {
    return (
      <View style={styles.container}>

        <RNCamera
          ref={ref => {this.camera = ref}}
          style={{
            flex: 1,
            width: '100%',
            position: 'relative'
          }}
        >
        </RNCamera>

        <ActionButton size={80} useNativeFeedback={false} buttonColor="rgba(231,76,60,1)">
          <ActionButton.Item useNativeFeedback={false} buttonColor='#9b59b6' title="Settings" onPress={this.props.switchScreen}>
            <Icon name="md-create" style={styles.actionButtonIcon} />
          </ActionButton.Item>
          <ActionButton.Item useNativeFeedback={false} buttonColor='#1abc9c' title="Start" onPress={this.takePicture}>
            <Icon name="md-done-all" style={styles.actionButtonIcon} />
          </ActionButton.Item>

        </ActionButton>

      </View>
    )
  }
}

I already tried to delete the application and restart the Metro server.

I enabled the storage permission manually from the Settings and it works now. However, when I deleted the application and reinstalled it again the storage permissions aren't requested to the user. I have tried to request it with react-native-permissions but it doesn't work:


    componentDidMount() {
      _requestPermission = () => {
        Permissions.request('storage').then(response => {
          // Returns once the user has chosen to 'allow' or to 'not allow' access
          // Response is one of: 'authorized', 'denied', 'restricted', or 'undetermined'
          console.log(response)
        })
      }
    }

Somehow the react-native-permissions method started to work after I removed it out of the onComponentMount method and triggered it with a button.

Upvotes: 3

Views: 7773

Answers (3)

AbdulmateenChitrali
AbdulmateenChitrali

Reputation: 399

Try this way work both on ios and android

  const pickImage = async () => {

    const permissionResult = await ImagePicker.requestCameraPermissionsAsync();
    if (permissionResult.granted === false) {
      alert('Permission to access camera was denied.');
    }else{
      const result = await ImagePicker.launchCameraAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
      allowsEditing:true,
      base64:true,
      quality: 0.5,
    });

    if (!result.cancelled) {
      setImage(`data:image/jpeg;base64,${result?.base64}`);
    }

    }
  };

Upvotes: 1

Krishna
Krishna

Reputation: 347

Just add this line AndroidManifest.xml:

<application tag android:requestLegacyExternalStorage="true"

Upvotes: 4

SmoggeR_js
SmoggeR_js

Reputation: 3160

Take a look to this component and check if the permissions are enabled before to use camera.

https://github.com/yonahforst/react-native-permissions

Upvotes: 1

Related Questions