#import #import "IjkplayerPlugin.h" #import "CoolFlutterIjkManager.h" #import "CoolFlutterIJK.h" #import "FlutterViewController+CoolStatusBarHidden.h" NSString *flutterOrientationNotifyName = @"io.flutter.plugin.platform.SystemChromeOrientationNotificationName"; const NSString *flutterOrientationNotifyKey = @"io.flutter.plugin.platform.SystemChromeOrientationNotificationKey"; @interface FlutterMethodCall (Ijk) - (int64_t)getId; - (int64_t)getIdParamFromDict; - (NSString *)getStringParam:(NSString *)key; @end static IjkplayerPlugin *__sharedInstance; @implementation IjkplayerPlugin { CoolFlutterIjkManager *manager; MPVolumeView *volumeView; UISlider *volumeViewSlider; } + (instancetype)sharedInstance { return __sharedInstance; } - (instancetype)initWithRegistrar:(NSObject *)registrar { self = [super init]; if (self) { self.registrar = registrar; manager = [CoolFlutterIjkManager managerWithRegistrar:registrar]; } return self; } + (instancetype)pluginWithRegistrar:(NSObject *)registrar { return [[self alloc] initWithRegistrar:registrar]; } + (void)registerWithRegistrar:(NSObject *)registrar { FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"top.kikt/ijkplayer" binaryMessenger:[registrar messenger]]; IjkplayerPlugin *instance = [IjkplayerPlugin pluginWithRegistrar:registrar]; [registrar addMethodCallDelegate:instance channel:channel]; __sharedInstance = instance; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { dispatch_queue_t mainQueue = dispatch_get_main_queue(); // __weak typeof(&*self) weakSelf = self; dispatch_async(mainQueue, ^{ if ([@"create" isEqualToString:call.method]) { @try { int64_t id = [self->manager createWithCall:call]; result(@(id)); } @catch (NSException *exception) { result([FlutterError errorWithCode:@"1" message:@"创建失败" details:exception]); } [self checkVolumeViewShouldShow]; } else if ([@"dispose" isEqualToString:call.method]) { NSDictionary *params = [call arguments]; int id = [params[@"id"] intValue]; [self->manager disposeWithId:id]; [self checkVolumeViewShouldShow]; result(@(YES)); } else if ([@"init" isEqualToString:call.method]) { [self->manager disposeAll]; [self checkVolumeViewShouldShow]; result(@YES); } else if ([@"setSystemVolume" isEqualToString:call.method]) { NSDictionary *params = [call arguments]; int volume = [params[@"volume"] intValue]; [self setSystemVolume:volume]; result(@YES); } else if ([@"getSystemVolume" isEqualToString:call.method]) { int currentVol = [self getSystemVolume]; result(@(currentVol)); } else if ([@"volumeUp" isEqualToString:call.method]) { int currentVol = [self getSystemVolume]; [self setSystemVolume: currentVol + 3]; currentVol = [self getSystemVolume]; result(@(currentVol)); } else if ([@"volumeDown" isEqualToString:call.method]) { int currentVol = [self getSystemVolume]; [self setSystemVolume: currentVol - 3]; currentVol = [self getSystemVolume]; result(@(currentVol)); } else if ([@"hideSystemVolumeBar" isEqualToString:call.method]) { [self hideSystemVolumeBar]; result(@YES); } else if ([@"setSystemBrightness" isEqualToString:call.method]) { NSDictionary *params = [call arguments]; CGFloat target = [params[@"brightness"] floatValue]; [[UIScreen mainScreen] setBrightness:target]; result(@YES); } else if ([@"getSystemBrightness" isEqualToString:call.method]) { CGFloat brightness = [UIScreen mainScreen].brightness; result(@(brightness)); } else if ([@"resetBrightness" isEqualToString:call.method]) { // CGFloat brightness = [UIScreen mainScreen].brightness; result(@YES); } else if ([@"setSupportOrientation" isEqualToString:call.method]) { [self setSupportOrientationWithCall:call]; result(@YES); } else if([@"setCurrentOrientation" isEqualToString:call.method]){ [self setCurrentOrientationWithCall:call]; result(@YES); } else if([@"unlockOrientation" isEqualToString:call.method]){ [self unlockOrientation]; result(@YES); } else if([@"showStatusBar" isEqualToString:call.method]) { BOOL showStatusBar = [call.arguments boolValue]; [self setStatusBarToShow:showStatusBar]; } else { result(FlutterMethodNotImplemented); } }); } - (UIDeviceOrientation) convertIntToOrientation:(int)orientation{ switch (orientation) { case 0: return UIDeviceOrientationPortrait; case 1: return UIDeviceOrientationLandscapeLeft; case 2: return UIDeviceOrientationPortraitUpsideDown; case 3: return UIDeviceOrientationLandscapeRight; default: return UIDeviceOrientationUnknown; } } - (void) setOrientationWithCall:(FlutterMethodCall *)call{ NSDictionary *dict = [call arguments]; NSArray *orientations = dict[@"orientation"]; UIInterfaceOrientationMask mask = 0; if (orientations.count == 0) { mask |= UIInterfaceOrientationMaskAll; } for (id number in orientations) { int value = [number intValue]; UIDeviceOrientation orientation = [self convertIntToOrientation:value]; NSLog(@"orientation = %ld",(long)orientation); if (orientation == UIDeviceOrientationPortrait){ mask |= UIInterfaceOrientationMaskPortrait; }else if (orientation == UIDeviceOrientationLandscapeLeft) { mask |= UIInterfaceOrientationMaskLandscapeLeft; }else if (orientation == UIDeviceOrientationPortraitUpsideDown) { mask |= UIInterfaceOrientationMaskPortraitUpsideDown; }else if (orientation == UIDeviceOrientationLandscapeRight) { mask |= UIInterfaceOrientationMaskLandscapeRight; } } [[NSNotificationCenter defaultCenter] postNotificationName:flutterOrientationNotifyName object:nil userInfo:@{flutterOrientationNotifyKey :@(mask)}]; if(orientations.count != 0 && [[UIDevice currentDevice]respondsToSelector:@selector(setOrientation:)]){ SEL selector = NSSelectorFromString(@"setOrientation:"); int value = [orientations[0] intValue]; UIDeviceOrientation orientation = [self convertIntToOrientation:value]; int val = orientation; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]]; [invocation setSelector:selector]; [invocation setTarget:[UIDevice currentDevice]]; [invocation setArgument:&val atIndex:2]; [invocation invoke]; } } - (void) setCurrentOrientationWithCall:(FlutterMethodCall *)call { if([[UIDevice currentDevice]respondsToSelector:@selector(setOrientation:)]){ SEL selector = NSSelectorFromString(@"setOrientation:"); NSDictionary *dict = [call arguments]; int target = [dict[@"target"] intValue]; UIDeviceOrientation orientation = [self convertIntToOrientation:target]; int val = orientation; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]]; [invocation setSelector:selector]; [invocation setTarget:[UIDevice currentDevice]]; [invocation setArgument:&val atIndex:2]; [invocation invoke]; NSLog(@"target orientation = %d", val); } } - (void) setSupportOrientationWithCall:(FlutterMethodCall *)call { NSDictionary *dict = [call arguments]; NSArray *orientations = dict[@"supportOrientation"]; UIInterfaceOrientationMask mask = 0; if (orientations.count == 0) { mask |= UIInterfaceOrientationMaskAll; } for (id number in orientations) { int value = [number intValue]; UIDeviceOrientation orientation = [self convertIntToOrientation:value]; NSLog(@"orientation = %ld",orientation); if (orientation == UIDeviceOrientationPortrait){ mask |= UIInterfaceOrientationMaskPortrait; }else if (orientation == UIDeviceOrientationLandscapeLeft) { mask |= UIInterfaceOrientationMaskLandscapeLeft; }else if (orientation == UIDeviceOrientationPortraitUpsideDown) { mask |= UIInterfaceOrientationMaskPortraitUpsideDown; }else if (orientation == UIDeviceOrientationLandscapeRight) { mask |= UIInterfaceOrientationMaskLandscapeRight; } } [[NSNotificationCenter defaultCenter] postNotificationName:flutterOrientationNotifyName object:nil userInfo:@{flutterOrientationNotifyKey :@(mask)}]; } - (void) unlockOrientation { UIDevice *device = [UIDevice currentDevice]; if([device respondsToSelector:@selector(setOrientation:)]){ SEL selector = NSSelectorFromString(@"setOrientation:"); int val = device.orientation; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]]; [invocation setSelector:selector]; [invocation setTarget:[UIDevice currentDevice]]; [invocation setArgument:&val atIndex:2]; [invocation invoke]; } [[NSNotificationCenter defaultCenter] postNotificationName:flutterOrientationNotifyName object:nil userInfo:@{flutterOrientationNotifyKey :@(UIInterfaceOrientationMaskAll)}]; } - (int) getSystemVolume{ // AVAudioSession *audioSession = [AVAudioSession sharedInstance]; // CGFloat currentVol = audioSession.outputVolume * 100; // NSLog(@"system volume = %.0f",currentVol); // return (int)currentVol; return (int)([self getVolumeWithVolumeView] * 100); } - (float) getVolumeWithVolumeView{ [self initVolumeView]; if(!volumeViewSlider){ AVAudioSession *audioSession = [AVAudioSession sharedInstance]; CGFloat currentVol = audioSession.outputVolume * 100; NSLog(@"system volume = %.0f",currentVol); return (int)currentVol; } return volumeViewSlider.value; } -(void)initVolumeView{ if(!volumeView){ volumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(-100, 0, 10, 10)]; } if(!volumeViewSlider){ for (UIView *view in [volumeView subviews]) { if ([view.class.description isEqualToString:@"MPVolumeSlider"]) { volumeViewSlider = (UISlider *) view; break; } } } UIWindow *window = UIApplication.sharedApplication.keyWindow; [window addSubview:volumeView]; } - (void) checkVolumeViewShouldShow{ int count = [manager ijkCount]; if (count>0){ [self initVolumeView]; }else{ [volumeView removeFromSuperview]; volumeView = nil; } } - (void)setSystemVolume:(int)volume { [self initVolumeView]; float targetVolume = ((float) volume) / 100; if (targetVolume > 1){ targetVolume = 1; } else if(targetVolume < 0){ targetVolume = 0; } // change system volume, the value is between 0.0f and 1.0f [volumeViewSlider setValue:targetVolume animated:NO]; // send UI control event to make the change effect right now. 立即生效 [volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside]; // [volumeView removeFromSuperview]; } -(void)hideSystemVolumeBar { } -(void)setStatusBarToShow:(BOOL)show{ UIViewController *ctl = [self getCurrentUIViewController]; if([ctl isKindOfClass:[FlutterViewController class] ]){ FlutterViewController *fCtl = (FlutterViewController*)ctl; if(show){ [fCtl showStatusBar]; }else{ [fCtl hideStatusBar]; } } } -(UIViewController*) getCurrentUIViewController{ UIViewController *result = nil; UIWindow *window = [[UIApplication sharedApplication] keyWindow]; if(window.windowLevel != UIWindowLevelNormal){ NSArray *windows =[[UIApplication sharedApplication ]windows]; for(UIWindow *tmp in windows){ window = tmp; break; } } result = window.rootViewController; while (result.presentedViewController) { result = result.presentedViewController; } if([result isKindOfClass:[UITabBarController class]]){ result = [(UITabBarController*)result selectedViewController]; } if([result isKindOfClass:[UINavigationController class]]){ result = [(UINavigationController*) result visibleViewController]; } return result; } @end @implementation FlutterMethodCall (Ijk) - (int64_t)getId { return [[self arguments] intValue]; } - (int64_t)getIdParamFromDict { return [[self arguments][@"id"] intValue]; } - (NSString *)getStringParam:(NSString *)key { return [self arguments][key]; } @end