examples working on android/ios again

This commit is contained in:
Kyle Corbitt 2016-02-10 11:39:54 +00:00
parent 17811e29f8
commit 6dc2cb968f
10 changed files with 227 additions and 158 deletions

View File

@ -14,17 +14,19 @@
# Ignore react and fbjs where there are overlaps, but don't ignore # Ignore react and fbjs where there are overlaps, but don't ignore
# anything that react-native relies on # anything that react-native relies on
.*/node_modules/fbjs-haste/.*/__tests__/.* .*/node_modules/fbjs/lib/Map.js
.*/node_modules/fbjs-haste/__forks__/Map.js .*/node_modules/fbjs/lib/Promise.js
.*/node_modules/fbjs-haste/__forks__/Promise.js .*/node_modules/fbjs/lib/fetch.js
.*/node_modules/fbjs-haste/__forks__/fetch.js .*/node_modules/fbjs/lib/ExecutionEnvironment.js
.*/node_modules/fbjs-haste/core/ExecutionEnvironment.js .*/node_modules/fbjs/lib/isEmpty.js
.*/node_modules/fbjs-haste/core/isEmpty.js .*/node_modules/fbjs/lib/crc32.js
.*/node_modules/fbjs-haste/crypto/crc32.js .*/node_modules/fbjs/lib/ErrorUtils.js
.*/node_modules/fbjs-haste/stubs/ErrorUtils.js
.*/node_modules/react-haste/React.js # Flow has a built-in definition for the 'react' module which we prefer to use
.*/node_modules/react-haste/renderers/dom/ReactDOM.js # over the currently-untyped source
.*/node_modules/react-haste/renderers/shared/event/eventPlugins/ResponderEventPlugin.js .*/node_modules/react/react.js
.*/node_modules/react/lib/React.js
.*/node_modules/react/lib/ReactDOM.js
# Ignore commoner tests # Ignore commoner tests
.*/node_modules/commoner/test/.* .*/node_modules/commoner/test/.*
@ -55,9 +57,9 @@ suppress_type=$FlowIssue
suppress_type=$FlowFixMe suppress_type=$FlowFixMe
suppress_type=$FixMe suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-8]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-0]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-8]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+ suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-0]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
[version] [version]
0.18.1 0.20.1

View File

@ -1,3 +1,37 @@
node_modules/**/*
VideoPlayer.xcodeproj/project.xcworkspace/**/* VideoPlayer.xcodeproj/project.xcworkspace/**/*
VideoPlayer.xcodeproj/xcuserdata/**/* VideoPlayer.xcodeproj/xcuserdata/**/*
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IJ
#
.idea
.gradle
local.properties
# node.js
#
node_modules/
npm-debug.log

View File

