# 圖片存入相簿功能 > RN 提供了 CameraRoll 的功能。 - [Ref](https://www.twblogs.net/a/5c87b8f3bd9eee35cd6a4885) --- ## 照片獲取與保存 將採用 CameraRoll 訪問本地相冊的功能,它包含兩個方法: `CameraRoll.getPhotos(params);` 與 `CameraRoll.saveToCameraRoll(tag, [type]);` 。 ### 權限 要保存內容,或取用手機資料,皆需要跟手機請求權限。 - [Ref](https://blog.csdn.net/zeping891103/article/details/88413708) #### Android 官方提供 PermissionsAndroid 来獲取權限,以獲取 WRITE 權限。 ``` js UNSAFE_componentWillMount() { this.requestReadPermission(); } async requestReadPermission() { try { const os = Platform.OS; // android or ios if(os === 'android'){ const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, { //第一次请求【拒绝】后提示用户你为什么要这个权限 'title': '我要读写权限', 'message': '没权限我不能工作,同意就好了' } ); if (granted === PermissionsAndroid.RESULTS.GRANTED) { console.log('你已获取了读写权限'); // 继续运行其它代码 } else { console.log('获取读写权限失败'); } }else{ console.log('你已获取了读写权限'); // 继续运行其它代码 } } catch (err) { console.log(err.toString()); } } ``` 用户首次啟動 app 時將會收到讀寫權限請求的通知。 除此之外,最好還要 android/app/src/main/AndroidManifest.xml配置上 ``` // 需要什麼權限就配置什麼權限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ``` #### iOS 使用 RCTCameraRoll Library(也有部分權限只需配置 Info.plist 即可,視官方 RN 支持程度而定)。 1. node_module/react-native/Libraries/CameraRoll 2. 把 RCTCameraRoll.xcodeproj 添加到在 Liberaries 資料夾下 3. Build Phases -> Link Binary With Libraries 裡添加 libRCTCameraRoll.a 4. 在 Info.plist 配置請求照片的描述(Privacy - Photo Library Usage Description) ``` CameraRoll.getPhotos(...) // 获取相册照片或视频 CameraRoll.saveToCameraRoll(...) // 保存照片或视频 ``` ### Demo ``` js import React from 'react'; import { View, Text, Button, Image, Platform, CameraRoll, PermissionsAndroid, Alert } from 'react-native'; class CameraRollAPI extends React.Component { state = { images: [], // 存放照片數據 cursorEnd: '', // 上一次相冊中獲取照片的結束標記 hasNextPage: true // 是否還有下一張照片 } UNSAFE_componentWillMount() { this.requestReadPermission(); } getPhotos(){ if(this.state.hasNextPage){ let queryNativePictuire = { first: 1, assetType: 'Photos' // All全部|Videos錄像|Photos照片(默認) }; if (this.state.cursorEnd) { queryNativePictuire.after = this.state.cursorEnd; } CameraRoll.getPhotos(queryNativePictuire).then((result) => { let pageInfo = result.page_info; this.setState({ images: result.edges, cursorEnd: pageInfo.end_cursor, hasNextPage: pageInfo.has_next_page }); }).catch((error) => { console.log(error); }); }else{ Alert.alert('提示','已經沒有下一張照片'); } } async requestReadPermission() { try { const os = Platform.OS; // android or ios if(os === 'android'){ const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, { //第一次請求【拒絕】後提示用戶你爲什麼要這個權限 'title': '我要讀寫權限', 'message': '沒權限我不能工作,同意就好了' } ); if (granted === PermissionsAndroid.RESULTS.GRANTED) { // 已獲取了讀寫權限 this.getPhotos(); } else { // 獲取讀寫權限失敗 } }else{ this.getPhotos(); } } catch (err) { console.log(err.toString()); } } _getNextPhoto = () => { this.getPhotos(); } _saveImg = () => { const img = 'http://www.helloui.net/assets/watch.jpg'; // 網絡圖片在android中會報錯 var promise = CameraRoll.saveToCameraRoll(img); // 在 Android 上,img是一個本地 URI,例如"file:///sdcard/img.png"。在 iOS, img可以是任意圖片 URI promise.then(function(result) { alert('保存成功!地址如下:\n' + result); }).catch(function(error) { alert('保存失敗!\n' + error); }); } _renderImg = () => { const side = 200 ; if(this.state.images.length > 0){ const image = this.state.images[0].node.image; return( <View> <Image source={{ uri: image.uri }} style={{width:side, height:side}} /> </View> ); }else{ return null; } } render(){ return( <View> <Text>照片:</Text> {this._renderImg()} <Button title='更換一張照片' onPress={this._getNextPhoto} /> <Button title='保存一張網絡圖片' onPress={this._saveImg} /> </View> ); } } export default CameraRollAPI; ```