Ahmed Essaadi
Ahmed Essaadi

Reputation: 415

undefined is not an object (evaluating '_expo.Permission.askAsync')

i don't know what's the problem exactly but when i click on the button to choose image that erreur fire in the console here's my code

_checkPermissions = async () => {
    try {
      const { status } = await Permission.askAsync(Permission.CAMERA);
      this.setState({ camera: status });
      const { statusRoll } = await Permission.askAsync(Permission.CAMERA_ROLL);
      this.setState({ cameraRoll: statusRoll });
    } catch (err) {
      console.log(err);
    }
  };
  findNewImage = async () => {
    try {
      this._checkPermissions();
      let result = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: "Images",
        allowsEditing: true,
        quality: 1
      });

      if (!result.cancelled) {
        this.setState({
          image: result.uri
        });
      } else {
        console.log("cancel");
      }
    } catch (err) {
     // console.log(err);
    }
  };

Upvotes: 8

Views: 6533

Answers (3)

jave.web
jave.web

Reputation: 15032

I know I'm a little late to the party, but I feel it's important to show a way that is currently working (as of 2022) and also askAsync is deprecated ...

Getting image from (native) CAMERA

TL;DR: Even though we want "camera", we will actually use expo-image-picker FOR THE CAMERA (yes, you read right!)
I REPEAT: DO NOT USE expo-camera FOR CAMERA!

REMEMBER: USE ImagePickerExpo.requestCameraPermissionsAsync()
AND ImagePickerExpo.launchCameraAsync()
NOT Camera....!

  1. So install it first: expo install expo-image-picker

  2. Then import everything, from it under 1 alias, I like to use ImagePickerExpo because ImagePicker itself is confusing since it can mean more libraries, + import all needed for this code - you can replace Button with any other button/pressable that supports onPress (to use react-native-elements, you need to install it with yarn add react-native-elements)

  3. Create displaying component

  4. Create a state & setter to save current image source

  5. Create a function that requests the permissions and opens the camera

  6. Return the coponent with button binding onPress on function from 5. and Image that is displayed from the state from 4. but only when available.

working & tested(so far on android in expo go) code:

import React, { useState } from 'react';
import { View, Image, Alert, StyleSheet } from 'react-native';
import { Button } from 'react-native-elements';

import * as ImagePickerExpo from 'expo-image-picker';


const MyCameraComponent = () => {
    const [selectedImage, setSelectedImage] = useState(null);

    const openCameraWithPermission = async () => {
        let permissionResult = await ImagePickerExpo.requestCameraPermissionsAsync();

        if (permissionResult.granted === false) {
            Alert.alert("For this to work app needs camera roll permissions...");
            return;
        }

        let cameraResult = await ImagePickerExpo.launchCameraAsync({
            // ...
        });
        console.log(cameraResult);

        if (cameraResult.cancelled === true) {
            return;
        }

        setSelectedImage({ localUri: cameraResult.uri });
    };


    return (
        <View>

            <Button title='Take a photo' onPress={openCameraWithPermission}></Button>

            {(selectedImage !== null) && <Image
                source={{ uri: selectedImage.localUri }}
                style={styles.thumbnail}
            />}

        </View>
    );
}

const styles = StyleSheet.create({
    thumbnail: {
        width: 300,
        height: 300,
        resizeMode: "contain"
    }
});

export default MyCameraComponent;

Note that I had to style the Image for it to display, it didn't display to me without proper styling which I find misleading, but I guess that's the react native way...
BTW: This also works in Android emulator (besides expo go in real Android device)
It also works on snack on desktop but only when you choose android (or Web) - https://snack.expo.dev/@jave.web/expo-camera-from-expo-image-picker

Getting image from (native) gallery (not camera)

In case you're wondering how to do the same for gallery, the code is basically the same, you just need a different callback function for the button that uses requestMediaLibraryPermissionsAsync / launchImageLibraryAsync instead of the camera ones.

let openImagePickerAsync = async () => {
    let permissionResult = await ImagePickerExpo.requestMediaLibraryPermissionsAsync();

    if (permissionResult.granted === false) {
        Alert.alert("For this to work app needs media library/gallery permissions...");
        return;
    }

    let pickerResult = await ImagePickerExpo.launchImageLibraryAsync({
        presentationStyle: 0, // without this iOS was crashing
    });
    console.log(pickerResult);

    if (pickerResult.cancelled === true) {
        return;
    }

    setSelectedImage({ localUri: pickerResult.uri });
}

Upvotes: 0

Abdelrhman Elmahdy
Abdelrhman Elmahdy

Reputation: 1683

to me what solved it was importing the permissions and imagePicker like this:

import * as Permissions from 'expo-permissions';
import * as ImagePicker from 'expo-image-picker';

instead of this:

import Permissions from 'expo-permissions';
import ImagePicker from 'expo-image-picker';

And that's basically because there is no default export

Upvotes: 26

roel
roel

Reputation: 1660

It is getAsync(), not askAsync()

https://docs.expo.io/versions/latest/sdk/permissions/

Upvotes: 0

Related Questions