Browse Source

update ios code

Caijinglong 6 years ago
parent
commit
d030d6da31

+ 4 - 2
README.md

@@ -6,8 +6,10 @@ ijkplayer,通过内接纹理的方式接入 bilibili/ijkplayer
 
 ### android
 
-仅支持 android, 还需要重新编译 ffmpeg,目前的 so 库不支持 http 协议
+- [x] 重新编译 ijkplayer,支持 https
 
 ### ios
 
-未开启
+- [x] 重新编译 ijkplayer,支持 https
+
+需要修复一个 iOS 的 UI 线程 bug

+ 6 - 0
example/ios/Podfile.lock

@@ -2,20 +2,26 @@ PODS:
   - Flutter (1.0.0)
   - flutter_ijkplayer (0.0.1):
     - Flutter
+  - photo_manager (0.0.1):
+    - Flutter
 
 DEPENDENCIES:
   - Flutter (from `.symlinks/flutter/ios`)
   - flutter_ijkplayer (from `/Volumes/Evo512/code/flutter/plugins/ijkplayer/ios/flutter_ijkplayer.podspec`)
+  - photo_manager (from `/Users/cai/.pub-cache/hosted/pub.flutter-io.cn/photo_manager-0.3.2/ios/photo_manager.podspec`)
 
 EXTERNAL SOURCES:
   Flutter:
     :path: ".symlinks/flutter/ios"
   flutter_ijkplayer:
     :path: "/Volumes/Evo512/code/flutter/plugins/ijkplayer/ios/flutter_ijkplayer.podspec"
+  photo_manager:
+    :path: "/Users/cai/.pub-cache/hosted/pub.flutter-io.cn/photo_manager-0.3.2/ios/photo_manager.podspec"
 
 SPEC CHECKSUMS:
   Flutter: 9d0fac939486c9aba2809b7982dfdbb47a7b0296
   flutter_ijkplayer: add1e58f2329ca825b03decb062a9167be9bbc59
+  photo_manager: a406dfebdf49773f7eb25ba093e132f6d1f677e1
 
 PODFILE CHECKSUM: a14c63eb48a9d676ed6d876506b3258fd9c85235
 

+ 2 - 0
example/ios/Runner/Info.plist

@@ -41,5 +41,7 @@
 	</array>
 	<key>UIViewControllerBasedStatusBarAppearance</key>
 	<false/>
+    <key>NSPhotoLibraryUsageDescription</key>
+    <string>App need your agree, can visit your album</string>
 </dict>
 </plist>

+ 25 - 0
example/lib/main.dart

@@ -1,5 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
+import 'package:photo/photo.dart';
 
 void main() => runApp(MyApp());
 
@@ -41,6 +42,12 @@ class HomePageState extends State<HomePage> {
     return Scaffold(
       appBar: AppBar(
         title: const Text('Plugin example app'),
+        actions: <Widget>[
+          IconButton(
+            icon: Icon(Icons.videocam),
+            onPressed: _pickVideo,
+          ),
+        ],
       ),
       body: Container(
         // width: MediaQuery.of(context).size.width,
@@ -71,4 +78,22 @@ class HomePageState extends State<HomePage> {
       ),
     );
   }
+
+  void _pickVideo() async {
+    var list = await PhotoPicker.pickAsset(
+      context: context,
+      pickType: PickType.onlyVideo,
+    );
+    if (list != null && list.isNotEmpty) {
+      var asset = list[0];
+      var fileUri = (await asset.file).uri;
+      playUri(fileUri.toString());
+    }
+  }
+
+  void playUri(String uri) async {
+    await controller.setDataSource(uri);
+    print("set data source success");
+    controller.play();
+  }
 }

+ 14 - 0
example/pubspec.lock

@@ -81,6 +81,20 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.5.0"
+  photo:
+    dependency: "direct main"
+    description:
+      name: photo
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "0.3.2"
+  photo_manager:
+    dependency: transitive
+    description:
+      name: photo_manager
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "0.3.2"
   quiver:
     dependency: transitive
     description:

+ 2 - 6
example/pubspec.yaml

@@ -1,6 +1,6 @@
 name: ijkplayer_example
 description: Demonstrates how to use the ijkplayer plugin.
-publish_to: 'none'
+publish_to: "none"
 
 environment:
   sdk: ">=2.1.0 <3.0.0"
@@ -12,6 +12,7 @@ dependencies:
   # The following adds the Cupertino Icons font to your application.
   # Use with the CupertinoIcons class for iOS style icons.
   cupertino_icons: ^0.1.2
+  photo: ^0.3.2
 
 dev_dependencies:
   flutter_test:
