React Native学习之CameraRoll API
CameraRoll 模块提供了对手机中保存的图片、视频文件进行遍历访问与操作。提供两个静态方法:getPhotos
和saveToCameraRoll
/ saveImageWithTag
getPhotos
可以得到手机中所有的图片和视频(不仅仅是使用摄像头拍摄的照片、视频,还有各个应用自己下载到手机的图片与视频)
static getPhotos(params: object)
返回一个带有图片标识符 JSON 对象的 Promise
params:对象,一些筛选的规则,有4个成员变量
first
:数值,希望获取多少张图片的信息groupTypes
:字符串,默认为SavedPhotos [Album All Event Faces Library PhotoStream],仅支持IOS平台,用来指定获取图片或视频的类型assetType
:字符串,默认为Photos [All Videos],表示只获取图片after
:字符串,用来记录上一次获取图片的结束标志,方便可以接着上次的位置继续获取。它的值不能由开发者随意赋予,而是应当在上一次获取图片后保存其值。通常,在Android平台,一开始就给这个值为null,但是在IOS平台,设置为null会抛一个无法捕捉的异常,导致红屏。
注意:不管是Android平台还是iOS平台,得到的image对象,可以作为一个整体,传递给Image组件,用来显示图片。
可以分批次读取手机中的所有图片:监听ScrollView滑动到底部时,继续getPhotos
,这时需要用after成员变量,递归调用getPhotos
,当page_info.has_next_page = false
时返回。
CameralRoll 在 iOS 平台中需要添加链接库才能运行,否则报错找不到API:
node_modules\react-native\Libraries\CameraRoll
下的 Xcode 项目文件RCTCameraRoll.xcodeproj
拖动到当前 Xcode 项目的 Libraries 目录。- 选中当前项目,在右边选择 Build Phases,点击打开子项目 Link Binary With Libraris。
- 打开第一步插入的
RCTCameraRoll.xcodeproj
,再打开它的子目录 Products,将子目录下的libRCTCameraRoll.a
文件拖到 Link Binary With Libraris 列表中。 - 使用 Xcode 重新运行项目。
saveToCameraRoll 和 saveImageWithTag(已过时)
保存一个图片到相册
static saveToCameraRoll(tag, type?)
static saveImageWithTag(tag)
返回一个Promise,操作成功时返回新的URI
在安卓上,tag 参数是一个本地URI(是把本地的图片保存到相册中),例如"file:///sdcard/img.png".
在iOS设备上 tag 参数可能是以下之一:
- 本地URI
- 资源库的标签
- 非以上两种类型,表示图片数据将会存储在内存中(并且在本进程持续的时候一直会占用内存)。
系统能够自动识别文件类型, 你也可以传入一个可选的 type 参数,参数值必须为 'photo' 或者 'video' 之一。
rn-camera-roll
CameraRoll暂时还不是特别完善,推荐一个跨平台的rn-camera-roll
。
rn-camera-roll
:https://www.npmjs.com/package/rn-camera-roll
安装组件
npm install rn-camera-roll --save
使用组件
iOS:导入库
node_modules/react-native/Libraries/CameraRoll/RCTCameraRoll.xcodeproj
Android(react-native >= v0.15):
(1)自动更新gradle文件
react-native link rn-camera-roll
(2)在 MainActivity 中注册组件包(需重新编译)
package cc.rnapp;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import com.facebook.react.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
// IMPORT HERE
import fr.bamlab.rncameraroll.CameraRollPackage;
// ---
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactInstanceManager mReactInstanceManager;
private ReactRootView mReactRootView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new MainReactPackage())
// REGISTER PACKAGE HERE
.addPackage(new CameraRollPackage())
// ---
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, "example", null);
setContentView(mReactRootView);
}
...
CameraRoll 范例
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
CameraRoll,
Image,
ListView,
ScrollView,
StyleSheet,
Text,
View
} from 'react-native';
let fetchParams = {
first: 10,
assetType: 'Photos',
//groupTypes in not supported on Android
// groupTypes:'All',
};
let imgUrl = 'http://www.ouloon.com/images/';
class RNAPP extends Component {
constructor(props) {
super(props);
this.state = {
images: []
};
}
render() {
return (
<ScrollView>
<View style={styles.row}>
<View style={styles.flex_1} >
<Image
resizeMode='stretch'
style={[styles.imgHeight, styles.m5]}
source={{ uri: imgUrl + 'ReactNative.jpg' }}
/>
</View>
<View style={styles.flex_1} >
<Image
resizeMode='stretch'
style={[styles.imgHeight, styles.m5]}
source={{ uri: imgUrl + 'Android.jpg' }}
/>
</View>
</View>
<View>
<Text
onPress={this.saveImg.bind(this, 'ReactNative.jpg', 'Android.jpg')}
style={styles.saveImg}
>
保存图片到相册
</Text>
</View>
<View style={styles.imageGrid} >
{
this.state.images.map((image) =>
<Image
style={styles.image}
resizeMode='stretch'
source={image}
key={image.uri}
/>
)
}
</View>
</ScrollView>
);
}
componentDidMount() {
let _that = this;
//从0.20.0版本开始支持返回Promise机制
CameraRoll.getPhotos(fetchParams).then(
(data) => {
console.log(data);
let edges = data.edges;
//.map 是针对数组里的每一个元素,调用回调函数
//第一个参数是元素,第二个参数是下标,然后把每次调用的返回值按顺序再组织成一个新的数组
let images = edges.map((edge) => {
return edge.node.image;
});
_that.setState({
images: images,
});
}
).catch(error => {
console.log('错误: ' + error);
});
}
saveImg(img1, img2) {
let _that = this;
//CameraRoll.saveImageWithTag(imgUrl + img1).then(
CameraRoll.saveToCameraRoll(imgUrl + img1, 'photo').then(
(url) => {
if (url) {
let images = _that.state.images;
//unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
images.unshift({
uri: url,
});
_that.setState({
images: images,
});
//继续保存第二张图片
//CameraRoll.saveImageWithTag(imgUrl + img2).then(
CameraRoll.saveToCameraRoll(imgUrl + img2, 'photo').then(
(url) => {
images.unshift({
uri: url,
});
_that.setState({
images: images,
});
alert('图片全部保存成功');
}
).catch(
error => {
alert('保存第二张照片失败: ' + error);
}
);
}
}
).catch(error => {
alert('保存第一张照片失败: ' + error);
});
}
}
const styles = StyleSheet.create({
flex_1: {
flex: 1,
},
m5: {
marginLeft: 5,
marginRight: 5,
borderWidth: 1,
borderColor: '#ddd',
},
row: {
flexDirection: 'row',
},
imageGrid: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center',
},
image: {
width: 100,
height: 100,
margin: 10,
},
imgHeight: {
height: 180,
},
saveImg: {
flex: 1,
height: 30,
textAlign: 'center',
textAlignVertical: 'center',
marginTop: 20,
color: '#FFF',
lineHeight: 20,
borderRadius: 5,
marginLeft: 5,
marginRight: 5,
fontWeight: 'bold',
backgroundColor: '#3BC1FF',
},
});
AppRegistry.registerComponent('RNAPP', () => RNAPP);
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/02/25/react-native-learning-cameraroll-api/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论