├── .babelrc ├── .gitignore ├── .watchmanconfig ├── App.js ├── App.test.js ├── README.md ├── android ├── app │ ├── BUCK │ ├── app.iml │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── screenrecorder │ │ │ ├── MainActivity.java │ │ │ ├── MainApplication.java │ │ │ ├── RecorderManager.java │ │ │ └── RecorderReactPackage.java │ │ └── res │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ └── values │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── keystores │ ├── BUCK │ └── debug.keystore.properties ├── screenrecorder.iml └── settings.gradle ├── app.json ├── index.js ├── ios ├── ASScreenRecorder.h ├── ASScreenRecorder.m ├── RecorderManager.h ├── RecorderManager.m ├── screenrecorder-tvOS │ └── Info.plist ├── screenrecorder-tvOSTests │ └── Info.plist ├── screenrecorder.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── chenshu.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ ├── xcshareddata │ │ └── xcschemes │ │ │ ├── screenrecorder-tvOS.xcscheme │ │ │ └── screenrecorder.xcscheme │ └── xcuserdata │ │ └── chenshu.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── screenrecorder │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Info.plist │ └── main.m └── screenrecorderTests │ ├── Info.plist │ └── screenrecorderTests.m ├── package-lock.json └── package.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "babel-preset-react-native-stage-0/decorator-support" 4 | ], 5 | "env": { 6 | "development": { 7 | "plugins": [ 8 | "transform-react-jsx-source" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # expo 4 | .expo/ 5 | 6 | # dependencies 7 | /node_modules 8 | 9 | # builds 10 | ios/build/ 11 | android/app/build/ 12 | android/build/generated/ 13 | android/build/intermediates/ 14 | 15 | # misc 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | android/.gradle 21 | android/.idea 22 | android/local.properties 23 | 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | TextInput, 6 | View, 7 | CameraRoll, 8 | Button, 9 | NativeModules, 10 | Platform, 11 | DeviceEventEmitter, 12 | Keyboard 13 | } from 'react-native'; 14 | import VideoPlayer from 'react-native-video-controls'; 15 | const { RecorderManager } = NativeModules; 16 | 17 | export default class App extends React.Component { 18 | state = { 19 | videoUri: null, 20 | disableStart: false, 21 | disableStopped: true, 22 | disablePlayable: true, 23 | androidVideoUrl: null, 24 | keyboardIsShown: false, 25 | } 26 | 27 | start = () => { 28 | RecorderManager.start(); 29 | this.setState({ 30 | disableStart: true, 31 | disableStopped: false, 32 | disablePlayable: true, 33 | }); 34 | } 35 | 36 | stop = () => { 37 | RecorderManager.stop(); 38 | this.setState({ 39 | disableStart: true, 40 | disableStopped: true, 41 | disablePlayable: false, 42 | }); 43 | } 44 | 45 | play = () => { 46 | switch (Platform.OS) { 47 | case 'android': 48 | const { androidVideoUrl } = this.state; 49 | if (androidVideoUrl) { 50 | this.setState({ 51 | videoUri: androidVideoUrl, 52 | disableStart: true, 53 | disableStopped: true, 54 | disablePlayable: true, 55 | }) 56 | } 57 | break; 58 | 59 | case 'ios': 60 | CameraRoll.getPhotos({ 61 | first: 1, 62 | assetType: 'Videos' 63 | }).then(r => { 64 | if (r.edges.length > 0) { 65 | const video = r.edges[0].node.image; 66 | this.setState({ 67 | videoUri: video.uri, 68 | disableStart: true, 69 | disableStopped: true, 70 | disablePlayable: true, 71 | }) 72 | } 73 | }); 74 | break; 75 | 76 | default: 77 | break; 78 | } 79 | } 80 | 81 | playEnded = () => { 82 | this.setState({ 83 | videoUri: null, 84 | disableStart: false, 85 | disableStopped: true, 86 | disablePlayable: true, 87 | androidVideoUrl: null, 88 | }); 89 | } 90 | 91 | keyboardDidShow = () => { 92 | this.setState({keyboardIsShown: true}); 93 | } 94 | 95 | keyboardDidHide = () => { 96 | this.setState({keyboardIsShown: false}); 97 | } 98 | 99 | rendernControlBtnGroup = () => { 100 | const { disableStart, disableStopped, disablePlayable } = this.state; 101 | return ( 102 | 103 |