MediaLibrary.createAssetAsync on Android Expo app

Hi, this is my first post.
I hope this is the right place and that someone could help me.

I’m trying to use the MediaLibrary.createAssetAsync(uri); function to create an assets.

I’m use the App Expo Client 2.17.4.

On iOS device everything is working as expected.
Saddly on my Android Device (Samsung Galaxy s9) no, it seems that the MediaLibrary.createAssetAsync(uri) method either return an asset or throw an exception.

Thanks for the help

this is the js source code:

import React from ‘react’;
import { Text, View, TouchableOpacity, Alert,SafeAreaView,Dimensions, Platform,StyleSheet } from ‘react-native’;

import { Camera } from ‘expo-camera’;
import * as Permissions from ‘expo-permissions’;
import * as ImagePicker from ‘expo-image-picker’;
import * as MediaLibrary from ‘expo-media-library’;

import { FontAwesome, Ionicons,MaterialCommunityIcons} from ‘@expo/vector-icons’;

import styles from ‘…/…/Stili/styles’;
import Graphic from ‘…/…/Helper/Graphic’;
import Costanti from ‘…/…/Helper/Costanti’;
import NomiView from ‘…/NomiView’;

import SharedData from ‘…/…/Data/SharedData’;

const windowWidth = Dimensions.get(‘window’).width;
const windowHeight = Dimensions.get(‘window’).height;

import * as ScreenOrientation from ‘expo-screen-orientation’;

