• ReactNative: 了解CameraRoll的API使用


    一、简介

    在APP中照相机的使用非常普遍,需要的相机的功能可能是拍摄图片、保存图片、获取图片、拍摄视频、获取视频、扫描二维码等等。在ReactNative中,提供了一个API来实现这些功能,也即CameraRoll。注意,为了访问运行iOS 10或更高版本的设备上的“相机胶卷”,需要用户的许可。 用描述您的应用如何使用此数据的字符串应添加“ Info.plist”中的“ NSCameraUsageDescription”键。

    二、API

    这个CameraRoll提供了对照相机控制的权限,它提供了常用的静态属性和方法,使用简单。具体的API解释如下所示:

    属性:

    //组类型选项,是一个数组
    static GroupTypesOptions: Array<string>
    
    //也即:
    //Album:专辑  All:所有  Event:事件 
    //Faces:面孔 Library:图库 PhotoStream:照片流  SavedPhotos:保存的图片
    var GROUP_TYPES_OPTIONS = [
        'Album',
        'All',
        'Event',
        'Faces',
        'Library',
        'PhotoStream',
        'SavedPhotos', // default
    ];
    
    
    //资源类型选项,是一个数组
    static AssetTypeOptions: Array<string>
    
    //也即:All:所有 Videos:视频 Photos:照片
    var ASSET_TYPE_OPTIONS = [
        'All',
        'Videos',
        'Photos', // default
    ];

    方法:

    保存资源

    //保存图片到相册
    static saveImageWithTag(tag: string): Promise<Object>{}
    
    //保存资源
    static saveToCameraRoll(tag: string, type?: 'photo' | 'video'): Promise<Object> {}
    
    //返回值解释
    Promise:这是一个异步处理,它是一个函数,包裹着当前操作的逻辑,是否保存成功。
    
    //注意如下:
    1、将照片或视频保存到相机胶卷/图库。
    
    2、在iOS上,tag标签可以是任何图像URI(包括本地,远程资产库和base64数据URI)或本地视频文件URI(目前不支持远程或数据URI用于保存视频)。在Android上,tag标签必须是本地图像或视频URI,例如““ file:///sdcard/img.png”`。
    
    3、如果标签的文件扩展名为.mov或.mp4,则将其推断为视频。 否则,它将被视为照片。 要覆盖自动选择,您可以传递一个可选的“ type”参数,该参数必须是“ photo”或“ video”之一。
    
    4、第1个方法已过时,被官方弃用了。推荐用方法2。

    获取资源

    //获取资源
    static getPhotos(params){
          .......... 
          if(获取到了){
              ..........将结果设置到回调函数中.........
              RCTCameraRollManager.getPhotos(params).then(successCallback, errorCallback);
         } 
         return RCTCameraRollManager.getPhotos(params);
    }
    
    //params为参数,它有对应的格式要求,系统使用getPhotosParamChecker检查,格式如下:
    var getPhotosParamChecker = createStrictShapeTypeChecker({
        
        //所需的照片数量与照片应用程序的顺序相反(即,“保存的照片”中最新的照片)。
        first: PropTypes.number.isRequired,
    
        //与上次调用getPhotos返回的,与page_info {end_cursor}相匹配的游标
        after: PropTypes.string,
    
        //指定要将结果过滤到的组类型。
        groupTypes: PropTypes.oneOf(GROUP_TYPES_OPTIONS),
    
        //为组名称指定过滤器,例如“最近的照片”或自定义相册标题。
        groupName: PropTypes.string,
    
        //指定资源类型过滤器
        assetType: PropTypes.oneOf(ASSET_TYPE_OPTIONS),
    
        //按mimetype(例如image/jpeg)过滤。
        mimeTypes: PropTypes.arrayOf(PropTypes.string),
    });
    
    //这个函数的返回值也是特定的格式,系统使用getPhotosParamChecker检查,格式如下:
    var getPhotosReturnChecker = createStrictShapeTypeChecker({
        // $FlowFixMe(>=0.41.0)
        edges: PropTypes.arrayOf(createStrictShapeTypeChecker({
            node: createStrictShapeTypeChecker({
                type: PropTypes.string.isRequired,
                group_name: PropTypes.string.isRequired,
                image: createStrictShapeTypeChecker({
                    uri: PropTypes.string.isRequired,
                    height: PropTypes.number.isRequired,
                     PropTypes.number.isRequired,
                    isStored: PropTypes.bool,
                }).isRequired,
                timestamp: PropTypes.number.isRequired,
                location: createStrictShapeTypeChecker({
                    latitude: PropTypes.number,
                    longitude: PropTypes.number,
                    altitude: PropTypes.number,
                    heading: PropTypes.number,
                    speed: PropTypes.number,
                }),
            }).isRequired,
        })).isRequired,
        page_info: createStrictShapeTypeChecker({
            has_next_page: PropTypes.bool.isRequired,
            start_cursor: PropTypes.string,
            end_cursor: PropTypes.string,
        }).isRequired,
    });
    
    //也即返回的是一个Promise,在解析后将具有以下形状:
    - `edges` : {Array<node>} An array of node objects
          - `node`: {object} An object with the following shape:
              - `type`: {string}
              - `group_name`: {string}
              - `image`: {object} : An object with the following shape:
                  - `uri`: {string}
                  - `height`: {number}
                  - `width`: {number}
                  - `isStored`: {boolean}
              - `timestamp`: {number}
              - `location`: {object} : An object with the following shape:
                  - `latitude`: {number}
                  - `longitude`: {number}
                  - `altitude`: {number}
                  - `heading`: {number}
                  - `speed`: {number}
     - `page_info` : {object} : An object with the following shape:
          - `has_next_page`: {boolean}
          - `start_cursor`: {boolean}
          - `end_cursor`: {boolean}     

    三、使用

    myCameraRollView.js

    import React, { Component } from 'react';
    
    import {
        StyleSheet,
        View,
        Image,
        Text,
        TouchableOpacity,
        Dimensions,
        CameraRoll
    } from 'react-native';
    
    const imageURL = 'http://a3.att.hudong.com/35/34/19300001295750130986345801104.jpg';
    const {width} = Dimensions.get('window');
    
    export default class  MyCameraRollView extends Component{
    
        state = { uri: "" };
    
        //保存图片
        saveImage() {
            //方式一
            let promise = CameraRoll.saveToCameraRoll(imageURL, 'photo');
            promise.then(function (result) {
                alert('保存成功!地址如下:
    ' + result);
            }).catch(function (error) {
                alert('保存失败!
    ' + error);
            });
    
            //方式二
            // CameraRoll.saveToCameraRoll(imageURL, 'photo').then(result => {
            //     alert('保存成功!地址如下:
    ' + result);
            // }).catch(error => {
            //     alert('保存失败!
    ' + error);
            // })
        }
    
        //获取图片
        getAndShowImage(){
            const params = {
                //照片数量
                first: 1,
                //组类型
                groupTypes: 'All',
                //资源类型
                assetType: 'Photos',
                //资源格式
                mimeTypes: ['image/jpeg'],
            };
            CameraRoll.getPhotos(params).then(
                (response) => {
                    const edges = response.edges;
                    edges.map( (edge) => {
                        this.setState({ uri: edge.node.image.uri });
                        console.log('uri:'+edge.node.image.uri);
                        console.log('height:'+edge.node.image.height);
                        console.log(''+edge.node.image.width);
                        console.log('isStored:'+edge.node.image.isStored);
                    })
                },
                (error) => {
                    alert('获取失败!
    ' + error);
                }
            )
        }
    
        render() {
            const {uri,height,width} = this.state;
            return (
                <View style={styles.container}>
                    <View style={[styles.top,styles.center]}>
                        <Image style={styles.image}
                               resizeMode="stretch"
                               source={uri?{uri: uri }:null}/>
                    </View>
                    <View style={styles.bottom}>
                        <TouchableOpacity onPress={this.saveImage.bind(this)}>
                            <Text style={styles.save}>保存图片</Text>
                        </TouchableOpacity>
                        <TouchableOpacity onPress={this.getAndShowImage.bind(this)}>
                            <Text style={styles.save}>获取图片并显示</Text>
                        </TouchableOpacity>
                    </View>
                </View>
            );
        }
    }
    
    const styles = StyleSheet.create({
        container: {
            flex:1
        },
        top: {
            height: 300,
            marginTop: 20,
            marginLeft: 20,
            marginRight: 20,
            backgroundColor:'#4DE'
        },
        image: {
            height: 300,
             width-40
        },
        bottom: {
            height: 100,
            marginTop: 100,
            marginLeft: 20,
            marginRight: 20
        },
        save: {
            fontSize: 25,
            textAlign:'center',
            marginTop: 20,
            borderWidth: 1,
            borderColor:'red'
        },
        fetch: {
            fontSize: 25,
            textAlign:'center',
            marginTop: 20,
            borderWidth: 1,
            borderColor:'green'
        },
        center: {
            justifyContent: 'center',
            alignItems: 'center'
        }
    });

    index.ios.js 

    /**
     * Sample React Native App
     * https://github.com/facebook/react-native
     * @flow
     */
    
    import React, { Component } from 'react';
    
    import {
        AppRegistry,
        StyleSheet,
        View
    } from 'react-native';
    import MyCameraRollView from "./src/MyCameraRollView";
    
    
    export default class ReactNativeDemo extends Component {
    
        render() {
            return (
                <View style={[styles.flex,styles.bgColor]}>
                    <MyCameraRollView/>
                </View>
            );
        }
    }
    
    const styles = StyleSheet.create({
        flex: {
            flex: 1
        },
        bgColor: {
          backgroundColor: 'white'
        },
        center: {
            alignItems: 'center',
            justifyContent: 'center',
        }
    });
    
    AppRegistry.registerComponent('ReactNativeDemo', () => ReactNativeDemo);
    View Code

       

    2020-01-10 14:39:34.256 [info][tid:com.facebook.react.JavaScript] uri:assets-library://asset/asset.JPG?id=5C2769FB-E915-4A22-9100-7B02CAAB45A7&ext=JPG
    2020-01-10 14:39:34.256 [info][tid:com.facebook.react.JavaScript] height:471
    2020-01-10 14:39:34.257 [info][tid:com.facebook.react.JavaScript] 670
    2020-01-10 14:39:34.257 [info][tid:com.facebook.react.JavaScript] isStored:true

    四、注意

    1、iOS系统从iOS10开始,对于用户隐私更加关注,因此对于相册或者相机的使用,必须添加权限允许字段。字段分别是NSPhotoLibraryUsageDescription和NSPhotoLibraryAddUsageDescription。 info.plist的配置如图所示:

    2、如果在使用CameraRoll的API,然后运行项目时报错(非对象错误),说明在xcode项目没有导入需要的libRCTCameraRoll.a静态库。错误如下所示:

    2020-01-10 10:50:42.462 [error][tid:com.facebook.react.JavaScript] undefined is not an object (evaluating 'RCTCameraRollManager.saveToCameraRoll')
    2020-01-10 10:50:42.468 [fatal][tid:com.facebook.react.ExceptionsManagerQueue] Unhandled JS Exception: undefined is not an object (evaluating 'RCTCameraRollManager.saveToCameraRoll')

    那么此时只需要把项目根路径下的node_modules/react-native/Libraries/CameraRoll/RCTCameraRoll.xcodeproj导入xcode中的Libraries文件夹下即可。步骤如下:

    第一步:打开xcode,选中Libraries文件夹,右键添加文件到该工程中

    第二步:找到RCTCameraRoll.xcodeproj文件,添加到项目中,也即Add即可

    第三步:添加完后,手动把libRCTCameraRoll.a静态库嵌入到项目中。好了,再运行就可以了。

  • 相关阅读:
    android PopupWindow实现从底部弹出或滑出选择菜单或窗口
    AndroidUI开源组件库BottomView 第三方自定义UI控件
    Android LayoutInflater详解
    Android设置上下边框或者左右边框
    杭州驾校模拟考试
    告诉你LTE-FDD与LTE-TDD的区别
    Android-Uiautomator:[5]停止monkey测试
    Android WebView
    解决Item控件抢占焦点
    ACM-计算几何之Quoit Design——hdu1007 zoj2107
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/12170338.html
Copyright © 2020-2023  润新知