@ -1,5 +1,7 @@
apply plugin: "com.android.application" apply plugin: "com.android.application"
import com.android.build.OutputFile
/** /**
* The react.gradle file registers two tasks: bundleDebugJsAndAssets and bundleReleaseJsAndAssets. * The react.gradle file registers two tasks: bundleDebugJsAndAssets and bundleReleaseJsAndAssets.
* These basically call `react-native bundle` with the correct arguments during the Android build * These basically call `react-native bundle` with the correct arguments during the Android build
@ -49,6 +51,22 @@ apply plugin: "com.android.application"
apply from: "react.gradle" apply from: "react.gradle"
/**
* Set this to true to create three separate APKs instead of one:
* - A universal APK that works on all devices
* - An APK that only works on ARM devices
* - An APK that only works on x86 devices
* The advantage is the size of the APK is reduced by about 4MB.
* Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device.
*/
def enableSeparateBuildPerCPUArchitecture = false
/**
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = false
android { android {
compileSdkVersion 23 compileSdkVersion 23
buildToolsVersion "23.0.1" buildToolsVersion "23.0.1"
@ -63,17 +81,38 @@ android {
abiFilters "armeabi-v7a", "x86" abiFilters "armeabi-v7a", "x86"
} }
} }
splits {
abi {
enable enableSeparateBuildPerCPUArchitecture
universalApk true
reset()
include "armeabi-v7a", "x86"
}
}
buildTypes { buildTypes {
release { release {
minifyEnabled false // Set this to true to enable Proguard minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
} }
} }
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
def versionCodes = ["armeabi-v7a":1, "x86":2]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
} }
dependencies { dependencies {
compile project(':react-native-video')
compile fileTree(dir: "libs", include: ["*.jar"]) compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1" compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:0.16.+" compile "com.facebook.react:react-native:0.19.+"
compile project(':RCTVideo')
} }

View File

@ -40,10 +40,13 @@
-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
-keep class * extends com.facebook.react.bridge.NativeModule { *; } -keep class * extends com.facebook.react.bridge.NativeModule { *; }
-keepclassmembers,includedescriptorclasses class * { native <methods>; }
-keepclassmembers class * { @com.facebook.react.uimanager.UIProp <fields>; } -keepclassmembers class * { @com.facebook.react.uimanager.UIProp <fields>; }
-keepclassmembers class * { @com.facebook.react.uimanager.ReactProp <methods>; } -keepclassmembers class * { @com.facebook.react.uimanager.ReactProp <methods>; }
-keepclassmembers class * { @com.facebook.react.uimanager.ReactPropGroup <methods>; } -keepclassmembers class * { @com.facebook.react.uimanager.ReactPropGroup <methods>; }
-dontwarn com.facebook.react.**
# okhttp # okhttp
-keepattributes Signature -keepattributes Signature
@ -58,3 +61,7 @@
-dontwarn java.nio.file.* -dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.** -dontwarn okio.**
# stetho
-dontwarn com.facebook.stetho.**

View File

@ -74,14 +74,33 @@ task bundleReleaseJsAndAssets(type: Exec) {
enabled config.bundleInRelease ?: true enabled config.bundleInRelease ?: true
} }
void runBefore(String dependentTaskName, Task task) {
Task dependentTask = tasks.findByPath(dependentTaskName);
if (dependentTask != null) {
dependentTask.dependsOn task
}
}
gradle.projectsEvaluated { gradle.projectsEvaluated {
// hook bundleDebugJsAndAssets into the android build process // hook bundleDebugJsAndAssets into the android build process
bundleDebugJsAndAssets.dependsOn mergeDebugResources bundleDebugJsAndAssets.dependsOn mergeDebugResources
bundleDebugJsAndAssets.dependsOn mergeDebugAssets bundleDebugJsAndAssets.dependsOn mergeDebugAssets
processDebugResources.dependsOn bundleDebugJsAndAssets
runBefore('processArmeabi-v7aDebugResources', bundleDebugJsAndAssets)
runBefore('processX86DebugResources', bundleDebugJsAndAssets)
runBefore('processUniversalDebugResources', bundleDebugJsAndAssets)
runBefore('processDebugResources', bundleDebugJsAndAssets)
// hook bundleReleaseJsAndAssets into the android build process // hook bundleReleaseJsAndAssets into the android build process
bundleReleaseJsAndAssets.dependsOn mergeReleaseResources bundleReleaseJsAndAssets.dependsOn mergeReleaseResources
bundleReleaseJsAndAssets.dependsOn mergeReleaseAssets bundleReleaseJsAndAssets.dependsOn mergeReleaseAssets
processReleaseResources.dependsOn bundleReleaseJsAndAssets
runBefore('processArmeabi-v7aReleaseResources', bundleReleaseJsAndAssets)
runBefore('processX86ReleaseResources', bundleReleaseJsAndAssets)
runBefore('processUniversalReleaseResources', bundleReleaseJsAndAssets)
runBefore('processReleaseResources', bundleReleaseJsAndAssets)
} }

View File

@ -1,80 +1,41 @@
package com.videoplayer; package com.videoplayer;
import android.app.Activity; import com.facebook.react.ReactActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import com.brentvatne.react.ReactVideoPackage; import com.brentvatne.react.ReactVideoPackage;
import com.facebook.react.LifecycleState; import com.facebook.react.ReactPackage;
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.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler { import java.util.Arrays;
import java.util.List;
private ReactInstanceManager mReactInstanceManager; public class MainActivity extends ReactActivity {
private ReactRootView mReactRootView;
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected String getMainComponentName() {
super.onCreate(savedInstanceState); return "VideoPlayer";
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new MainReactPackage())
.addPackage(new ReactVideoPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, "VideoPlayer", null);
setContentView(mReactRootView);
} }
/**
* Returns whether dev mode should be enabled.
* This enables e.g. the dev menu.
*/
@Override @Override
public boolean onKeyUp(int keyCode, KeyEvent event) { protected boolean getUseDeveloperSupport() {
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) { return BuildConfig.DEBUG;
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
} }
/**
* A list of packages used by the app. If the app uses additional views
* or modules besides the default ones, add more packages here.
*/
@Override @Override
public void onBackPressed() { protected List<ReactPackage> getPackages() {
if (mReactInstanceManager != null) { return Arrays.<ReactPackage>asList(
mReactInstanceManager.onBackPressed(); new MainReactPackage(),
} else { new ReactVideoPackage());
super.onBackPressed();
}
}
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
@Override
protected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onResume(this, this);
}
} }
} }