export default class AttivitaDettaglioFotoIns2View extends React.Component{

constructor(props){
    super(props);
    this.state = { 
        hasPermission:false,
        type:Camera.Constants.Type.back,
        refresh:false,
        bestRatio:'4:3',
        zoom:0,
        isLandScape:false,
    };
};

async componentDidMount(){
    this.getPermissionAsync();
    
    ScreenOrientation.unlockAsync();

    /* */
    Dimensions.addEventListener('change',()=>{
        ScreenOrientation.getOrientationAsync().then((data)=>{
            let isLandScape=false;
            if (data==ScreenOrientation.Orientation.LANDSCAPE_LEFT || 
                data==ScreenOrientation.Orientation.LANDSCAPE_RIGHT ){
                isLandScape=true;
              }
            
              this.setState({isLandScape:isLandScape});
      
          }).catch((error)=>{
            alert('non è stato possibile determinare la posizione dello schermo');
          });
    });
    
}

componentWillUnmount(){
    ScreenOrientation.lockAsync(Graphic.myPortrait());
}

prepareRatio = async () =>{
    //
    if (Platform.OS === 'android' && this.camera) {
        const ratios = await this.camera.getSupportedRatiosAsync();
        var bestRatio = '';
        
        
        var bestRatioError = 100000;
        var wantedRatio=windowHeight/windowWidth;
        
        for (i in ratios) {
            const r = ratios[i].split(":");
            if (Math.abs(wantedRatio - r[0]/r[1]) < bestRatioError) {
                bestRatioError = Math.abs(wantedRatio - r[0]/r[1]);
                bestRatio = ratios[i];
            }
        }
        
        this.setState({bestRatio:bestRatio});   
        this.setState({refresh:!this.state.refresh});
    }
}

/*funzioni grafiche*/
render(){

    if(this.state.hasPermission===false){
        return(
            <View>
                 <Text>No access to camera</Text>
            </View>
        );
    }

    return(
        <SafeAreaView style={{ flex: 1 }}>
            
            <Camera style={this.state.isLandScape?styleView.cameraL:styleView.carmeraP} 
                    type={this.state.type}
                    ref={ref => {
                        this.camera = ref;
                      }}
                      onCameraReady={
                        this.prepareRatio
                      }
                      ratio={this.state.bestRatio}
                      zoom={this.state.zoom}
                    >
                    {this._currentAspectRatio()}    
                
                <View style={{flex:1}}></View>
                {this._slider()}    
                <View style={this.state.isLandScape?styleView.pulsantieraInnerL:styleView.pulsantieraInnerP}>
                    <TouchableOpacity
                        style={this.state.isLandScape?styleView.pulsanteCameraL:styleView.pulsanteCameraP}
                        onPress={this.takePictureFromCameraRoll}
                        >
                        <Ionicons
                            name="ios-photos"
                            style={{ color: "#fff", fontSize: 30}}
                        />
                    </TouchableOpacity>
                    <TouchableOpacity
                        style={this.state.isLandScape?styleView.pulsanteCameraL:styleView.pulsanteCameraP}
                        onPress={this.takePicture}>
                        <FontAwesome
                            name="camera"
                            style={{ color: "#fff", fontSize: 30}}
                        />
                    </TouchableOpacity>
                    <TouchableOpacity
                        style={this.state.isLandScape?styleView.pulsanteCameraL:styleView.pulsanteCameraP}
                        onPress={()=>{
                            this.ritornaRiepilogoFoto();
                        }}>
                        <MaterialCommunityIcons
                            name="exit-to-app"
                            style={{ color: "#fff", fontSize: 30}}
                        />
                    </TouchableOpacity>
                </View>
                
            </Camera>
        </SafeAreaView>
    );
}; 

_slider=()=>{
    
    return(
        <View style={this.state.isLandScape?styleView.pulsantieraInnerL:styleView.pulsantieraInnerP}>
                    <TouchableOpacity
                        style={this.state.isLandScape?styleView.pulsanteCameraL:styleView.pulsanteCameraP}
                        onPress={()=>{
                            if(this.state.zoom>0) {
                                let newZoom=this.state.zoom;
                                newZoom-=0.1;
                                if (newZoom<0) newZoom=0;
                                this.setState({zoom:newZoom});
                            }
                        }}>
                        <FontAwesome
                            name="minus"
                            style={{ color: "#fff", fontSize: 30}}
                        />
                    </TouchableOpacity>

                    <View style={this.state.isLandScape?styleView.testoL:styleView.testoP}>
                        <Text style={styles.testoDefault} >Zoom :{this.state.zoom.toFixed(2)}</Text>
                    </View>
                    <TouchableOpacity
                        style={this.state.isLandScape?styleView.pulsanteCameraL:styleView.pulsanteCameraP}
                        onPress={()=>{
                            if(this.state.zoom<1) {
                                let newZoom=this.state.zoom;
                                newZoom+=0.1;
                                if (newZoom>1) newZoom=1;
                                this.setState({zoom:newZoom});
                            }
                        }}
                        >
                        <FontAwesome
                            name="plus"
                            style={{ color: "#fff", fontSize: 30}}
                        />
                    </TouchableOpacity>
                </View>
        
        );
       
}

_currentAspectRatio=()=>{
    if(Platform.OS=='android'){
        return(
            <View style={{position:'absolute',top:20,left:10, backgroundColor:'black'}} >
                <Text style={styles.testoDefault}>ratio: {this.camera?this.camera.props.ratio:''} {this.state.isLandScape?'L':'P'}</Text>
            </View>

        );
    }else{return (null);}
}

/*funzioni logiche */
addPicture(photo,idFoto,isFromCamera){
    var obj= new Object;
    obj.photo=photo;
    obj.id=idFoto;
    obj.isFromCamera=isFromCamera;
    return obj;
}

takePictureNoAlbum=async()=>{
    const { uri }  = await this.camera.takePictureAsync();
    MediaLibrary.createAssetAsync(uri)
    .then((asset)=>{
        var idFoto=SharedData.getInstance().getAttivitaCorrente().fotoNuoveLista.length+1;
        SharedData.getInstance().getAttivitaCorrente().fotoNuoveLista.push(this.addPicture(asset,
                                                                                     idFoto,
                                                                                     true));                                                                              
        this.ritornaRiepilogoFoto();
    })
    .catch((error)=>{
        alert('errore durante il salvataggio della foto ' + error);
    })

}

/* */
takePicture = async () => {
   
    const { uri }  = await this.camera.takePictureAsync();

    /**/
    const asset = await MediaLibrary.createAssetAsync(uri);

    /*this piece of code is not executed at all */
    var idFoto=0;
    SharedData.getInstance().getAttivitaCorrente().fotoNuoveLista.forEach((item)=>{
        if (item.id>idFoto) idFoto=item.id;
    });
    idFoto+=1;
    
    SharedData.getInstance().getAttivitaCorrente().fotoNuoveLista.push(this.addPicture(asset,
                                                                                    idFoto,
                                                                                    true));                                                                              
    this.ritornaRiepilogoFoto();
        
}

/*original method currently not used */
takePicture_backup= async () => {
    const { uri }  = await this.camera.takePictureAsync();
    
    const asset = await MediaLibrary.createAssetAsync(uri);

    MediaLibrary.createAlbumAsync(Costanti.NOME_ALBUM, asset)
      .then(() => {
          
        var idFoto=0;
        SharedData.getInstance().getAttivitaCorrente().fotoNuoveLista.forEach((item)=>{
            if (item.id>idFoto) idFoto=item.id;
        });
        idFoto+=1;
        
        SharedData.getInstance().getAttivitaCorrente().fotoNuoveLista.push(this.addPicture(asset,
                                                                                     idFoto,
                                                                                     true));                                                                              
        this.ritornaRiepilogoFoto();
      })
      .catch((error) => {
        Alert('errore durante lo scatto della foto: ' + error);
      });
  }

/* */
takePictureFromCameraRoll=async()=>{
    //
    if(!this.state.hasPermission){
      Alert('l\'App non ha il permesso di accedere al rullino!');
    }else{
        let photo =await ImagePicker.launchImageLibraryAsync({mediaTypes:ImagePicker.MediaTypeOptions.Images,})
        let  asset = await MediaLibrary.createAssetAsync(photo.uri);
        var idFoto=0;
        SharedData.getInstance().getAttivitaCorrente().fotoNuoveLista.forEach((item)=>{
            if (item.id>idFoto) idFoto=item.id;
        });
        idFoto+=1;
        SharedData.getInstance().getAttivitaCorrente().fotoNuoveLista.push(this.addPicture(asset,
                                                                                        idFoto,
                                                                                        false));                                                                              
        this.ritornaRiepilogoFoto();
      
    }
}



takePictureFromCameraRoll_backup=async()=>{
    //
    if(!this.state.hasPermission){
      Alert('l\'App non ha il permesso di accedere al rullino!');
    }else{
      let photo =await ImagePicker.launchImageLibraryAsync({mediaTypes:ImagePicker.MediaTypeOptions.Images,})
      let  asset = await MediaLibrary.createAssetAsync(photo.uri);
      MediaLibrary.createAlbumAsync(Costanti.NOME_ALBUM, asset)
      .then(() => {
        var idFoto=0;
        SharedData.getInstance().getAttivitaCorrente().fotoNuoveLista.forEach((item)=>{
            if (item.id>idFoto) idFoto=item.id;
        });
        idFoto+=1;
        SharedData.getInstance().getAttivitaCorrente().fotoNuoveLista.push(this.addPicture(asset,
                                                                                     idFoto,
                                                                                     false));                                                                              
        this.ritornaRiepilogoFoto();
      })
      .catch(error => {
        Alert('errore durante la lettura del rullino: ' + error);
      });
    }
}

/* */
getPermissionAsync = async () => {
    // Camera roll Permission 
    const stat_cr = await Permissions.getAsync(Permissions.CAMERA_ROLL);
    
    if(stat_cr.status!== 'granted'){
        const new_stat_cr = await Permissions.askAsync(Permissions.CAMERA_ROLL);
        if (new_stat_cr.status !== 'granted') {
            alert('autorizzazione al salvataggio delle foto non data!');
        }
    }
    // Camera Permission
    const { status } = await Permissions.askAsync(Permissions.CAMERA);
    this.setState({ hasPermission: status === 'granted' });
  } 

  /* */
  ritornaRiepilogoFoto(){
    this.props.navigation.replace(NomiView.NomeAttivitaDettaglioFotoNew2View());
  }

};


Expo CLI 3.27.7 environment info:
System:
OS: macOS 10.15.5
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 14.11.0 - /usr/local/bin/node
npm: 6.14.8 - /usr/local/bin/npm
SDKs:
iOS SDK:
Platforms: iOS 13.5, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
IDEs:
Android Studio: 4.0 AI-193.6911.18.40.6514223
Xcode: 11.5/11E608c - /usr/bin/xcodebuild
npmPackages:
expo: ~37.0.3 => 37.0.7
react: ~16.9.0 => 16.9.0
react-dom: ~16.9.0 => 16.9.0
react-native: https://github.com/expo/react-native/archive/sdk-37.0.1.tar.gz => 0.61.4
react-native-web: ~0.11.7 => 0.11.7
npmGlobalPackages:
expo-cli: 3.27.7
Expo Workflow: managed

2 Likes

I’m having the same issue here.

1 Like

Im also experiencing the same issue

await MediaLibrary.createAssetAsync(uri)

is not working for me as well

Thanks

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.