@@ -25,23 +26,18 @@ dev_dependencies:
 
 # The following section is specific to Flutter.
 flutter:
-
   # The following line ensures that the Material Icons font is
   # included with your application, so that you can use the icons in
   # the material Icons class.
   uses-material-design: true
-
   # To add assets to your application, add an assets section, like this:
   # assets:
   #  - images/a_dot_burr.jpeg
   #  - images/a_dot_ham.jpeg
-
   # An image asset can refer to one or more resolution-specific "variants", see
   # https://flutter.io/assets-and-images/#resolution-aware.
-
   # For details regarding adding assets from package dependencies, see
   # https://flutter.io/assets-and-images/#from-packages
-
   # To add custom fonts to your application, add a fonts section here,
   # in this "flutter" section. Each entry in this list should have a
   # "family" key with the font family name, and a "fonts" key with a

+ 9 - 0
ios/Classes/FlutterIJK.h

@@ -15,4 +15,13 @@
 
 - (int64_t)id;
 
+- (void)dispose;
+
+- (void)play;
+
+- (void)pause;
+
+- (void)stop;
+
+- (void)setDateSourceWithUri:(NSString *)uri;
 @end

+ 38 - 8
ios/Classes/FlutterIJK.m

@@ -8,6 +8,9 @@
 #import <AVFoundation/AVFoundation.h>
 
 @interface IJKVideoPlayer : NSObject <FlutterTexture>
+@property(nonatomic, strong) IJKFFMoviePlayerController *controller;
+
+- (void)setDataSource:(NSString *)uri;
 @end
 
 @interface FlutterIJK ()
@@ -23,6 +26,7 @@
         self.registrar = registrar;
         IJKMPMoviePlayerController *controller = [[IJKMPMoviePlayerController alloc] initWithContentURLString:@""];
         NSObject <FlutterTextureRegistry> *textures = [self.registrar textures];
+        player = [IJKVideoPlayer new];
         textureId = [textures registerTexture:player];
     }
 
@@ -37,20 +41,39 @@
     return textureId;
 }
 