View File

@ -1,5 +1,7 @@
rootProject.name = 'VideoPlayer' rootProject.name = 'VideoPlayer'
include ':app' include ':app'
include ':react-native-video'
project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android')
include ':RCTVideo', ':app' include ':RCTVideo', ':app'
project(':RCTVideo').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android') project(':RCTVideo').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android')

View File

@ -1,35 +1,39 @@
'use strict'; 'use strict';
var React = require('react-native'); import React, {
var {
AppRegistry, AppRegistry,
Component,
StyleSheet, StyleSheet,
Text, Text,
View,
TouchableOpacity, TouchableOpacity,
} = React; View,
} from 'react-native';
var Video = require('react-native-video'); import Video from 'react-native-video';
var VideoPlayer = React.createClass({ class VideoPlayer extends Component {
getInitialState() { constructor(props) {
return { super(props);
rate: 1, this.onLoad = this.onLoad.bind(this);
volume: 1, this.onProgress = this.onProgress.bind(this);
muted: false, }
resizeMode: 'contain',
duration: 0.0, state = {
currentTime: 0.0, rate: 1,
} volume: 1,
}, muted: false,
resizeMode: 'contain',
duration: 0.0,
currentTime: 0.0,
};
onLoad(data) { onLoad(data) {
this.setState({duration: data.duration}); this.setState({duration: data.duration});
}, }
onProgress(data) { onProgress(data) {
this.setState({currentTime: data.currentTime}); this.setState({currentTime: data.currentTime});
}, }
getCurrentTimePercentage() { getCurrentTimePercentage() {
if (this.state.currentTime > 0) { if (this.state.currentTime > 0) {
@ -37,10 +41,10 @@ var VideoPlayer = React.createClass({
} else { } else {
return 0; return 0;
} }
}, }
renderRateControl(rate) { renderRateControl(rate) {
var isSelected = (this.state.rate == rate); const isSelected = (this.state.rate == rate);
return ( return (
<TouchableOpacity onPress={() => { this.setState({rate: rate}) }}> <TouchableOpacity onPress={() => { this.setState({rate: rate}) }}>
@ -49,10 +53,10 @@ var VideoPlayer = React.createClass({
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
) )
}, }
renderResizeModeControl(resizeMode) { renderResizeModeControl(resizeMode) {
var isSelected = (this.state.resizeMode == resizeMode); const isSelected = (this.state.resizeMode == resizeMode);
return ( return (
<TouchableOpacity onPress={() => { this.setState({resizeMode: resizeMode}) }}> <TouchableOpacity onPress={() => { this.setState({resizeMode: resizeMode}) }}>
@ -61,10 +65,10 @@ var VideoPlayer = React.createClass({
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
) )
}, }
renderVolumeControl(volume) { renderVolumeControl(volume) {
var isSelected = (this.state.volume == volume); const isSelected = (this.state.volume == volume);
return ( return (
<TouchableOpacity onPress={() => { this.setState({volume: volume}) }}> <TouchableOpacity onPress={() => { this.setState({volume: volume}) }}>
@ -73,11 +77,11 @@ var VideoPlayer = React.createClass({
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
) )
}, }
render() { render() {
var flexCompleted = this.getCurrentTimePercentage() * 100; const flexCompleted = this.getCurrentTimePercentage() * 100;
var flexRemaining = (1 - this.getCurrentTimePercentage()) * 100; const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
return ( return (
<View style={styles.container}> <View style={styles.container}>
@ -128,10 +132,10 @@ var VideoPlayer = React.createClass({
</View> </View>
); );
} }
}); }
var styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',

View File

@ -1,39 +1,42 @@
'use strict'; 'use strict';
var React = require('react-native'); import React, {
var { AlertIOS,
AppRegistry, AppRegistry,
Component,
StyleSheet, StyleSheet,
Text, Text,
View,
TouchableOpacity, TouchableOpacity,
AlertIOS, View,
} = React; } from 'react-native';
var Video = require('react-native-video'); import Video from 'react-native-video';
var VideoPlayer = React.createClass({ class VideoPlayer extends Component {
getInitialState() { constructor(props) {
return { super(props);
rate: 1, this.onLoad = this.onLoad.bind(this);
volume: 1, this.onProgress = this.onProgress.bind(this);
muted: false, }
resizeMode: 'contain', state = {
duration: 0.0, rate: 1,
currentTime: 0.0, volume: 1,
controls: false, muted: false,
paused: true, resizeMode: 'contain',
skin: 'custom' duration: 0.0,
} currentTime: 0.0,
}, controls: false,
paused: true,
skin: 'custom'
};
onLoad(data) { onLoad(data) {
this.setState({duration: data.duration}); this.setState({duration: data.duration});
}, }
onProgress(data) { onProgress(data) {
this.setState({currentTime: data.currentTime}); this.setState({currentTime: data.currentTime});
}, }
getCurrentTimePercentage() { getCurrentTimePercentage() {
if (this.state.currentTime > 0) { if (this.state.currentTime > 0) {
@ -41,11 +44,11 @@ var VideoPlayer = React.createClass({
} else { } else {
return 0; return 0;
} }
}, }
renderSkinControl(skin) { renderSkinControl(skin) {
var isSelected = this.state.skin == skin; const isSelected = this.state.skin == skin;
var selectControls = skin == 'native' || skin == 'embed'; const selectControls = skin == 'native' || skin == 'embed';
return ( return (
<TouchableOpacity onPress={() => { this.setState({ <TouchableOpacity onPress={() => { this.setState({
controls: selectControls, controls: selectControls,
@ -56,10 +59,10 @@ var VideoPlayer = React.createClass({
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
); );
}, }
renderRateControl(rate) { renderRateControl(rate) {
var isSelected = (this.state.rate == rate); const isSelected = (this.state.rate == rate);
return ( return (
<TouchableOpacity onPress={() => { this.setState({rate: rate}) }}> <TouchableOpacity onPress={() => { this.setState({rate: rate}) }}>
@ -68,10 +71,10 @@ var VideoPlayer = React.createClass({
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
) )
}, }
renderResizeModeControl(resizeMode) { renderResizeModeControl(resizeMode) {
var isSelected = (this.state.resizeMode == resizeMode); const isSelected = (this.state.resizeMode == resizeMode);
return ( return (
<TouchableOpacity onPress={() => { this.setState({resizeMode: resizeMode}) }}> <TouchableOpacity onPress={() => { this.setState({resizeMode: resizeMode}) }}>
@ -80,10 +83,10 @@ var VideoPlayer = React.createClass({
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
) )
}, }
renderVolumeControl(volume) { renderVolumeControl(volume) {
var isSelected = (this.state.volume == volume); const isSelected = (this.state.volume == volume);
return ( return (
<TouchableOpacity onPress={() => { this.setState({volume: volume}) }}> <TouchableOpacity onPress={() => { this.setState({volume: volume}) }}>
@ -92,11 +95,11 @@ var VideoPlayer = React.createClass({
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
) )
}, }
renderCustomSkin() { renderCustomSkin() {
var flexCompleted = this.getCurrentTimePercentage() * 100; const flexCompleted = this.getCurrentTimePercentage() * 100;
var flexRemaining = (1 - this.getCurrentTimePercentage()) * 100; const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
return ( return (
<View style={styles.container}> <View style={styles.container}>
@ -151,10 +154,10 @@ var VideoPlayer = React.createClass({
</View> </View>
</View> </View>
); );
}, }
renderNativeSkin() { renderNativeSkin() {
var videoStyle = this.state.skin == 'embed' ? styles.nativeVideoControls : styles.fullScreen; const videoStyle = this.state.skin == 'embed' ? styles.nativeVideoControls : styles.fullScreen;
return ( return (
<View style={styles.container}> <View style={styles.container}>
<View style={styles.fullScreen}> <View style={styles.fullScreen}>
@ -202,16 +205,14 @@ var VideoPlayer = React.createClass({
</View> </View>
); );
}, }
render() { render() {
return this.state.controls ? this.renderNativeSkin() : this.renderCustomSkin(); return this.state.controls ? this.renderNativeSkin() : this.renderCustomSkin();
} }
}
}); const styles = StyleSheet.create({
var styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',

View File

@ -6,7 +6,7 @@
"start": "node_modules/react-native/packager/packager.sh" "start": "node_modules/react-native/packager/packager.sh"
}, },
"dependencies": { "dependencies": {
"react-native": "0.18.1", "react-native": "^0.19.0",
"react-native-video": "../../" "react-native-video": "../../"
} }
} }