├── .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 |