+- (void)dispose {
+    IJKFFMoviePlayerController *ctl = [player controller];
+    [ctl stop];
+    [ctl shutdown];
+}
+
+- (void)play {
+    IJKFFMoviePlayerController *ctl = [player controller];
+    [ctl play];
+}
+
+- (void)pause {
+    [[player controller] pause];
+}
+
+- (void)stop {
+    [[player controller] stop];
+}
+
+- (void)setDateSourceWithUri:(NSString *)uri {
+    [player setDataSource:uri];
+}
+
 @end
 
 @implementation IJKVideoPlayer {
-    IJKFFMoviePlayerController *controller;
+//    IJKFFMoviePlayerController *controller;
 }
 
 - (instancetype)init {
     self = [super init];
     if (self) {
-        IJKFFOptions *options = [IJKFFOptions optionsByDefault];
-        NSString *urlString = @"https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4";
-        controller = [[IJKFFMoviePlayerController alloc] initWithContentURLString:urlString withOptions:options];
-        [controller prepareToPlay];
-        [controller play];
+
     }
 
     return self;
@@ -58,7 +81,14 @@
 
 
 - (CVPixelBufferRef _Nullable)copyPixelBuffer {
-    return [controller framePixelbuffer];
+    return [self.controller framePixelbuffer];
 }
 
-@end
+- (void)setDataSource:(NSString *)uri {
+    IJKFFOptions *options = [IJKFFOptions optionsByDefault];
+    self.controller = [[IJKFFMoviePlayerController alloc] initWithContentURLString:uri withOptions:options];
+    [self.controller prepareToPlay];
+}
+
+
+@end

+ 5 - 0
ios/Classes/FlutterIjkManager.h

@@ -5,6 +5,8 @@
 #import <Foundation/Foundation.h>
 #import <Flutter/Flutter.h>
 
+@class FlutterIJK;
+
 @interface FlutterIjkManager : NSObject
 
 @property(nonatomic, strong) NSObject <FlutterPluginRegistrar> *registrar;
@@ -15,4 +17,7 @@
 
 - (int64_t)create;
 
+- (FlutterIJK *)findIJKWithId:(int64_t)id1;
+
+- (void)disposeWithId:(int64_t)id;
 @end

+ 15 - 2
ios/Classes/FlutterIjkManager.m

@@ -7,7 +7,7 @@
 #import <IJKMediaFramework/IJKMediaFramework.h>
 
 @implementation FlutterIjkManager {
-    NSObject <FlutterTextureRegistry> *textures;
+    NSMutableDictionary<NSNumber *, FlutterIJK * > *dict;
 }
 
 
@@ -15,7 +15,7 @@
     self = [super init];
     if (self) {
         self.registrar = registrar;
-        textures = [registrar textures];
+        dict = [NSMutableDictionary new];
     }
 
     return self;
@@ -27,8 +27,21 @@
 
 - (int64_t)create {
     FlutterIJK *ijk = [FlutterIJK ijkWithRegistrar:self.registrar];
+    NSNumber *number = @([ijk id]);
+    dict[number] = ijk;
     return [ijk id];
 }
 
+- (FlutterIJK *)findIJKWithId:(int64_t)id {
+    return dict[@(id)];
+}
+
+- (void)disposeWithId:(int64_t)id {
+    FlutterIJK *ijk = dict[@(id)];
+    if (ijk) {
+        [ijk dispose];
+        [dict removeObjectForKey:@(id)];
+    }
+}
 
 @end

+ 7 - 0
ios/Classes/IjkplayerPlugin.h

@@ -1,4 +1,11 @@
 #import <Flutter/Flutter.h>
 
 @interface IjkplayerPlugin : NSObject<FlutterPlugin>
+@property(nonatomic, strong) NSObject <FlutterPluginRegistrar> *registrar;
+
+- (instancetype)initWithRegistrar:(NSObject <FlutterPluginRegistrar> *)registrar;
+
++ (instancetype)pluginWithRegistrar:(NSObject <FlutterPluginRegistrar> *)registrar;
+
+
 @end

+ 76 - 4
ios/Classes/IjkplayerPlugin.m

@@ -1,26 +1,98 @@
 #import "IjkplayerPlugin.h"
+#import "FlutterIjkManager.h"
+#import "FlutterIJK.h"
+
+@interface FlutterMethodCall (Ijk)
+- (int64_t)getId;
+
+- (int64_t)getIdParamFromDict;
+
+- (NSString *)getStringParam:(NSString *)key;
+@end
+
+@implementation IjkplayerPlugin {
+  FlutterIjkManager *manager;
+}
+
+- (instancetype)initWithRegistrar:(NSObject <FlutterPluginRegistrar> *)registrar {
+  self = [super init];
+  if (self) {
+    self.registrar = registrar;
+    manager = [FlutterIjkManager managerWithRegistrar:registrar];
+  }
+
+  return self;
+}
+
++ (instancetype)pluginWithRegistrar:(NSObject <FlutterPluginRegistrar> *)registrar {
+  return [[self alloc] initWithRegistrar:registrar];
+}
+
 
-@implementation IjkplayerPlugin
 + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
   FlutterMethodChannel* channel = [FlutterMethodChannel
           methodChannelWithName:@"top.kikt/ijkplayer"
                 binaryMessenger:[registrar messenger]];
-  IjkplayerPlugin* instance = [[IjkplayerPlugin alloc] init];
+  IjkplayerPlugin *instance = [IjkplayerPlugin pluginWithRegistrar:registrar];
   [registrar addMethodCallDelegate:instance channel:channel];
 }
 
 - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
-
-
   if ([@"create" isEqualToString:call.method]) {
+    @try {
+      int64_t id = [manager create];
+      result(@(id));
+    }
+    @catch (NSException *exception) {
+      result([FlutterError errorWithCode:@"1" message:@"创建失败" details:exception]);
+    }
   } else if ([@"dispose" isEqualToString:call.method]) {
+    int64_t id = [call getId];
+    [manager disposeWithId:id];
   } else if ([@"play" isEqualToString:call.method]) {
+    FlutterIJK *ijk = [manager findIJKWithId:call.getId];
+    if (ijk) {
+      [ijk play];
+      result(@(1));
+    }
   } else if ([@"pause" isEqualToString:call.method]) {
+    FlutterIJK *ijk = [manager findIJKWithId:[call getId]];
+    if (ijk) {
+      [ijk pause];
+    }
   } else if ([@"stop" isEqualToString:call.method]) {
+    FlutterIJK *ijk = [manager findIJKWithId:[call getId]];
+    if (ijk) {
+      [ijk stop];
+    }
   } else if ([@"setDataSource" isEqualToString:call.method]) {
+    FlutterIJK *ijk = [manager findIJKWithId:[call getIdParamFromDict]];
+    if (ijk) {
+      NSString *uri = [call getStringParam:@"uri"];
+      [ijk setDateSourceWithUri:uri];
+      result(nil);
+    } else {
+      result([FlutterError errorWithCode:@"1" message:@"设置失败" details:nil]);
+    }
   } else {
     result(FlutterMethodNotImplemented);
   }
 }
 
 @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