├── .gitattributes
├── android
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── easy
│ │ └── ijkplayer
│ │ ├── RNEasyIjkplayerPackage.java
│ │ ├── RNEasyIjkplayerModule.java
│ │ ├── RNEasyIjkplayerViewManager.java
│ │ └── RNEasyIjkplayerView.java
├── .settings
│ └── org.eclipse.buildship.core.prefs
├── .project
├── build.gradle
├── gradlew.bat
└── gradlew
├── ios
├── RNEasyIjkplayer.xcworkspace
│ └── contents.xcworkspacedata
├── RNEasyIjkplayerViewManager.h
├── RNEasyIjkplayer.podspec
├── RNEasyIjkplayerView.h
├── RNEasyIjkplayer.xcodeproj
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── RNEasyIjkplayer.xcscheme
│ └── project.pbxproj
├── RNEasyIjkplayerViewManager.m
└── RNEasyIjkplayerView.m
├── .gitignore
├── package.json
├── README.md
└── index.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itgou/react-native-easy-ijkplayer/HEAD/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ios/RNEasyIjkplayer.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 |
3 |
5 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Nov 09 10:34:14 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
7 |
--------------------------------------------------------------------------------
/android/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | arguments=
2 | auto.sync=false
3 | build.scans.enabled=false
4 | connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(5.6.1))
5 | connection.project.dir=
6 | eclipse.preferences.version=1
7 | gradle.user.home=
8 | java.home=
9 | jvm.arguments=
10 | offline.mode=false
11 | override.workspace.settings=true
12 | show.console.view=true
13 | show.executions.view=true
14 |
--------------------------------------------------------------------------------
/ios/RNEasyIjkplayerViewManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // RNEasyIjkplayerViewManager.h
3 | // RNEasyIjkplayer
4 | //
5 | // Created by lj on 2019/11/10.
6 | // Copyright © 2019 Facebook. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "RNEasyIjkplayerView.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface RNEasyIjkplayerViewManager : RCTViewManager
15 |
16 | @end
17 |
18 | NS_ASSUME_NONNULL_END
19 |
--------------------------------------------------------------------------------
/android/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | android
4 | Project android created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.buildship.core.gradleprojectbuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.buildship.core.gradleprojectnature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 |
3 | # OSX
4 | #
5 | .DS_Store
6 |
7 | # node.js
8 | #
9 | node_modules/
10 | npm-debug.log
11 | yarn-error.log
12 |
13 |
14 | # Xcode
15 | #
16 | build/
17 | *.pbxuser
18 | !default.pbxuser
19 | *.mode1v3
20 | !default.mode1v3
21 | *.mode2v3
22 | !default.mode2v3
23 | *.perspectivev3
24 | !default.perspectivev3
25 | xcuserdata
26 | *.xccheckout
27 | *.moved-aside
28 | DerivedData
29 | *.hmap
30 | *.ipa
31 | *.xcuserstate
32 | project.xcworkspace
33 | ios/IJKMediaFramework.framework
34 |
35 |
36 | # Android/IntelliJ
37 | #
38 | build/
39 | .idea
40 | .gradle
41 | local.properties
42 | *.iml
43 |
44 | # BUCK
45 | buck-out/
46 | \.buckd/
47 | *.keystore
48 |
49 |
50 |
--------------------------------------------------------------------------------
/ios/RNEasyIjkplayer.podspec:
--------------------------------------------------------------------------------
1 |
2 | Pod::Spec.new do |s|
3 | s.name = "RNEasyIjkplayer"
4 | s.version = "1.0.0"
5 | s.summary = "RNEasyIjkplayer"
6 | s.description = <<-DESC
7 | RNEasyIjkplayer
8 | DESC
9 | s.homepage = ""
10 | s.license = "MIT"
11 | # s.license = { :type => "MIT", :file => "FILE_LICENSE" }
12 | s.author = { "author" => "author@domain.cn" }
13 | s.platform = :ios, "7.0"
14 | s.source = { :git => "https://github.com/author/RNEasyIjkplayer.git", :tag => "master" }
15 | s.source_files = "RNEasyIjkplayer/**/*.{h,m}"
16 | s.requires_arc = true
17 |
18 |
19 | s.dependency "React"
20 | #s.dependency "others"
21 |
22 | end
23 |
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-easy-ijkplayer",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [
10 | "react-native",
11 | "ijkplayer",
12 | "Android",
13 | "ios",
14 | "rtmp",
15 | "rtsp",
16 | "stream player"
17 | ],
18 | "author": {
19 | "name": "Jason",
20 | "email": "412300204@qq.com"
21 | },
22 | "license": "BSD",
23 | "repository": {
24 | "type": "git",
25 | "url": "https://github.com/itgou/react-native-easy-ijkplayer"
26 | },
27 | "peerDependencies": {
28 | "react": "^16.2.0",
29 | "react-native": "^0.41.2"
30 | },
31 | "dependencies": {
32 | "prop-types": "15.6.0"
33 | }
34 | }
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 |
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.1'
9 | }
10 | }
11 |
12 | apply plugin: 'com.android.library'
13 |
14 | android {
15 | compileSdkVersion 23
16 | buildToolsVersion "23.0.1"
17 |
18 | defaultConfig {
19 | minSdkVersion 21
20 | targetSdkVersion 22
21 | versionCode 1
22 | versionName "1.0"
23 | }
24 | lintOptions {
25 | abortOnError false
26 | }
27 | }
28 |
29 | repositories {
30 | mavenCentral()
31 | }
32 |
33 | dependencies {
34 | compile 'com.facebook.react:react-native:+'
35 | implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
36 | implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'
37 | implementation 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.8'
38 | implementation 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.8'
39 | }
40 |
--------------------------------------------------------------------------------
/android/src/main/java/com/easy/ijkplayer/RNEasyIjkplayerPackage.java:
--------------------------------------------------------------------------------
1 |
2 | package com.easy.ijkplayer;
3 |
4 | import java.util.Arrays;
5 | import java.util.Collections;
6 | import java.util.List;
7 |
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.bridge.NativeModule;
10 | import com.facebook.react.bridge.ReactApplicationContext;
11 | import com.facebook.react.uimanager.ViewManager;
12 | import com.facebook.react.bridge.JavaScriptModule;
13 | public class RNEasyIjkplayerPackage implements ReactPackage {
14 | @Override
15 | public List createNativeModules(ReactApplicationContext reactContext) {
16 | return Arrays.asList(new RNEasyIjkplayerModule(reactContext));
17 | }
18 |
19 | // Deprecated from RN 0.47
20 | public List> createJSModules() {
21 | return Collections.emptyList();
22 | }
23 |
24 | @Override
25 | public List createViewManagers(ReactApplicationContext reactContext) {
26 | return Arrays.asList(
27 | new RNEasyIjkplayerViewManager()
28 | );
29 | }
30 | }
--------------------------------------------------------------------------------
/ios/RNEasyIjkplayerView.h:
--------------------------------------------------------------------------------
1 | //
2 | // RNEasyIjkplayerView.h
3 | // RNEasyIjkplayer
4 | //
5 | // Created by lj on 2019/11/10.
6 | // Copyright © 2019 Facebook. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "React/RCTComponent.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface RNEasyIjkplayerView : UIView
15 |
16 | @property(nonatomic,strong, readwrite) NSURL *url;
17 | @property(nonatomic,strong, readwrite) NSNumber *autoPlay;
18 | @property(nonatomic,strong, readwrite) NSNumber *duration;
19 | @property(nonatomic,strong, readwrite) NSDictionary *size;
20 |
21 | @property(nonatomic, copy) RCTBubblingEventBlock onPrepared;
22 | @property(nonatomic, copy) RCTBubblingEventBlock onProgressUpdate;
23 | @property(nonatomic, copy) RCTBubblingEventBlock onLoadProgressUpdate;
24 | @property(nonatomic, copy) RCTBubblingEventBlock onInfo;
25 | @property(nonatomic, copy) RCTBubblingEventBlock onError;
26 | @property(nonatomic, copy) RCTBubblingEventBlock onComplete;
27 |
28 | @property (nonatomic, strong) NSThread *progressUpdateThread;
29 | @property (nonatomic, strong) NSTimer *progressUpdateTimer;
30 |
31 | -(instancetype)init;
32 | -(void)play;
33 | -(void)pause;
34 | -(void)stop;
35 | -(void)seekTo:(NSInteger)time;
36 |
37 | @end
38 |
39 | NS_ASSUME_NONNULL_END
40 |
--------------------------------------------------------------------------------
/android/src/main/java/com/easy/ijkplayer/RNEasyIjkplayerModule.java:
--------------------------------------------------------------------------------
1 | package com.easy.ijkplayer;
2 |
3 | import android.util.Log;
4 | import com.facebook.react.bridge.Arguments;
5 | import com.facebook.react.bridge.Callback;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
8 | import com.facebook.react.bridge.ReactMethod;
9 | import com.facebook.react.bridge.WritableMap;
10 |
11 | import javax.annotation.Nonnull;
12 |
13 | public class RNEasyIjkplayerModule extends ReactContextBaseJavaModule {
14 |
15 | public RNEasyIjkplayerModule(ReactApplicationContext reactContext){
16 | super(reactContext);
17 | }
18 |
19 | @Nonnull
20 | @Override
21 | public String getName() {
22 | return "RNEasyIjkplayerView";
23 | }
24 |
25 | /**
26 | * 获取视频时长
27 | * @param reactTag
28 | * @param callback
29 | */
30 | @ReactMethod
31 | public void getDuration(int reactTag, Callback callback){
32 | Log.i("IJKModule",""+RNEasyIjkplayerView.mDuration);
33 | int duration = (int) RNEasyIjkplayerView.mDuration;
34 | Log.i("IJKModule",""+duration);
35 | if(duration != 0 ){
36 | callback.invoke(false,duration);
37 | }else{
38 | callback.invoke(true,duration);
39 | }
40 | }
41 |
42 | /**
43 | * 获取视频的像素尺寸
44 | * @param reactTag
45 | * @param callback
46 | */
47 | @ReactMethod
48 | public void getSize(int reactTag, Callback callback){
49 | WritableMap size = Arguments.createMap();
50 | size.putInt("width",0);
51 | size.putInt("height",0);
52 | if(RNEasyIjkplayerView.size.getInt("width")>0 && RNEasyIjkplayerView.size.getInt("height")>0){
53 | size.putInt("width",RNEasyIjkplayerView.size.getInt("width"));
54 | size.putInt("height",RNEasyIjkplayerView.size.getInt("height"));
55 | callback.invoke(false,size);
56 | }else{
57 | callback.invoke(true,size);
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/ios/RNEasyIjkplayer.xcodeproj/xcshareddata/xcschemes/RNEasyIjkplayer.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/ios/RNEasyIjkplayerViewManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // RNEasyIjkplayerViewManager.m
3 | // RNEasyIjkplayer
4 | //
5 | // Created by lj on 2019/11/10.
6 | // Copyright © 2019 Facebook. All rights reserved.
7 | //
8 |
9 | #import "RNEasyIjkplayerViewManager.h"
10 | #import
11 | #import
12 | #import
13 |
14 | @interface RNEasyIjkplayerViewManager()
15 | @end
16 |
17 | @implementation RNEasyIjkplayerViewManager
18 | RCT_EXPORT_MODULE(RNEasyIjkplayerView)
19 | // RNTMapManager.m
20 |
21 | RCT_EXPORT_VIEW_PROPERTY(onPrepared, RCTBubblingEventBlock)
22 | RCT_EXPORT_VIEW_PROPERTY(onProgressUpdate, RCTBubblingEventBlock)
23 | RCT_EXPORT_VIEW_PROPERTY(onLoadProgressUpdate, RCTBubblingEventBlock)
24 | RCT_EXPORT_VIEW_PROPERTY(onInfo, RCTBubblingEventBlock)
25 | RCT_EXPORT_VIEW_PROPERTY(onComplete, RCTBubblingEventBlock)
26 | RCT_EXPORT_VIEW_PROPERTY(onError, RCTBubblingEventBlock)
27 |
28 | RCT_CUSTOM_VIEW_PROPERTY(options, NSDictionary, RNEasyIjkplayerView){
29 |
30 | NSString *urlString = [json objectForKey:@"url"];
31 | if(urlString){
32 | view.url = [NSURL URLWithString:urlString];
33 | }
34 | view.autoPlay= [json objectForKey:@"autoPlay"] ? [json objectForKey:@"autoPlay"] : @0 ;
35 |
36 | }
37 |
38 | RCT_EXPORT_METHOD(play:(nonnull NSNumber*) reactTag){
39 | [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) {
40 | RNEasyIjkplayerView *view =(RNEasyIjkplayerView *) viewRegistry[reactTag];
41 | if (!view || ![view isKindOfClass:[RNEasyIjkplayerView class]]) {
42 | RCTLogError(@"Cannot find NativeView with tag #%@", reactTag);
43 | return;
44 | }
45 | [view play];
46 | }];
47 | }
48 |
49 | RCT_EXPORT_METHOD(pause:(nonnull NSNumber*) reactTag){
50 | [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) {
51 | RNEasyIjkplayerView *view = (RNEasyIjkplayerView *) viewRegistry[reactTag];
52 | if (!view || ![view isKindOfClass:[RNEasyIjkplayerView class]]) {
53 | RCTLogError(@"Cannot find NativeView with tag #%@", reactTag);
54 | return;
55 | }
56 | [view pause];
57 | }];
58 | }
59 |
60 | RCT_EXPORT_METHOD(stop:(nonnull NSNumber*) reactTag){
61 | [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) {
62 | RNEasyIjkplayerView *view =(RNEasyIjkplayerView *) viewRegistry[reactTag];
63 | if (!view || ![view isKindOfClass:[RNEasyIjkplayerView class]]) {
64 | RCTLogError(@"Cannot find NativeView with tag #%@", reactTag);
65 | return;
66 | }
67 | [view stop];
68 | }];
69 | }
70 |
71 |
72 | RCT_EXPORT_METHOD(seekTo:(nonnull NSNumber*) reactTag time:(NSInteger) time ){
73 | [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) {
74 | RNEasyIjkplayerView *view = (RNEasyIjkplayerView *) viewRegistry[reactTag];
75 | if (!view || ![view isKindOfClass:[RNEasyIjkplayerView class]]) {
76 | RCTLogError(@"Cannot find NativeView with tag #%@", reactTag);
77 | return;
78 | }
79 | if(time){
80 | [view seekTo:time];
81 | }
82 | }];
83 | }
84 |
85 | RCT_EXPORT_METHOD(getDuration:(nonnull NSNumber*) reactTag callback:(RCTResponseSenderBlock)callback){
86 | [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) {
87 | RNEasyIjkplayerView *view = (RNEasyIjkplayerView *)viewRegistry[reactTag];
88 | if (!view || ![view isKindOfClass:[RNEasyIjkplayerView class]]) {
89 | RCTLogError(@"Cannot find NativeView with tag #%@", reactTag);
90 | return;
91 | }
92 | if(view.duration){
93 | callback(@[@NO,view.duration]);
94 | }else{
95 | callback(@[@YES]);
96 | }
97 |
98 | }];
99 | }
100 |
101 | RCT_EXPORT_METHOD(getSize:(nonnull NSNumber*) reactTag callback:(RCTResponseSenderBlock)callback){
102 | [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) {
103 | RNEasyIjkplayerView *view = (RNEasyIjkplayerView *)viewRegistry[reactTag];
104 | if (!view || ![view isKindOfClass:[RNEasyIjkplayerView class]]) {
105 | RCTLogError(@"Cannot find NativeView with tag #%@", reactTag);
106 | return;
107 | }
108 | if(view.size){
109 | callback(@[@NO,view.size]);
110 | }else{
111 | callback(@[@YES]);
112 | }
113 |
114 | }];
115 | }
116 |
117 | -(UIView *)view{
118 |
119 | //直播视频
120 | // http://img.elleshop.com.cn/media/product/14994134515891.mp4
121 | // http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8
122 | RNEasyIjkplayerView *view = [[RNEasyIjkplayerView alloc]init];
123 |
124 | return view;
125 | }
126 |
127 | @end
128 |
--------------------------------------------------------------------------------
/android/src/main/java/com/easy/ijkplayer/RNEasyIjkplayerViewManager.java:
--------------------------------------------------------------------------------
1 | package com.easy.ijkplayer;
2 |
3 | import android.util.Log;
4 |
5 | import com.facebook.react.bridge.Callback;
6 | import com.facebook.react.bridge.ReactMethod;
7 | import com.facebook.react.bridge.ReadableArray;
8 | import com.facebook.react.bridge.ReadableMap;
9 | import com.facebook.react.common.MapBuilder;
10 | import com.facebook.react.uimanager.SimpleViewManager;
11 | import com.facebook.react.uimanager.ThemedReactContext;
12 | import com.facebook.react.uimanager.annotations.ReactProp;
13 |
14 | import java.util.Map;
15 |
16 | import javax.annotation.Nonnull;
17 | import javax.annotation.Nullable;
18 |
19 |
20 | public class RNEasyIjkplayerViewManager extends SimpleViewManager {
21 | private static final String TAG = "RNEasyIjkplayerViewManager";
22 | private final String REACT_CLASS = "RNEasyIjkplayerView";
23 | private static final int COMMAND_PAUSE_ID = 1;
24 | private static final String COMMAND_PAUSE_NAME = "pause";
25 | private static final int COMMAND_PLAY_ID = 2;
26 | private static final String COMMAND_PLAY_NAME = "play";
27 | private static final int COMMAND_STOP_ID = 3;
28 | private static final String COMMAND_STOP_NAME = "stop";
29 | private static final int COMMAND_SEEK_TO_ID = 4;
30 | private static final String COMMAND_SEEK_TO_NAME = "seekTo";
31 |
32 | @Nonnull
33 | @Override
34 | public String getName() {
35 | return REACT_CLASS;
36 | }
37 |
38 | @Nonnull
39 | @Override
40 | protected RNEasyIjkplayerView createViewInstance(@Nonnull ThemedReactContext reactContext) {
41 | RNEasyIjkplayerView ijkPlayer = new RNEasyIjkplayerView(reactContext);
42 | return ijkPlayer;
43 | }
44 |
45 | // @ReactProp(name = "url")
46 | // public void setUrl(RNEasyIjkplayerView ijkPlayer, String url) {
47 | // Log.i(TAG, "url:" + url);
48 | // if (ijkPlayer.isPlaying()) {
49 | // ijkPlayer.restart(url);
50 | // } else {
51 | // if (!url.equals("")) {
52 | // ijkPlayer.setDataSource(url);
53 | // }
54 | // }
55 | // }
56 |
57 | @ReactProp(name = "options")
58 | public void setOptions(RNEasyIjkplayerView ijkPlayer, ReadableMap options) {
59 | /* auto start */
60 | int autoPlay = 0;
61 | if(options.hasKey("autoPlay")){
62 | autoPlay = options.getInt("autoPlay");
63 | Log.i(TAG,"autoPlay::"+autoPlay);
64 | if(autoPlay == 1){
65 | ijkPlayer.setMAutoPlay(1);
66 | }
67 | }
68 | /* url */
69 | if(options.hasKey("url")){
70 | String url = options.getString("url");
71 | Log.i(TAG,url);
72 | if (ijkPlayer.isPlaying()) {
73 | Log.i(TAG,"isPlaying");
74 | ijkPlayer.restart(url);
75 | } else {
76 | if (!url.equals("")) {
77 | ijkPlayer.setDataSource(url);
78 | if(autoPlay == 1){
79 | ijkPlayer.start();
80 | }
81 | }
82 | }
83 | }
84 | }
85 |
86 |
87 | @javax.annotation.Nullable
88 | @Override
89 | public Map getCommandsMap() {
90 | return MapBuilder.of(
91 | COMMAND_PAUSE_NAME, COMMAND_PAUSE_ID,
92 | COMMAND_PLAY_NAME, COMMAND_PLAY_ID,
93 | COMMAND_STOP_NAME, COMMAND_STOP_ID,
94 | COMMAND_SEEK_TO_NAME, COMMAND_SEEK_TO_ID
95 | );
96 | }
97 |
98 | @Override
99 | public void receiveCommand(@Nonnull RNEasyIjkplayerView root, int commandId, @javax.annotation.Nullable ReadableArray args) {
100 | switch (commandId) {
101 | case COMMAND_PAUSE_ID:
102 | root.pause();
103 | break;
104 | case COMMAND_PLAY_ID:
105 | root.start();
106 | break;
107 | case COMMAND_STOP_ID:
108 | root.stop();
109 | break;
110 | case COMMAND_SEEK_TO_ID:
111 | int progress = args.getInt(0);
112 | Log.i(TAG, "seek Progress:" + progress);
113 | root.seekTo(progress * 1000);
114 | break;
115 | default:
116 | break;
117 | }
118 |
119 | }
120 |
121 | @Nullable
122 | @Override
123 | public Map getExportedCustomBubblingEventTypeConstants() {
124 | return MapBuilder.builder()
125 | .put(
126 | "onComplete",
127 | MapBuilder.of(
128 | "phasedRegistrationNames",
129 | MapBuilder.of("bubbled", "onComplete")))
130 | .put(
131 | "onInfo",
132 | MapBuilder.of(
133 | "phasedRegistrationNames",
134 | MapBuilder.of("bubbled", "onInfo")))
135 | .put(
136 | "onError",
137 | MapBuilder.of(
138 | "phasedRegistrationNames",
139 | MapBuilder.of("bubbled", "onError")))
140 | .put(
141 | "onPrepared",
142 | MapBuilder.of(
143 | "phasedRegistrationNames",
144 | MapBuilder.of("bubbled", "onPrepared")))
145 | .put(
146 | "onProgressUpdate",
147 | MapBuilder.of(
148 | "phasedRegistrationNames",
149 | MapBuilder.of("bubbled", "onProgressUpdate")))
150 | .build();
151 | }
152 |
153 | }
154 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # react-native-easy-ijkplayer
3 |
4 | ## Getting started
5 |
6 | `$ npm install react-native-easy-ijkplayer --save`
7 |
8 | ### Mostly automatic installation
9 |
10 | `$ react-native link react-native-easy-ijkplayer`
11 |
12 | ### Manual installation
13 |
14 |
15 | #### iOS
16 |
17 | 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]`
18 | 2. Go to `node_modules` ➜ `react-native-easy-ijkplayer` and add `RNEasyIjkplayer.xcodeproj`
19 | 3. In XCode, in the project navigator, select your project. Add `libRNEasyIjkplayer.a` to your project's `Build Phases` ➜ `Link Binary With Libraries`
20 | 4. Run your project (`Cmd+R`)<
21 |
22 | #### Android
23 |
24 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java`
25 | - Add `import com.easy.ijkplayer.RNEasyIjkplayerPackage;` to the imports at the top of the file
26 | - Add `new RNEasyIjkplayerPackage()` to the list returned by the `getPackages()` method
27 | 2. Append the following lines to `android/settings.gradle`:
28 | ```
29 | include ':react-native-easy-ijkplayer'
30 | project(':react-native-easy-ijkplayer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-easy-ijkplayer/android')
31 | ```
32 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
33 | ```
34 | compile project(':react-native-easy-ijkplayer')
35 | ```
36 |
37 | ### Demo Reposity: https://github.com/itgou/react-native-easy-ijkplayer-demo
38 |
39 | ### Extra Setting in Android
40 | 1. For resolving Error: minSdkVersion 16 cannot be smaller than version 21 declared in library [:react-native-easy-ijkplayer]
41 |
42 | Open up `android/build.gradle`
43 | ```
44 | buildscript {
45 | ext {
46 | buildToolsVersion = "28.0.3"
47 | - minSdkVersion = 16
48 | + minSdkVersion = 21
49 | compileSdkVersion = 28
50 | targetSdkVersion = 28
51 | supportLibVersion = "28.0.0"
52 |
53 | ```
54 | 2. For resolving Bug about android:allowBackup
55 |
56 | Open up `android/app/src/main/AndroidManifest.xml`
57 | ```
58 |
61 |
62 |
63 | android:icon="@mipmap/ic_launcher"
64 | android:roundIcon="@mipmap/ic_launcher_round"
65 | android:allowBackup="false"
66 | + tools:replace="android:allowBackup"
67 | android:theme="@style/AppTheme">
68 | {
110 | this.RNTIJKPlayerRef.play()
111 | }
112 |
113 | _pause = () => {
114 | this.RNTIJKPlayerRef.pause()
115 | }
116 |
117 | _stop = () => {
118 | this.RNTIJKPlayerRef.stop()
119 | }
120 |
121 | _seekTo = () => {
122 | this.RNTIJKPlayerRef.seekTo(60)
123 | }
124 | _getDuration = () => {
125 | this.RNTIJKPlayerRef.getDuration((err, duration) => {
126 | console.log(err)
127 | console.log(duration)
128 | })
129 | }
130 |
131 | _getSize = () => {
132 | this.RNTIJKPlayerRef.getSize((err, size) => {
133 | console.log(err)
134 | console.log(size)
135 | })
136 | }
137 | _onPrepared = (event) => {
138 | this.setState({showIndicator:false})
139 | }
140 | _onLoadProgressUpdate = ({nativeEvent: {loadProgress}}) => {
141 | }
142 |
143 | _onProgressUpdate = ( progress) => {
144 | console.log('progress',progress)
145 | }
146 |
147 | _onInfo = (info) => {
148 | }
149 |
150 | _onError = (error) => {
151 | }
152 |
153 | _onComplete = () => {
154 | }
155 |
156 | render() {
157 | const {showIndicator}= this.state
158 | return (
159 | <>
160 | this.RNTIJKPlayerRef = ref}
162 | options={{
163 | url:"http://img.elleshop.com.cn/media/product/14994134515891.mp4",
164 | autoPlay: 1,
165 | }}
166 | showIndicator={showIndicator}
167 | onComplete={this._onComplete}
168 | onPrepared={this._onPrepared}
169 | onError={this._onError}
170 | onInfo={this._onInfo}
171 | onProgressUpdate={this._onProgressUpdate}
172 | />
173 |
177 |
181 |
185 |
189 |
193 |
197 | >
198 | )
199 | }
200 | }
201 |
202 | ```
203 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import {
3 | View, Dimensions,
4 | StyleSheet, ActivityIndicator,
5 | requireNativeComponent,
6 | UIManager, findNodeHandle,
7 | NativeModules, NativeEventEmitter
8 | } from "react-native"
9 | import PropTypes from 'prop-types'
10 |
11 | const defaultIndicatorSize = 16
12 | const { width: D_WIDTH } = Dimensions.get('window')
13 |
14 | class IJKPlayerView extends Component {
15 | static propTypes = {
16 | showIndicator: PropTypes.bool,
17 | options: PropTypes.object,
18 | onComplete: PropTypes.func,
19 | onPrepared: PropTypes.func,
20 | onError: PropTypes.func,
21 | onInfo: PropTypes.func,
22 | onProgressUpdate: PropTypes.func,
23 | onLoadProgressUpdate: PropTypes.func,
24 | }
25 | constructor(props) {
26 | super(props)
27 | this.state = {
28 | indicatorLeft: null,
29 | indicatorTop: null,
30 | showIndicator: false,
31 | }
32 | }
33 |
34 | static getDerivedStateFromProps(props, state) {
35 | const { style,showIndicator } = props
36 | let width, height
37 | if (style) {
38 | width = style.width
39 | height = style.height
40 | }
41 | let videoWrapperWidth = width || D_WIDTH
42 | let videoWrapperHeight = height || D_WIDTH * 0.7
43 | const indicatorLeft = videoWrapperWidth / 2 - defaultIndicatorSize / 2
44 | const indicatorTop = videoWrapperHeight / 2 - defaultIndicatorSize / 2
45 | if (
46 | indicatorLeft !== state.indicatorLeft
47 | || indicatorTop !== state.indicatorTop
48 | || showIndicator !== state.showIndicator
49 | ) {
50 | return {
51 | indicatorLeft,
52 | indicatorTop,
53 | videoWrapperWidth,
54 | videoWrapperHeight,
55 | showIndicator,
56 | }
57 | }
58 | return null
59 | }
60 |
61 | play = () => {
62 | console.log('play')
63 | UIManager.dispatchViewManagerCommand(
64 | findNodeHandle(this.ref),
65 | UIManager.getViewManagerConfig('RNEasyIjkplayerView').Commands.play,
66 | null,
67 | )
68 | }
69 |
70 | pause = () => {
71 | console.log('pause')
72 | UIManager.dispatchViewManagerCommand(
73 | findNodeHandle(this.ref),
74 | UIManager.getViewManagerConfig('RNEasyIjkplayerView').Commands.pause,
75 | null,
76 | )
77 | }
78 |
79 | stop = () => {
80 | console.log('pause')
81 | UIManager.dispatchViewManagerCommand(
82 | findNodeHandle(this.ref),
83 | UIManager.getViewManagerConfig('RNEasyIjkplayerView').Commands.stop,
84 | null,
85 | )
86 | }
87 |
88 | seekTo = (time) => {
89 | UIManager.dispatchViewManagerCommand(
90 | findNodeHandle(this.ref),
91 | UIManager.getViewManagerConfig('RNEasyIjkplayerView').Commands.seekTo,
92 | [time],
93 | )
94 | }
95 |
96 | /**
97 | *
98 | * @param callback
99 | */
100 | getDuration = (callback) => {
101 | NativeModules.RNEasyIjkplayerView.getDuration(findNodeHandle(this.ref), callback)
102 | }
103 |
104 | getSize = (callback) => {
105 | NativeModules.RNEasyIjkplayerView.getSize(findNodeHandle(this.ref), callback)
106 | }
107 |
108 | _onProgressUpdate = ({ nativeEvent: { progress } }) => {
109 | const { onProgressUpdate } = this.props
110 | onProgressUpdate && onProgressUpdate(progress)
111 | }
112 |
113 | _onPrepared = (event) => {
114 | console.log('on prepared')
115 | const { onPrepared } = this.props
116 | onPrepared && onPrepared(event)
117 |
118 | this.setState({ showIndicator: false })
119 | this.getSize((err, size) => {
120 | if (!err) {
121 | const { videoWrapperHeight, videoWrapperWidth } = this.state
122 | if (size.width <= size.height) { //宽度小于高度, 左右留黑边
123 | let videoWidth = size.width / size.height * videoWrapperHeight
124 | this.setState({
125 | videoWidth,
126 | videoHeight: videoWrapperHeight,
127 | videoLeft: (videoWrapperWidth - videoWidth) / 2,
128 | })
129 | } else { //宽度大于高度, 上下留黑边
130 | let videoHeight = size.height / size.width * videoWrapperWidth
131 | this.setState({
132 | videoHeight,
133 | videoWidth: videoWrapperWidth,
134 | videoTop: (videoWrapperHeight - videoHeight) / 2,
135 | })
136 | }
137 | }
138 | })
139 | }
140 |
141 | _onLoadProgressUpdate = ({ nativeEvent: { loadProgress } }) => {
142 | console.log('on loadProgressUpdate:', loadProgress)
143 | const { onLoadProgressUpdate } = this.props
144 | onLoadProgressUpdate && onLoadProgressUpdate(loadProgress)
145 | }
146 |
147 | _onInfo = ({ nativeEvent: { info } }) => {
148 | console.log('on Info:', info)
149 | const { onInfo } = this.props
150 | onInfo && onInfo(info)
151 | }
152 |
153 | _onError = ({ nativeEvent: { error } }) => {
154 | console.log('on error:', error)
155 | const { onError } = this.props
156 | onError && onError(error)
157 | }
158 |
159 | _onComplete = () => {
160 | const { onComplete } = this.props
161 | onComplete && onComplete()
162 | }
163 |
164 | render() {
165 | const {
166 | videoWrapperWidth, videoWrapperHeight, videoHeight, videoWidth, videoLeft, videoTop,
167 | indicatorLeft, indicatorTop, showIndicator
168 | } = this.state
169 | return
170 | this.ref = ref}
181 | onPrepared={this._onPrepared}
182 | onProgressUpdate={this._onProgressUpdate}
183 | onLoadProgressUpdate={this._onLoadProgressUpdate}
184 | onInfo={this._onInfo}
185 | onError={this._onError}
186 | onComplete={this._onComplete}
187 | />
188 |
193 |
194 | }
195 | }
196 |
197 | const styles = StyleSheet.create({
198 | container: {
199 | position: 'relative',
200 | },
201 | video: {
202 | position: 'absolute',
203 | },
204 | indicator: {
205 | position: 'absolute',
206 | },
207 | })
208 | var IJKPlayer = requireNativeComponent('RNEasyIjkplayerView', IJKPlayerView)
209 |
210 | export default IJKPlayerView
211 |
--------------------------------------------------------------------------------
/android/src/main/java/com/easy/ijkplayer/RNEasyIjkplayerView.java:
--------------------------------------------------------------------------------
1 | package com.easy.ijkplayer;
2 |
3 | import android.os.Handler;
4 | import android.util.Log;
5 | import android.view.SurfaceHolder;
6 | import android.view.SurfaceView;
7 |
8 | import com.facebook.react.bridge.Arguments;
9 | import com.facebook.react.bridge.LifecycleEventListener;
10 | import com.facebook.react.bridge.ReactContext;
11 | import com.facebook.react.bridge.WritableMap;
12 | import com.facebook.react.uimanager.events.RCTEventEmitter;
13 |
14 | import java.io.IOException;
15 |
16 | import tv.danmaku.ijk.media.player.IMediaPlayer;
17 | import tv.danmaku.ijk.media.player.IjkMediaPlayer;
18 |
19 | public class RNEasyIjkplayerView extends SurfaceView implements LifecycleEventListener {
20 |
21 | private static final String TAG = "IJKPlayer";
22 | private static final String NAME_ERROR_EVENT = "onError";
23 | private static final String NAME_INFO_EVENT = "onInfo";
24 | private static final String NAME_COMPLETE_EVENT = "onComplete";
25 | private static final String NAME_PROGRESS_UPDATE_EVENT = "onProgressUpdate";
26 | private static final String NAME_PREPARE_EVENT = "onPrepared";
27 | public static final int PROGRESS_UPDATE_INTERVAL_MILLS = 500;
28 | private IjkMediaPlayer mIjkPlayer;
29 | public static int mDuration;
30 | public static int mAutoPlay = 0;
31 | public static WritableMap size = Arguments.createMap();
32 | private String mCurrUrl;
33 | private boolean mManualPause;
34 | private boolean mManualStop;
35 | private Handler mHandler = new Handler();
36 | private Runnable progressUpdateRunnable = new Runnable() {
37 | @Override
38 | public void run() {
39 | if (mIjkPlayer == null || mDuration == 0) {
40 | return;
41 | }
42 | long currProgress = mIjkPlayer.getCurrentPosition();
43 | int mCurrProgress = (int) Math.ceil((currProgress * 1.0f)/1000);
44 | sendEvent(NAME_PROGRESS_UPDATE_EVENT, "progress", "" + mCurrProgress);
45 | mHandler.postDelayed(progressUpdateRunnable, PROGRESS_UPDATE_INTERVAL_MILLS);
46 | }
47 | };
48 |
49 | public RNEasyIjkplayerView(ReactContext reactContext) {
50 | super(reactContext);
51 | reactContext.addLifecycleEventListener(this);
52 | initIjkMediaPlayer();
53 | initSurfaceView();
54 | initIjkMediaPlayerListener();
55 | }
56 |
57 |
58 | private void initSurfaceView() {
59 | this.getHolder().addCallback(new SurfaceHolder.Callback() {
60 | @Override
61 | public void surfaceCreated(SurfaceHolder holder) {
62 | Log.i(TAG, "surface created");
63 | mIjkPlayer.setDisplay(holder);
64 | }
65 |
66 | @Override
67 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
68 | Log.i(TAG, "surface changed");
69 | }
70 |
71 | @Override
72 | public void surfaceDestroyed(SurfaceHolder holder) {
73 | Log.i(TAG, "surface destroyed");
74 | }
75 | });
76 | }
77 |
78 | private void initIjkMediaPlayer() {
79 | mIjkPlayer = new IjkMediaPlayer();
80 | }
81 |
82 |
83 | private void initIjkMediaPlayerListener() {
84 | mIjkPlayer.setOnPreparedListener(new IMediaPlayer.OnPreparedListener() {
85 | @Override
86 | public void onPrepared(IMediaPlayer iMediaPlayer) {
87 | mDuration = (int)Math.ceil(mIjkPlayer.getDuration()/1000);
88 | mHandler.post(progressUpdateRunnable);
89 | sendEvent(NAME_PREPARE_EVENT, "isPrepare", "1");
90 | }
91 | });
92 |
93 | mIjkPlayer.setOnVideoSizeChangedListener(new IMediaPlayer.OnVideoSizeChangedListener() {
94 | @Override
95 | public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int width, int height, int i2, int i3) {
96 | Log.i(TAG, "width:" + width + " height:" + height);
97 | size.putInt("width", width);
98 | size.putInt("height", height);
99 | float ratioHW = height * 1.0f / width;
100 | }
101 | });
102 |
103 | mIjkPlayer.setOnInfoListener(new IMediaPlayer.OnInfoListener() {
104 | @Override
105 | public boolean onInfo(IMediaPlayer iMediaPlayer, int infoCode, int i1) {
106 | sendEvent(NAME_INFO_EVENT, "code", "" + infoCode);
107 | return false;
108 | }
109 | });
110 |
111 | mIjkPlayer.setOnErrorListener(new IMediaPlayer.OnErrorListener() {
112 | @Override
113 | public boolean onError(IMediaPlayer iMediaPlayer, int errorCode, int i1) {
114 | sendEvent(NAME_ERROR_EVENT, "code", "" + errorCode);
115 | return false;
116 | }
117 | });
118 |
119 | mIjkPlayer.setOnBufferingUpdateListener(new IMediaPlayer.OnBufferingUpdateListener() {
120 | @Override
121 | public void onBufferingUpdate(IMediaPlayer iMediaPlayer, int i) {
122 |
123 | }
124 | });
125 |
126 | mIjkPlayer.setOnCompletionListener(new IMediaPlayer.OnCompletionListener() {
127 | @Override
128 | public void onCompletion(IMediaPlayer iMediaPlayer) {
129 | // mHandler.removeCallbacks(progressUpdateRunnable);
130 | sendEvent(NAME_COMPLETE_EVENT, "complete", "1");
131 | stop();
132 | }
133 | });
134 | }
135 |
136 | private void sendEvent(String eventName, String paramName, String paramValue) {
137 | WritableMap event = Arguments.createMap();
138 | event.putString(paramName, "" + paramValue);
139 | ReactContext reactContext = (ReactContext) getContext();
140 | reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
141 | getId(),
142 | eventName,
143 | event);
144 | }
145 |
146 |
147 | public void setMAutoPlay(int autoPlay) {
148 | mAutoPlay = autoPlay;
149 | }
150 |
151 | public int getMAutoPlay() {
152 | return mAutoPlay;
153 | }
154 |
155 | public void seekTo(long progress) {
156 | if (mIjkPlayer != null) {
157 | mIjkPlayer.seekTo(progress);
158 | }
159 | }
160 |
161 | public void restart(String url) {
162 | stop();
163 | setDataSource(url);
164 | resetSurfaceView();
165 | }
166 |
167 | public void resetSurfaceView() {
168 | this.setVisibility(SurfaceView.GONE);
169 | this.setVisibility(SurfaceView.VISIBLE);
170 | }
171 |
172 | public void start() {
173 | if (mIjkPlayer != null) { //已经初始化
174 | if (mIjkPlayer.isPlaying()) return;
175 | if (mManualPause) { //手动点击暂停
176 | mIjkPlayer.start();
177 | } else { //第一次播放
178 | mIjkPlayer.prepareAsync();
179 | }
180 | resetSurfaceView();
181 | mManualPause = false;
182 | } else {
183 | setDataSource(mCurrUrl);
184 | initIjkMediaPlayerListener();
185 | initSurfaceView();
186 | resetSurfaceView();
187 | mIjkPlayer.prepareAsync();
188 | mManualStop = false;
189 | }
190 | }
191 |
192 | public void pause() {
193 | if (mIjkPlayer != null) {
194 | mIjkPlayer.pause();
195 | mManualPause = true;
196 | mHandler.removeCallbacks(progressUpdateRunnable);
197 | }
198 | }
199 |
200 | public void stop() {
201 | if (mIjkPlayer != null) {
202 | mIjkPlayer.stop();
203 | mIjkPlayer.reset();
204 | mIjkPlayer = null;
205 | mManualStop = true;
206 | mHandler.removeCallbacks(progressUpdateRunnable);
207 | }
208 | }
209 |
210 | public boolean isPlaying() {
211 | if (mIjkPlayer != null) {
212 | return mIjkPlayer.isPlaying();
213 | }
214 | return false;
215 | }
216 |
217 | public void setDataSource(String url) {
218 | try {
219 | if (mIjkPlayer == null) initIjkMediaPlayer();
220 | mIjkPlayer.setDataSource(url);
221 | mCurrUrl = url;
222 | } catch (IOException e) {
223 | e.printStackTrace();
224 | }
225 | }
226 |
227 | @Override
228 | public void onHostResume() {
229 | Log.i(TAG, "onHostResume");
230 | if (!mManualPause) {
231 | Log.i(TAG, "exec start");
232 | mIjkPlayer.start();
233 | mHandler.post(progressUpdateRunnable);
234 | }
235 | }
236 |
237 | @Override
238 | public void onHostPause() {
239 | Log.i(TAG, "onHostPause");
240 | mIjkPlayer.pause();
241 | mHandler.removeCallbacks(progressUpdateRunnable);
242 | }
243 |
244 | @Override
245 | public void onHostDestroy() {
246 | Log.i(TAG, "onHostDestroy");
247 | mIjkPlayer.stop();
248 | mIjkPlayer.release();
249 | mHandler.removeCallbacks(progressUpdateRunnable);
250 | }
251 | }
252 |
--------------------------------------------------------------------------------
/ios/RNEasyIjkplayerView.m:
--------------------------------------------------------------------------------
1 | //
2 | // RNEasyIjkplayerView.m
3 | // RNEasyIjkplayer
4 | //
5 | // Created by lj on 2019/11/10.
6 | // Copyright © 2019 Facebook. All rights reserved.
7 | //
8 |
9 | #import "RNEasyIjkplayerView.h"
10 | #import
11 |
12 | @interface RNEasyIjkplayerView()
13 |
14 | @property (nonatomic, strong) IJKFFMoviePlayerController *player;
15 | @property (nonatomic, strong) UIView *playerView;
16 |
17 | @end
18 |
19 | @implementation RNEasyIjkplayerView
20 |
21 | -(instancetype)init{
22 | self = [super init];
23 | if(self){
24 | self.backgroundColor = [UIColor blackColor];
25 | }
26 | return self;
27 | }
28 |
29 |
30 |
31 | -(void)play{
32 | if(!_player){
33 | if(_url== nil){
34 | NSLog(@"url不能为空");
35 | return;
36 | }
37 |
38 | _player = [[IJKFFMoviePlayerController alloc]initWithContentURL:_url withOptions:nil];
39 |
40 | //获取视频的view层
41 | _playerView = [_player view];
42 | _playerView.frame = self.bounds; //设置视频的宽高
43 | _playerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
44 |
45 | [self insertSubview:_playerView atIndex:1];
46 |
47 | [_player setScalingMode:IJKMPMovieScalingModeAspectFill];
48 | [_player prepareToPlay];
49 |
50 | [self installMovieNotificationObservers];
51 | }else{
52 | if(_player.isPlaying!=YES){
53 | [_player play];
54 | [self startSendProgressUpdate];
55 | }
56 | }
57 |
58 | }
59 |
60 | -(void)startSendProgressUpdate{
61 | __weak __typeof(self) weakSelf = self;
62 | dispatch_async(dispatch_get_global_queue(0, 0), ^{
63 | __strong __typeof(weakSelf) strongSelf = weakSelf;
64 | if (strongSelf) {
65 | strongSelf.progressUpdateThread = [NSThread currentThread];
66 | [strongSelf.progressUpdateThread setName:@"Update Progress Thread"];
67 | strongSelf.progressUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:strongSelf selector:@selector(updateProgressAction) userInfo:nil repeats:YES];
68 | NSRunLoop *runloop = [NSRunLoop currentRunLoop];
69 | [runloop addTimer:strongSelf.progressUpdateTimer forMode:NSDefaultRunLoopMode];
70 | [runloop run];
71 | }
72 | });
73 | }
74 |
75 | -(void)updateProgressAction{
76 |
77 | if(self.onProgressUpdate){
78 | NSTimeInterval playbackTime = _player.currentPlaybackTime;
79 | NSInteger progress = playbackTime;
80 | self.onProgressUpdate(@{@"progress":@(progress)});
81 | }
82 | }
83 |
84 | - (void)cancelUpdateTimerAction{
85 | if (self.progressUpdateTimer) {
86 | [self.progressUpdateTimer invalidate];
87 | self.progressUpdateTimer = nil;
88 | }
89 | }
90 |
91 | - (void)cancelTimer{
92 | if (self.progressUpdateTimer && self.progressUpdateThread) {
93 | [self performSelector:@selector(cancelUpdateTimerAction) onThread:self.progressUpdateThread withObject:nil waitUntilDone:YES];
94 | }
95 | }
96 |
97 | -(void)pause{
98 | if(_player.isPlaying == YES){
99 | [_player pause];
100 | [self cancelTimer];
101 | }
102 | }
103 |
104 | -(void)stop{
105 | if(_player){
106 | [_player stop];
107 | _player = nil;
108 | [self cancelTimer];
109 | [_playerView removeFromSuperview];
110 | _playerView=nil;
111 | }
112 | }
113 |
114 | -(void)seekTo:(NSInteger)time{
115 | _player.currentPlaybackTime = time;
116 | NSLog(@"");
117 | }
118 |
119 | -(void)didMoveToWindow{
120 | if([_autoPlay compare:[NSNumber numberWithInt:1]] == NSOrderedSame){
121 | NSLog(@"");
122 | [self play];
123 | }
124 | }
125 |
126 | -(void)mediaIsPreparedToPlayDidChange:(NSNotification*)notifacation{
127 |
128 | NSTimeInterval time = _player.duration;
129 | NSInteger ttime = time;
130 | _duration = [NSNumber numberWithInteger:ttime];
131 |
132 | CGSize size= _player.naturalSize;
133 | if(size.width && size.height){
134 | _size = @{@"width":@(size.width),@"height":@(size.height)};
135 | }
136 | if(self.onPrepared){
137 | self.onPrepared(@{@"duration":@([_duration intValue]),@"size":_size});
138 | }
139 |
140 | [_player play];
141 |
142 | [self startSendProgressUpdate];
143 |
144 | }
145 |
146 | -(void)mediaPlayerPlaybackDidComplete:(NSNotification*)notifacation{
147 | NSLog(@"Playback did complete");
148 | NSLog(@"%@",notifacation);
149 | [self cancelTimer];
150 | NSNumber *reason = [notifacation.userInfo objectForKey:IJKMPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
151 |
152 | if([reason compare: [NSNumber numberWithInteger:IJKMPMovieFinishReasonPlaybackEnded]] == NSOrderedSame ){
153 | NSLog(@"normal complete");
154 | if(self.onComplete){
155 | self.onComplete(@{});
156 | }
157 | }else if([reason compare: [NSNumber numberWithInteger:IJKMPMovieFinishReasonPlaybackError]] == NSOrderedSame ){
158 | NSLog(@"Error complete");
159 | if(self.onError){
160 | self.onError(@{@"info":@"error complete"});
161 | }
162 | }else if([reason compare: [NSNumber numberWithInteger:IJKMPMovieFinishReasonUserExited]] == NSOrderedSame ){
163 | NSLog(@"user exit complete");
164 | }
165 | if(self.onInfo){
166 | self.onInfo(@{@"info":@"complete"});
167 | }
168 |
169 | }
170 |
171 | -(void)mediaPlayerPlaybackStateDidChange:(NSNotification*)notifacation{
172 | NSLog(@"Playback state change");
173 | // IJKMPMoviePlaybackStateStopped,
174 | // IJKMPMoviePlaybackStatePlaying,
175 | // IJKMPMoviePlaybackStatePaused,
176 | // IJKMPMoviePlaybackStateInterrupted,
177 | // IJKMPMoviePlaybackStateSeekingForward,
178 | // IJKMPMoviePlaybackStateSeekingBackward
179 | if(_player.playbackState == IJKMPMoviePlaybackStatePlaying){
180 | NSLog(@"playback state changed to playing");
181 | if(self.onInfo){
182 | self.onInfo(@{@"info":@"playing"});
183 | }
184 | }else if(_player.playbackState == IJKMPMoviePlaybackStatePaused){
185 | NSLog(@"playback state changed to pause");
186 | if(self.onInfo){
187 | self.onInfo(@{@"info":@"pause"});
188 | }
189 | }else if(_player.playbackState == IJKMPMoviePlaybackStateStopped){
190 | if(self.onInfo){
191 | self.onInfo(@{@"info":@"stop"});
192 | }
193 | }else{
194 |
195 | }
196 | }
197 |
198 | -(void)mediaPlayerLoadStateDidChange:(NSNotification*)notifacation{
199 | if(self.onLoadProgressUpdate){
200 | self.onLoadProgressUpdate(@{@"bufferingProgress":@(_player.bufferingProgress)});
201 | }
202 | }
203 |
204 | -(void)mediaPlayerSeekDidComplete:(NSNotification*)notifacation{
205 | }
206 |
207 | - (void)installMovieNotificationObservers {
208 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mediaIsPreparedToPlayDidChange:) name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification object:_player];
209 |
210 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mediaPlayerPlaybackDidComplete:) name:IJKMPMoviePlayerPlaybackDidFinishNotification object:_player];
211 |
212 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mediaPlayerPlaybackStateDidChange:) name:IJKMPMoviePlayerPlaybackStateDidChangeNotification object:_player];
213 |
214 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mediaPlayerLoadStateDidChange:) name:IJKMPMoviePlayerLoadStateDidChangeNotification object:_player];
215 |
216 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mediaPlayerSeekDidComplete:) name:IJKMPMoviePlayerDidSeekCompleteNotification object:_player];
217 |
218 |
219 | }
220 |
221 | -(void)removeMovieNotificationObservers{
222 | [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification object:_player];
223 |
224 | [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerPlaybackDidFinishNotification object:_player];
225 | [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerPlaybackStateDidChangeNotification object:_player];
226 | [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerLoadStateDidChangeNotification object:_player];
227 | [[NSNotificationCenter defaultCenter]removeObserver:self name:IJKMPMoviePlayerDidSeekCompleteNotification object:_player];
228 | }
229 |
230 | -(void)dealloc{
231 | [self removeMovieNotificationObservers];
232 | if(_player){
233 | [_player stop];
234 | _player = nil;
235 | }
236 | }
237 |
238 | @end
239 |
--------------------------------------------------------------------------------
/ios/RNEasyIjkplayer.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 2A14909F2378C58000B61333 /* RNEasyIjkplayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A14909E2378C58000B61333 /* RNEasyIjkplayerView.m */; };
11 | 2A1490A22378C6AB00B61333 /* RNEasyIjkplayerViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A1490A12378C6AB00B61333 /* RNEasyIjkplayerViewManager.m */; };
12 | 2ACE694C237D1E4B00F6466F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE694B237D1E4B00F6466F /* AudioToolbox.framework */; };
13 | 2ACE694E237D1E5100F6466F /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE694D237D1E5100F6466F /* AVFoundation.framework */; };
14 | 2ACE6966237D295600F6466F /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE6965237D295600F6466F /* VideoToolbox.framework */; };
15 | 2ACE6968237D296200F6466F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE6967237D296200F6466F /* UIKit.framework */; };
16 | 2ACE696A237D297200F6466F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE6969237D297200F6466F /* QuartzCore.framework */; };
17 | 2ACE696C237D297A00F6466F /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE696B237D297A00F6466F /* OpenGLES.framework */; };
18 | 2ACE696E237D298000F6466F /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE696D237D298000F6466F /* MobileCoreServices.framework */; };
19 | 2ACE6970237D298700F6466F /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE696F237D298700F6466F /* MediaPlayer.framework */; };
20 | 2ACE6972237D298E00F6466F /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE6971237D298E00F6466F /* CoreVideo.framework */; };
21 | 2ACE6974237D299600F6466F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE6973237D299500F6466F /* CoreMedia.framework */; };
22 | 2ACE6976237D299D00F6466F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE6975237D299D00F6466F /* CoreGraphics.framework */; };
23 | 2ACE6978237D29C400F6466F /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE6977237D29C400F6466F /* libbz2.tbd */; };
24 | 2ACE697A237D29CA00F6466F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE6979237D29CA00F6466F /* libz.tbd */; };
25 | 2ACE698A237D377800F6466F /* IJKMediaFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE6989237D377800F6466F /* IJKMediaFramework.framework */; };
26 | 2ACE698C237D378800F6466F /* IJKMediaFramework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACE698B237D378800F6466F /* IJKMediaFramework */; };
27 | /* End PBXBuildFile section */
28 |
29 | /* Begin PBXCopyFilesBuildPhase section */
30 | 58B511D91A9E6C8500147676 /* CopyFiles */ = {
31 | isa = PBXCopyFilesBuildPhase;
32 | buildActionMask = 2147483647;
33 | dstPath = "include/$(PRODUCT_NAME)";
34 | dstSubfolderSpec = 16;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXCopyFilesBuildPhase section */
40 |
41 | /* Begin PBXFileReference section */
42 | 134814201AA4EA6300B7C361 /* libRNEasyIjkplayer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNEasyIjkplayer.a; sourceTree = BUILT_PRODUCTS_DIR; };
43 | 2A14909D2378C58000B61333 /* RNEasyIjkplayerView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNEasyIjkplayerView.h; sourceTree = ""; };
44 | 2A14909E2378C58000B61333 /* RNEasyIjkplayerView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNEasyIjkplayerView.m; sourceTree = ""; };
45 | 2A1490A02378C6AB00B61333 /* RNEasyIjkplayerViewManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNEasyIjkplayerViewManager.h; sourceTree = ""; };
46 | 2A1490A12378C6AB00B61333 /* RNEasyIjkplayerViewManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNEasyIjkplayerViewManager.m; sourceTree = ""; };
47 | 2ACE694B237D1E4B00F6466F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
48 | 2ACE694D237D1E5100F6466F /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
49 | 2ACE6965237D295600F6466F /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; };
50 | 2ACE6967237D296200F6466F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
51 | 2ACE6969237D297200F6466F /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
52 | 2ACE696B237D297A00F6466F /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
53 | 2ACE696D237D298000F6466F /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
54 | 2ACE696F237D298700F6466F /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
55 | 2ACE6971237D298E00F6466F /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
56 | 2ACE6973237D299500F6466F /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
57 | 2ACE6975237D299D00F6466F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
58 | 2ACE6977237D29C400F6466F /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; };
59 | 2ACE6979237D29CA00F6466F /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
60 | 2ACE6989237D377800F6466F /* IJKMediaFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = IJKMediaFramework.framework; sourceTree = ""; };
61 | 2ACE698B237D378800F6466F /* IJKMediaFramework */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = IJKMediaFramework; path = IJKMediaFramework.framework/IJKMediaFramework; sourceTree = ""; };
62 | /* End PBXFileReference section */
63 |
64 | /* Begin PBXFrameworksBuildPhase section */
65 | 58B511D81A9E6C8500147676 /* Frameworks */ = {
66 | isa = PBXFrameworksBuildPhase;
67 | buildActionMask = 2147483647;
68 | files = (
69 | 2ACE697A237D29CA00F6466F /* libz.tbd in Frameworks */,
70 | 2ACE6978237D29C400F6466F /* libbz2.tbd in Frameworks */,
71 | 2ACE694C237D1E4B00F6466F /* AudioToolbox.framework in Frameworks */,
72 | 2ACE694E237D1E5100F6466F /* AVFoundation.framework in Frameworks */,
73 | 2ACE6976237D299D00F6466F /* CoreGraphics.framework in Frameworks */,
74 | 2ACE6974237D299600F6466F /* CoreMedia.framework in Frameworks */,
75 | 2ACE6972237D298E00F6466F /* CoreVideo.framework in Frameworks */,
76 | 2ACE6970237D298700F6466F /* MediaPlayer.framework in Frameworks */,
77 | 2ACE696E237D298000F6466F /* MobileCoreServices.framework in Frameworks */,
78 | 2ACE696C237D297A00F6466F /* OpenGLES.framework in Frameworks */,
79 | 2ACE696A237D297200F6466F /* QuartzCore.framework in Frameworks */,
80 | 2ACE6968237D296200F6466F /* UIKit.framework in Frameworks */,
81 | 2ACE6966237D295600F6466F /* VideoToolbox.framework in Frameworks */,
82 | 2ACE698A237D377800F6466F /* IJKMediaFramework.framework in Frameworks */,
83 | 2ACE698C237D378800F6466F /* IJKMediaFramework in Frameworks */,
84 | );
85 | runOnlyForDeploymentPostprocessing = 0;
86 | };
87 | /* End PBXFrameworksBuildPhase section */
88 |
89 | /* Begin PBXGroup section */
90 | 134814211AA4EA7D00B7C361 /* Products */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 134814201AA4EA6300B7C361 /* libRNEasyIjkplayer.a */,
94 | );
95 | name = Products;
96 | sourceTree = "";
97 | };
98 | 2ACE694A237D1E4B00F6466F /* Frameworks */ = {
99 | isa = PBXGroup;
100 | children = (
101 | 2ACE6979237D29CA00F6466F /* libz.tbd */,
102 | 2ACE6977237D29C400F6466F /* libbz2.tbd */,
103 | 2ACE6975237D299D00F6466F /* CoreGraphics.framework */,
104 | 2ACE6973237D299500F6466F /* CoreMedia.framework */,
105 | 2ACE6971237D298E00F6466F /* CoreVideo.framework */,
106 | 2ACE696F237D298700F6466F /* MediaPlayer.framework */,
107 | 2ACE696D237D298000F6466F /* MobileCoreServices.framework */,
108 | 2ACE696B237D297A00F6466F /* OpenGLES.framework */,
109 | 2ACE6969237D297200F6466F /* QuartzCore.framework */,
110 | 2ACE6967237D296200F6466F /* UIKit.framework */,
111 | 2ACE6965237D295600F6466F /* VideoToolbox.framework */,
112 | 2ACE694D237D1E5100F6466F /* AVFoundation.framework */,
113 | 2ACE694B237D1E4B00F6466F /* AudioToolbox.framework */,
114 | );
115 | name = Frameworks;
116 | sourceTree = "";
117 | };
118 | 58B511D21A9E6C8500147676 = {
119 | isa = PBXGroup;
120 | children = (
121 | 2ACE698B237D378800F6466F /* IJKMediaFramework */,
122 | 2ACE6989237D377800F6466F /* IJKMediaFramework.framework */,
123 | 2A1490A02378C6AB00B61333 /* RNEasyIjkplayerViewManager.h */,
124 | 2A1490A12378C6AB00B61333 /* RNEasyIjkplayerViewManager.m */,
125 | 2A14909D2378C58000B61333 /* RNEasyIjkplayerView.h */,
126 | 2A14909E2378C58000B61333 /* RNEasyIjkplayerView.m */,
127 | 134814211AA4EA7D00B7C361 /* Products */,
128 | 2ACE694A237D1E4B00F6466F /* Frameworks */,
129 | );
130 | sourceTree = "";
131 | };
132 | /* End PBXGroup section */
133 |
134 | /* Begin PBXNativeTarget section */
135 | 58B511DA1A9E6C8500147676 /* RNEasyIjkplayer */ = {
136 | isa = PBXNativeTarget;
137 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNEasyIjkplayer" */;
138 | buildPhases = (
139 | 58B511D71A9E6C8500147676 /* Sources */,
140 | 58B511D81A9E6C8500147676 /* Frameworks */,
141 | 58B511D91A9E6C8500147676 /* CopyFiles */,
142 | );
143 | buildRules = (
144 | );
145 | dependencies = (
146 | );
147 | name = RNEasyIjkplayer;
148 | productName = RCTDataManager;
149 | productReference = 134814201AA4EA6300B7C361 /* libRNEasyIjkplayer.a */;
150 | productType = "com.apple.product-type.library.static";
151 | };
152 | /* End PBXNativeTarget section */
153 |
154 | /* Begin PBXProject section */
155 | 58B511D31A9E6C8500147676 /* Project object */ = {
156 | isa = PBXProject;
157 | attributes = {
158 | LastUpgradeCheck = 0830;
159 | ORGANIZATIONNAME = Facebook;
160 | TargetAttributes = {
161 | 58B511DA1A9E6C8500147676 = {
162 | CreatedOnToolsVersion = 6.1.1;
163 | };
164 | };
165 | };
166 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNEasyIjkplayer" */;
167 | compatibilityVersion = "Xcode 3.2";
168 | developmentRegion = English;
169 | hasScannedForEncodings = 0;
170 | knownRegions = (
171 | English,
172 | en,
173 | );
174 | mainGroup = 58B511D21A9E6C8500147676;
175 | productRefGroup = 58B511D21A9E6C8500147676;
176 | projectDirPath = "";
177 | projectRoot = "";
178 | targets = (
179 | 58B511DA1A9E6C8500147676 /* RNEasyIjkplayer */,
180 | );
181 | };
182 | /* End PBXProject section */
183 |
184 | /* Begin PBXSourcesBuildPhase section */
185 | 58B511D71A9E6C8500147676 /* Sources */ = {
186 | isa = PBXSourcesBuildPhase;
187 | buildActionMask = 2147483647;
188 | files = (
189 | 2A1490A22378C6AB00B61333 /* RNEasyIjkplayerViewManager.m in Sources */,
190 | 2A14909F2378C58000B61333 /* RNEasyIjkplayerView.m in Sources */,
191 | );
192 | runOnlyForDeploymentPostprocessing = 0;
193 | };
194 | /* End PBXSourcesBuildPhase section */
195 |
196 | /* Begin XCBuildConfiguration section */
197 | 58B511ED1A9E6C8500147676 /* Debug */ = {
198 | isa = XCBuildConfiguration;
199 | buildSettings = {
200 | ALWAYS_SEARCH_USER_PATHS = NO;
201 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
202 | CLANG_CXX_LIBRARY = "libc++";
203 | CLANG_ENABLE_MODULES = YES;
204 | CLANG_ENABLE_OBJC_ARC = YES;
205 | CLANG_WARN_BOOL_CONVERSION = YES;
206 | CLANG_WARN_CONSTANT_CONVERSION = YES;
207 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
208 | CLANG_WARN_EMPTY_BODY = YES;
209 | CLANG_WARN_ENUM_CONVERSION = YES;
210 | CLANG_WARN_INFINITE_RECURSION = YES;
211 | CLANG_WARN_INT_CONVERSION = YES;
212 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
213 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
214 | CLANG_WARN_UNREACHABLE_CODE = YES;
215 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
216 | COPY_PHASE_STRIP = NO;
217 | ENABLE_STRICT_OBJC_MSGSEND = YES;
218 | ENABLE_TESTABILITY = YES;
219 | GCC_C_LANGUAGE_STANDARD = gnu99;
220 | GCC_DYNAMIC_NO_PIC = NO;
221 | GCC_NO_COMMON_BLOCKS = YES;
222 | GCC_OPTIMIZATION_LEVEL = 0;
223 | GCC_PREPROCESSOR_DEFINITIONS = (
224 | "DEBUG=1",
225 | "$(inherited)",
226 | );
227 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
228 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
229 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
230 | GCC_WARN_UNDECLARED_SELECTOR = YES;
231 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
232 | GCC_WARN_UNUSED_FUNCTION = YES;
233 | GCC_WARN_UNUSED_VARIABLE = YES;
234 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
235 | MTL_ENABLE_DEBUG_INFO = YES;
236 | ONLY_ACTIVE_ARCH = YES;
237 | SDKROOT = iphoneos;
238 | };
239 | name = Debug;
240 | };
241 | 58B511EE1A9E6C8500147676 /* Release */ = {
242 | isa = XCBuildConfiguration;
243 | buildSettings = {
244 | ALWAYS_SEARCH_USER_PATHS = NO;
245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
246 | CLANG_CXX_LIBRARY = "libc++";
247 | CLANG_ENABLE_MODULES = YES;
248 | CLANG_ENABLE_OBJC_ARC = YES;
249 | CLANG_WARN_BOOL_CONVERSION = YES;
250 | CLANG_WARN_CONSTANT_CONVERSION = YES;
251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
252 | CLANG_WARN_EMPTY_BODY = YES;
253 | CLANG_WARN_ENUM_CONVERSION = YES;
254 | CLANG_WARN_INFINITE_RECURSION = YES;
255 | CLANG_WARN_INT_CONVERSION = YES;
256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
257 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
258 | CLANG_WARN_UNREACHABLE_CODE = YES;
259 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
260 | COPY_PHASE_STRIP = YES;
261 | ENABLE_NS_ASSERTIONS = NO;
262 | ENABLE_STRICT_OBJC_MSGSEND = YES;
263 | GCC_C_LANGUAGE_STANDARD = gnu99;
264 | GCC_NO_COMMON_BLOCKS = YES;
265 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
266 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
267 | GCC_WARN_UNDECLARED_SELECTOR = YES;
268 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
269 | GCC_WARN_UNUSED_FUNCTION = YES;
270 | GCC_WARN_UNUSED_VARIABLE = YES;
271 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
272 | MTL_ENABLE_DEBUG_INFO = NO;
273 | SDKROOT = iphoneos;
274 | VALIDATE_PRODUCT = YES;
275 | };
276 | name = Release;
277 | };
278 | 58B511F01A9E6C8500147676 /* Debug */ = {
279 | isa = XCBuildConfiguration;
280 | buildSettings = {
281 | FRAMEWORK_SEARCH_PATHS = (
282 | "$(inherited)",
283 | "$(PROJECT_DIR)",
284 | );
285 | HEADER_SEARCH_PATHS = (
286 | "$(inherited)",
287 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
288 | "$(SRCROOT)/../../../React/**",
289 | "$(SRCROOT)/../../react-native/React/**",
290 | );
291 | "HEADER_SEARCH_PATHS[arch=*]" = "$(SRCROOT)/../../react-native/React";
292 | LIBRARY_SEARCH_PATHS = (
293 | "$(inherited)",
294 | "$(PROJECT_DIR)/IJKMediaFramework.framework",
295 | );
296 | OTHER_LDFLAGS = "-ObjC";
297 | PRODUCT_NAME = RNEasyIjkplayer;
298 | SKIP_INSTALL = YES;
299 | };
300 | name = Debug;
301 | };
302 | 58B511F11A9E6C8500147676 /* Release */ = {
303 | isa = XCBuildConfiguration;
304 | buildSettings = {
305 | FRAMEWORK_SEARCH_PATHS = (
306 | "$(inherited)",
307 | "$(PROJECT_DIR)",
308 | );
309 | HEADER_SEARCH_PATHS = (
310 | "$(inherited)",
311 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
312 | "$(SRCROOT)/../../../React/**",
313 | "$(SRCROOT)/../../react-native/React/**",
314 | );
315 | "HEADER_SEARCH_PATHS[arch=*]" = "$(SRCROOT)/../../react-native/React";
316 | LIBRARY_SEARCH_PATHS = (
317 | "$(inherited)",
318 | "$(PROJECT_DIR)/IJKMediaFramework.framework",
319 | );
320 | OTHER_LDFLAGS = "-ObjC";
321 | PRODUCT_NAME = RNEasyIjkplayer;
322 | SKIP_INSTALL = YES;
323 | };
324 | name = Release;
325 | };
326 | /* End XCBuildConfiguration section */
327 |
328 | /* Begin XCConfigurationList section */
329 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNEasyIjkplayer" */ = {
330 | isa = XCConfigurationList;
331 | buildConfigurations = (
332 | 58B511ED1A9E6C8500147676 /* Debug */,
333 | 58B511EE1A9E6C8500147676 /* Release */,
334 | );
335 | defaultConfigurationIsVisible = 0;
336 | defaultConfigurationName = Release;
337 | };
338 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNEasyIjkplayer" */ = {
339 | isa = XCConfigurationList;
340 | buildConfigurations = (
341 | 58B511F01A9E6C8500147676 /* Debug */,
342 | 58B511F11A9E6C8500147676 /* Release */,
343 | );
344 | defaultConfigurationIsVisible = 0;
345 | defaultConfigurationName = Release;
346 | };
347 | /* End XCConfigurationList section */
348 | };
349 | rootObject = 58B511D31A9E6C8500147676 /* Project object */;
350 | }
351 |
--------------------------------------------------------------------------------