Camera Roll API + Upload from Camera Roll module We will show the pictures in the camera using the built-in react Native camera Roll API. Once the user has selected a picture, we will use the upload from Camera roll module to obtain the Base64 data for the image. If you just want the user to see and select the picture, you can use this method, but if you want to take a photo, you need to use the camera module. If you do not want the user to define and select the image interface, you can use the image picker Module.
Import Cameraroll API
Const REACT = require (' react-native '); const { cameraroll,} = React;
Use the Getphotos method in Cameraroll to get a list of pictures.
Cameraroll.getphotos accepts 3 parameters: the first parameter is a pair of image, which defines what kind of picture is returned from the camera roll. The second one is a callback function, which takes the requested image, and the third parameter is a callback function that handles the error. First, let's take a look at the first parameter, how it defines the picture to be returned. The following is the property of this logarithm.
{First : ...,//(required) in the photo, after sorting in reverse order, in the number of captured photos after: ... ,//The Last call to Getphotos returns the pointer. Cursor grouptypes: ...,//Specify grouping type, filter result //one of [' Album ', ' All ', ' Event ', ' Faces ', ' Library ', ' photostream ', ' Sav ' Edphotos ' (default)] groupName: ...,//specifies filter on group names, like ' recent Photos ' or custom album Titles
assettype: ...//Specifies filter on Assettype //One of [' All ', ' Videos ', ' Photos ' (default)]}
For our example, we want to get the top 25 images from the camera roll, and the first parameter of Getphotos is:
Const FETCHPARAMS = { first:25,}
Next, we define a callback function to handle the received image. The data to be passed to this callback function is obtained from Camerarool.getphotos, which is a pair of images that contains an array containing all the image nodes. The other is a pair of images, which contain paging information. This pair looks like this:
{ edges: [ node: { type: ..., group_name: ..., image: { uri: ..., height: ..., width: ..., isstored: ..., }, timestamp: ..., location { ... }, node: {...}, node: {...}, ... ], page_info: { has_next_page: ..., start_cursor: ..., End_cursor: ..., }}
Since the image pair in the node contains the data we are going to use to display the picture in the app, we need to create a function that extracts the image pair from the edges array. And they should be saved in a state variable.
Storeimages (data) { const assets = data.edges; Const IMAGES = assets.map (asset = asset.node.image); This.setstate ({ images:images, });},
Since we are using the images variable, we need to define this variable first
Getinitialstate () { return { images: [], };},
The third parameter of Getphotos is the callback function used to handle the error. For this example, we just send the error to the console.
Logimageerror (Err) { console.log (err);},
So far, we have defined three parameters for Cameraroll.getphotos. We will call this Getphotos in Componentdidmount (), which will retrieve the picture information once.
Componentdidmount () { Const FETCHPARAMS = { first:25, }; Cameraroll.getphotos (Fetchparams, This.storeimages, This.logimageerror);},
To read a picture we can use the image component, the Flexbox style, and other map function to display the retrieved image.
Let's first import the stylesheet and image components
const { cameraroll, StyleSheet, Image,} = React;
Then display the picture in the render function
Render () { return ( <scrollview style={styles.container}> <view style={styles.imagegrid}> {this.state.images.map (image = <image style={styles.image} source={{Uri:image.uri}}/>)} </ view> </ScrollView> ); }
Then add a style
Const STYLES = stylesheet.create ({ container: { flex:1, backgroundcolor: ' #F5FCFF ', }, Imagegrid: { flex:1, flexdirection: ' Row ', flexwrap: ' Wrap ', justifycontent: ' Center ' }, Image: { width:100, height:100, margin:10, },});
For now, your component looks like this
Const REACT = require (' react-native '); const {StyleSheet, Text, View, ScrollView, Image, cameraroll,} = React;const Styles = Stylesheet.create ({container: {flex:1, backgroundcolor: ' #F5FCFF ',}, Imagegrid: {flex:1, fle Xdirection: ' Row ', Flexwrap: ' Wrap ', justifycontent: ' Center '}, Image: {width:100, height:100, margin : Reactimageproject,}, const = React.createclass ({getinitialstate ()} {return {images: [],}; }, Componentdidmount () {Const FETCHPARAMS = {first:25,}; Cameraroll.getphotos (Fetchparams, This.storeimages, This.logimageerror); }, Storeimages (data) {Const ASSETS = data.edges; Const IMAGES = Assets.map ((asset) = Asset.node.image); This.setstate ({images:images,}); }, Logimageerror (err) {Console.log (err); }, Render () {return (<scrollview style={styles.container}> <view style={styles.imagegrid}> {This.state.images.map (IMAGE) = <image style={styles.image} source={{Uri:image.uri}}/>)} </View> </scrollview> ; ); }});
When you run this project, you will see the latest 25 pictures in the latest camera
Select a picture in order for the user to be able to select one of the images, we ran to let the above image be clicked. We need to use the Touchablehighlight component to save the URI of the picture to another state variable when the image is clicked.
We first test the selection to the picture URI
Selectimage (URI) { this.setstate ({ selected:uri, }); Console.log (' Selected Image: ', URI);},
Again, you need to define in Getinitialsate ()
Getinitialstate () { return { images: [], selected: ', };},
The following is the new render function
const { StyleSheet, Text, View, ScrollView, Image, cameraroll, Touchablehighlight,} = React;render () { return ( <scrollview style={styles.container}> <view style={ Styles.imagegrid}> {this.state.images.map (image) = { return ( <touchablehighlight Onpress={this.selectimage.bind (null, Image.uri)}> <image style={styles.image} source={{Uri:image.uri}} /> </TouchableHighlight> ) })} </View> </ScrollView> );}
When you run this project, clicking on the image will output the URI of the image to the console.
The base64 data for the image already exists a module that uses the React native image component to obtain the Base64 version of the image. But it can't be installed through NPM. So we just need to create a custom module and add it in. As described in Upload-from-camera-roll, how to include the Upload-form-camera-roll module in your project.
Now, we can use this module to get Base64 encoded image data from the URI of the image. We can change the Selectimage function, and change the function of the original output URI to the Base64 encoding to save and output the image.
Selectimage (URI) { NativeModules.ReadImageData.readImage (URI, (image) = = { This.setstate ({ selected : Image, }); Console.log (image);} ),
The complete code is as follows
Const REACT = require (' react-native '); const {appregistry, StyleSheet, Text, View, ScrollView, Image, Cameraroll, Touchablehighlight, nativemodules,} = react;const styles = stylesheet.create ({container: {f Lex:1, BackgroundColor: ' #F5FCFF ',}, Imagegrid: {flex:1, flexdirection: ' Row ', FLEXW Rap: ' Wrap ', justifycontent: ' Center '}, Image: {width:100, height:100, Margin:10, }}); const Reactimageproject = React.createclass ({getinitialstate () {return {images: [], Selected: ',}; }, Componentdidmount () {Const FETCHPARAMS = {first:25,}; Cameraroll.getphotos (Fetchparams, This.storeimages, This.logimageerror); }, Storeimages (data) {Const ASSETS = data.edges; Const IMAGES = Assets.map ((asset) = Asset.node.image); This.setstate ({images:images,}); }, Logimageerror (err) {Console.log (err); }, Selectimage (URI) {NativeModules.ReadImageData.readImage (URI, (image) = = {This.setstate ({ Selected:image,}); Console.log (image); }); }, Render () {return (<scrollview style={styles.container}> <view style={sty les.imagegrid}> {this.state.images.map (image) = {return ( <touchablehighlight onpress={this.selectimage.bind (null, Image.uri)}> <image style={sty Les.image} source={{Uri:image.uri}}/> </TouchableHighlight>); })} </View> </ScrollView>); }}); Appregistry.registercomponent (' Reactimageproject ', () = Reactimageproject);
About the Nativemodules module we can add a Base64 property to the image in the image data obtained. As follows
Open in Libraries > Rctimage > RCTCAMERAROLLMANAGER.M in Xcode
Replace this file as
Https://github.com/scottdixon/react-native-upload-from-camera-roll/blob/master/RCTCameraRollManager.m
Now the image you get will contain the Base64 attribute. You only need to adjust the relevant react native file to let it know the new properties
Open/node_modules/react-native/libraries/cameraroll/cameraroll.js, add the following line to line 76
Base64:ReactPropTypes.string,
If you plan to use this method to upload a full-resolution picture, the application will run very slowly because it needs to convert the picture to a large base64 string.
For better optimization, we create a custom local module that allows our JavaScript to talk to Object-c, and in this way we give object-c a picture of the resource URI to it, object-c the Base64 data in return for this image. Now iOS only reads a picture when it's needed. In relation to the above method, all pictures are read. This is a very large optimization.
Creating a custom module is very simple.
In Xcode, open Project > Libraries > React > Base. Right-click on base, select New File ..., and select the Object-c. Name RCTCUSTOM.M, and add the following content. This creates a Readimagedata module.
#import "RCTBridgeModule.h" #import <AssetsLibrary/AssetsLibrary.h> #import <UIKit/UIKit.h> @interface Readimagedata:nsobject <RCTBridgeModule> @end @implementation readimagedatarct_export_module (); Rct_export_method (readimage: (NSString *) input callback: (Rctresponsesenderblock) callback) {//Create Nsurl from URI Nsurl *url = [[Nsurl alloc] initwithstring:input]; Create an Alassetslibrary instance. This provides access to the//videos and photos is under the control of the photos application. Alassetslibrary *library = [[Alassetslibrary alloc] init]; Using the Alassetslibrary instance and our Nsurl object open the image. [Library Assetforurl:url resultblock:^ (Alasset *asset) {//Create an Alassetrepresentation object using our asset//and turn it into a bitmap using the Cgimageref op Aque type. Cgimageref imageref = [asset thumbnail]; Create uiimagejpegrepresentation from cgimageref nsdata *imagedata = UiimagejpegrepresentatioN ([UIImage Imagewithcgimage:imageref], 0.1); Convert to Base64 encoded string nsstring *base64encoded = [ImageData base64encodedstringwithoptions:0]; Callback (@[base64encoded]); } failureblock:^ (Nserror *error) {NSLog (@ "That didn ' t work%@", error); }]; } @end
Now that your Xcode project has a new custom module, we can import this component in JavaScript.
var {View, Text, Image, nativemodules} = React;
And then we can visit our new module Nativemodules.
NativeModules.ReadImageData.readImage (OurImage.node.image.uri, (image) = { Console.log (image)})
Then, can fetch the method, upload the picture resource
Fetch (' http://your.server/app.php ', {method: ' POST ', headers: { ' Accept ': ' Application/json ', ' Content-type ': ' Application/json ', body:JSON.stringify ({imagedata:image})})
Camera Roll API + Upload from camera roll Module