├── Samples
├── Xam.Forms.VideoPlayer.Samples.iOS
│ ├── Resources
│ │ ├── Default.png
│ │ ├── Default@2x.png
│ │ ├── Default-568h@2x.png
│ │ ├── Default-Portrait.png
│ │ ├── Default-Portrait@2x.png
│ │ └── LaunchScreen.storyboard
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── Icon1024.png
│ │ │ ├── Icon120.png
│ │ │ ├── Icon152.png
│ │ │ ├── Icon167.png
│ │ │ ├── Icon180.png
│ │ │ ├── Icon20.png
│ │ │ ├── Icon29.png
│ │ │ ├── Icon40.png
│ │ │ ├── Icon58.png
│ │ │ ├── Icon60.png
│ │ │ ├── Icon76.png
│ │ │ ├── Icon80.png
│ │ │ ├── Icon87.png
│ │ │ └── Contents.json
│ ├── Entitlements.plist
│ ├── Main.cs
│ ├── AppDelegate.cs
│ ├── Info.plist
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── Xam.Forms.VideoPlayer.Samples.iOS.csproj
├── Xam.Forms.VideoPlayer.Samples.UWP
│ ├── Assets
│ │ ├── StoreLogo.backup.png
│ │ ├── LargeTile.scale-100.png
│ │ ├── LargeTile.scale-200.png
│ │ ├── LargeTile.scale-400.png
│ │ ├── SmallTile.scale-100.png
│ │ ├── SmallTile.scale-200.png
│ │ ├── SmallTile.scale-400.png
│ │ ├── StoreLogo.scale-100.png
│ │ ├── StoreLogo.scale-200.png
│ │ ├── StoreLogo.scale-400.png
│ │ ├── SplashScreen.scale-100.png
│ │ ├── SplashScreen.scale-200.png
│ │ ├── SplashScreen.scale-400.png
│ │ ├── Square44x44Logo.scale-100.png
│ │ ├── Square44x44Logo.scale-200.png
│ │ ├── Square44x44Logo.scale-400.png
│ │ ├── Wide310x150Logo.scale-100.png
│ │ ├── Wide310x150Logo.scale-200.png
│ │ ├── Wide310x150Logo.scale-400.png
│ │ ├── Square150x150Logo.scale-100.png
│ │ ├── Square150x150Logo.scale-200.png
│ │ ├── Square150x150Logo.scale-400.png
│ │ ├── Square44x44Logo.targetsize-16.png
│ │ ├── Square44x44Logo.targetsize-256.png
│ │ ├── Square44x44Logo.targetsize-48.png
│ │ ├── Square44x44Logo.altform-unplated_targetsize-16.png
│ │ ├── Square44x44Logo.altform-unplated_targetsize-48.png
│ │ └── Square44x44Logo.altform-unplated_targetsize-256.png
│ ├── App.xaml
│ ├── MainPage.xaml
│ ├── MainPage.xaml.cs
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── Default.rd.xml
│ ├── Package.appxmanifest
│ ├── App.xaml.cs
│ └── Xam.Forms.VideoPlayer.Samples.UWP.csproj
├── Xam.Forms.VideoPlayer.Samples.Android
│ ├── Resources
│ │ ├── mipmap-hdpi
│ │ │ ├── icon.png
│ │ │ └── launcher_foreground.png
│ │ ├── mipmap-mdpi
│ │ │ ├── icon.png
│ │ │ └── launcher_foreground.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── icon.png
│ │ │ └── launcher_foreground.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── icon.png
│ │ │ └── launcher_foreground.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── icon.png
│ │ │ └── launcher_foreground.png
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── icon.xml
│ │ │ └── icon_round.xml
│ │ ├── values
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ ├── layout
│ │ │ ├── Toolbar.axml
│ │ │ └── Tabbar.axml
│ │ └── AboutResources.txt
│ ├── Properties
│ │ ├── AndroidManifest.xml
│ │ └── AssemblyInfo.cs
│ ├── Assets
│ │ └── AboutAssets.txt
│ ├── MainActivity.cs
│ └── Xam.Forms.VideoPlayer.Samples.Android.csproj
└── Xam.Forms.VideoPlayer.Samples
│ ├── App.xaml
│ ├── MainPage.xaml
│ ├── App.xaml.cs
│ ├── Xam.Forms.VideoPlayer.Samples.csproj
│ ├── MainPage.xaml.cs
│ ├── PlayVideoPage.xaml.cs
│ └── PlayVideoPage.xaml
├── Xam.Forms.VideoPlayer.Android
├── Resources
│ ├── drawable
│ │ ├── ic_fullscreen.png
│ │ └── ic_fullscreen_exit.png
│ ├── values
│ │ └── Strings.xml
│ └── AboutResources.txt
├── StatusBar.Android.cs
├── Properties
│ └── AssemblyInfo.cs
├── MainActivity.cs
├── VideoPicker.Android.cs
├── Resources.Designer.cs
├── Xam.Forms.VideoPlayer.Android.csproj
├── FullScreenMediaController.cs
├── Resources.resx
├── Resources.ru.resx
└── VideoPlayerRenderer.Android.cs
├── Xam.Forms.VideoPlayer.iOS
├── packages.config
├── StatusBar.iOS.cs
├── Properties
│ └── AssemblyInfo.cs
├── VideoPicker.iOS.cs
├── Xam.Forms.VideoPlayer.iOS.csproj
└── VideoPlayerRenderer.iOS.cs
├── Xam.Forms.VideoPlayer
├── VideoStatus.cs
├── IVideoPicker.cs
├── IVideoPlayerController.cs
├── IStatusBar.cs
├── VideoInfo.cs
├── Xam.Forms.VideoPlayer.csproj
├── UriVideoSource.cs
├── FileVideoSource.cs
├── ResourceVideoSource.cs
├── VideoSource.cs
├── VideoSourceConverter.cs
├── PositionSlider.cs
└── VideoPlayer.cs
├── Xam.Forms.VideoPlayer.UWP
├── VideoPicker.UWP.cs
├── Properties
│ ├── AssemblyInfo.cs
│ └── Xam.Forms.VideoPlayer.UWP.rd.xml
├── StatusBar.UWP.cs
├── Xam.Forms.VideoPlayer.UWP.csproj
└── VideoPlayerRenderer.UWP.cs
├── Readme.md
├── .gitattributes
├── Nuget
└── Xam.Forms.VideoPlayer.1.0.8.nuspec
└── .gitignore
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/Default.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/Default@2x.png
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/Resources/drawable/ic_fullscreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Xam.Forms.VideoPlayer.Android/Resources/drawable/ic_fullscreen.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/StoreLogo.backup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/StoreLogo.backup.png
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.iOS/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/Default-568h@2x.png
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/Resources/drawable/ic_fullscreen_exit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Xam.Forms.VideoPlayer.Android/Resources/drawable/ic_fullscreen_exit.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/LargeTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/LargeTile.scale-100.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/LargeTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/LargeTile.scale-200.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/LargeTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/LargeTile.scale-400.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SmallTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SmallTile.scale-100.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SmallTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SmallTile.scale-200.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SmallTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SmallTile.scale-400.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/StoreLogo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/StoreLogo.scale-100.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/StoreLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/StoreLogo.scale-200.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/StoreLogo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/StoreLogo.scale-400.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/Default-Portrait.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-hdpi/icon.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-mdpi/icon.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SplashScreen.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SplashScreen.scale-100.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SplashScreen.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/SplashScreen.scale-400.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/VideoStatus.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Xam.Forms.VideoPlayer
3 | {
4 | public enum VideoStatus
5 | {
6 | NotReady,
7 | Playing,
8 | Paused
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xhdpi/icon.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xxhdpi/icon.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xxxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xxxhdpi/icon.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.scale-100.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.scale-400.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Wide310x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Wide310x150Logo.scale-100.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Wide310x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Wide310x150Logo.scale-400.png
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/Resources/values/Strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Hello World, Click Me!
3 | Xam.Forms.VideoPlayer.Android
4 |
5 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square150x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square150x150Logo.scale-100.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square150x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square150x150Logo.scale-400.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.targetsize-16.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.targetsize-256.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.targetsize-48.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-hdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-hdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-mdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-mdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xhdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xhdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xxhdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xxhdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/IVideoPicker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace Xam.Forms.VideoPlayer
5 | {
6 | public interface IVideoPicker
7 | {
8 | Task GetVideoFileAsync();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.altform-unplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.altform-unplated_targetsize-16.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.altform-unplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.altform-unplated_targetsize-48.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.altform-unplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pro777s/Xam.Forms.VideoPlayer/HEAD/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Assets/Square44x44Logo.altform-unplated_targetsize-256.png
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/IVideoPlayerController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Xam.Forms.VideoPlayer
4 | {
5 | public interface IVideoPlayerController
6 | {
7 | VideoStatus Status { set; get; }
8 |
9 | TimeSpan Duration { set; get; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/IStatusBar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Xam.Forms.VideoPlayer
6 | {
7 | public interface IStatusBar
8 | {
9 | void HideStatusBar();
10 | void ShowStatusBar();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-anydpi-v26/icon.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 | #3F51B5
5 | #303F9F
6 | #FF4081
7 |
8 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/mipmap-anydpi-v26/icon_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples/App.xaml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/VideoInfo.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Xam.Forms.VideoPlayer
3 | {
4 | public class VideoInfo
5 | {
6 | public string DisplayName { set; get; }
7 |
8 | public VideoSource VideoSource { set; get; }
9 |
10 | public override string ToString()
11 | {
12 | return DisplayName;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/Xam.Forms.VideoPlayer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | Xam.Forms.VideoPlayer
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/layout/Toolbar.axml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/UriVideoSource.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 |
4 | namespace Xam.Forms.VideoPlayer
5 | {
6 | public class UriVideoSource : VideoSource
7 | {
8 | public static readonly BindableProperty UriProperty =
9 | BindableProperty.Create(nameof(Uri), typeof(string), typeof(UriVideoSource));
10 |
11 | public string Uri
12 | {
13 | set { SetValue(UriProperty, value); }
14 | get { return (string)GetValue(UriProperty); }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/FileVideoSource.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 |
4 | namespace Xam.Forms.VideoPlayer
5 | {
6 | public class FileVideoSource : VideoSource
7 | {
8 | public static readonly BindableProperty FileProperty =
9 | BindableProperty.Create(nameof(File), typeof(string), typeof(FileVideoSource));
10 |
11 | public string File
12 | {
13 | set { SetValue(FileProperty, value); }
14 | get { return (string)GetValue(FileProperty); }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/ResourceVideoSource.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 |
4 | namespace Xam.Forms.VideoPlayer
5 | {
6 | public class ResourceVideoSource : VideoSource
7 | {
8 | public static readonly BindableProperty PathProperty =
9 | BindableProperty.Create(nameof(Path), typeof(string), typeof(ResourceVideoSource));
10 |
11 | public string Path
12 | {
13 | set { SetValue(PathProperty, value); }
14 | get { return (string)GetValue(PathProperty); }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/layout/Tabbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace Xam.Forms.VideoPlayer.Samples.iOS
9 | {
10 | public class Application
11 | {
12 | // This is the main entry point of the application.
13 | static void Main(string[] args)
14 | {
15 | // if you want to use a different Application Delegate class from "AppDelegate"
16 | // you can specify it here.
17 | UIApplication.Main(args, null, "AppDelegate");
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/VideoSource.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 |
4 | namespace Xam.Forms.VideoPlayer
5 | {
6 | [TypeConverter(typeof(VideoSourceConverter))]
7 | public abstract class VideoSource : Element
8 | {
9 | public static VideoSource FromUri(string uri)
10 | {
11 | return new UriVideoSource() { Uri = uri };
12 | }
13 |
14 | public static VideoSource FromFile(string file)
15 | {
16 | return new FileVideoSource() { File = file };
17 | }
18 |
19 | public static VideoSource FromResource(string path)
20 | {
21 | return new ResourceVideoSource() { Path = path };
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/VideoSourceConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 |
4 | namespace Xam.Forms.VideoPlayer
5 | {
6 | public class VideoSourceConverter : TypeConverter
7 | {
8 | public override object ConvertFromInvariantString(string value)
9 | {
10 | if (!String.IsNullOrWhiteSpace(value))
11 | {
12 | return Uri.TryCreate(value, UriKind.Absolute, out Uri uri) && uri.Scheme != "file" ?
13 | VideoSource.FromUri(value) : VideoSource.FromResource(value);
14 | }
15 |
16 | throw new InvalidOperationException("Cannot convert null or whitespace to ImageSource");
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Assets/AboutAssets.txt:
--------------------------------------------------------------------------------
1 | Any raw assets you want to be deployed with your application can be placed in
2 | this directory (and child directories) and given a Build Action of "AndroidAsset".
3 |
4 | These files will be deployed with you package and will be accessible using Android's
5 | AssetManager, like this:
6 |
7 | public class ReadAsset : Activity
8 | {
9 | protected override void OnCreate (Bundle bundle)
10 | {
11 | base.OnCreate (bundle);
12 |
13 | InputStream input = Assets.Open ("my_asset.txt");
14 | }
15 | }
16 |
17 | Additionally, some Android functions will automatically load asset files:
18 |
19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
20 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 | namespace Xam.Forms.VideoPlayer.Samples.UWP
17 | {
18 | public sealed partial class MainPage
19 | {
20 | public MainPage()
21 | {
22 | this.InitializeComponent();
23 |
24 | LoadApplication(new Xam.Forms.VideoPlayer.Samples.App());
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
13 |
14 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.iOS/StatusBar.iOS.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | using Foundation;
7 | using UIKit;
8 | using Xam.Forms.VideoPlayer.iOS;
9 |
10 | [assembly: Xamarin.Forms.Dependency(typeof(StatusBar))]
11 |
12 | namespace Xam.Forms.VideoPlayer.iOS
13 | {
14 | public class StatusBar : IStatusBar
15 | {
16 | public StatusBar()
17 | {
18 | }
19 |
20 | #region IStatusBar implementation
21 |
22 | public void HideStatusBar()
23 | {
24 | UIApplication.SharedApplication.StatusBarHidden = true;
25 | }
26 |
27 | public void ShowStatusBar()
28 | {
29 | UIApplication.SharedApplication.StatusBarHidden = false;
30 | }
31 |
32 | #endregion
33 | }
34 | }
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 | using Xamarin.Forms.Xaml;
4 |
5 | [assembly: XamlCompilation(XamlCompilationOptions.Compile)]
6 | namespace Xam.Forms.VideoPlayer.Samples
7 | {
8 | public partial class App : Application
9 | {
10 | public App()
11 | {
12 | InitializeComponent();
13 |
14 | MainPage = new NavigationPage(new MainPage());
15 | }
16 |
17 | protected override void OnStart()
18 | {
19 | // Handle when your app starts
20 | }
21 |
22 | protected override void OnSleep()
23 | {
24 | // Handle when your app sleeps
25 | }
26 |
27 | protected override void OnResume()
28 | {
29 | // Handle when your app resumes
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/StatusBar.Android.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | using Android.App;
7 | using Android.Content;
8 | using Android.OS;
9 | using Android.Runtime;
10 | using Android.Views;
11 | using Android.Widget;
12 | using Xam.Forms.VideoPlayer.Android;
13 |
14 | [assembly: Xamarin.Forms.Dependency(typeof(StatusBar))]
15 |
16 | namespace Xam.Forms.VideoPlayer.Android
17 | {
18 | public class StatusBar : IStatusBar
19 | {
20 |
21 | #region IStatusBar implementation
22 |
23 | public void HideStatusBar()
24 | {
25 | var activity = MainActivity.Current as Activity;
26 | activity.Window.AddFlags(WindowManagerFlags.Fullscreen);
27 | }
28 |
29 | public void ShowStatusBar()
30 | {
31 | if (MainActivity.Current == null)
32 | return;
33 | var activity = MainActivity.Current as Activity;
34 | activity.Window.ClearFlags(WindowManagerFlags.Fullscreen);
35 | }
36 |
37 | #endregion
38 | }
39 | }
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.UWP/VideoPicker.UWP.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Windows.Storage;
4 | using Windows.Storage.Pickers;
5 | using Xam.Forms.VideoPlayer.UWP;
6 | using Xamarin.Forms;
7 |
8 | [assembly: Dependency(typeof(VideoPicker))]
9 |
10 | namespace Xam.Forms.VideoPlayer.UWP
11 | {
12 | public class VideoPicker : IVideoPicker
13 | {
14 | public async Task GetVideoFileAsync()
15 | {
16 | // Create and initialize the FileOpenPicker
17 | FileOpenPicker openPicker = new FileOpenPicker
18 | {
19 | ViewMode = PickerViewMode.Thumbnail,
20 | SuggestedStartLocation = PickerLocationId.VideosLibrary
21 | };
22 |
23 | openPicker.FileTypeFilter.Add(".mp3");
24 | openPicker.FileTypeFilter.Add(".mp4");
25 | openPicker.FileTypeFilter.Add(".mkv");
26 | openPicker.FileTypeFilter.Add(".wmv");
27 |
28 | // Get a file and return the path
29 | StorageFile storageFile = await openPicker.PickSingleFileAsync();
30 | return storageFile?.Path;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples/Xam.Forms.VideoPlayer.Samples.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 | pdbonly
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | MSBuild:UpdateDesignTimeXaml
23 |
24 |
25 |
26 |
27 |
28 | MSBuild:Compile
29 |
30 |
31 | MSBuild:Compile
32 |
33 |
34 | MSBuild:Compile
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.UWP/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Xam.Forms.VideoPlayer.UWP")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Xam.Forms.VideoPlayer.UWP")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Xam.Forms.VideoPlayer.Samples.UWP")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Xam.Forms.VideoPlayer.Samples.UWP")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using Android.App;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("Xam.Forms.VideoPlayer.Android")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("Xam.Forms.VideoPlayer.Android")]
14 | [assembly: AssemblyCopyright("Copyright © 2018")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: ComVisible(false)]
18 |
19 | // Version information for an assembly consists of the following four values:
20 | //
21 | // Major Version
22 | // Minor Version
23 | // Build Number
24 | // Revision
25 | //
26 | // You can specify all the values or you can default the Build and Revision Numbers
27 | // by using the '*' as shown below:
28 | // [assembly: AssemblyVersion("1.0.*")]
29 | [assembly: AssemblyVersion("1.0.0.0")]
30 | [assembly: AssemblyFileVersion("1.0.0.0")]
31 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.UWP/StatusBar.UWP.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Foundation.Metadata;
7 | using Xam.Forms.VideoPlayer.UWP;
8 |
9 | [assembly: Xamarin.Forms.Dependency(typeof(StatusBar))]
10 |
11 | namespace Xam.Forms.VideoPlayer.UWP
12 | {
13 | class StatusBar : IStatusBar
14 | {
15 | public async void HideStatusBar()
16 | {
17 | if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
18 | {
19 | var statusBar = Windows.UI.ViewManagement.StatusBar.GetForCurrentView();
20 | if (statusBar != null)
21 | {
22 | await statusBar.HideAsync();
23 | }
24 | }
25 | }
26 |
27 | public async void ShowStatusBar()
28 | {
29 | if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
30 | {
31 | var statusBar = Windows.UI.ViewManagement.StatusBar.GetForCurrentView();
32 | if (statusBar != null)
33 | {
34 | await statusBar.ShowAsync();
35 | }
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace Xam.Forms.VideoPlayer.Samples.iOS
9 | {
10 | // The UIApplicationDelegate for the application. This class is responsible for launching the
11 | // User Interface of the application, as well as listening (and optionally responding) to
12 | // application events from iOS.
13 | [Register("AppDelegate")]
14 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
15 | {
16 | //
17 | // This method is invoked when the application has loaded and is ready to run. In this
18 | // method you should instantiate the window, load the UI into it and then make the window
19 | // visible.
20 | //
21 | // You have 17 seconds to return from this method, or iOS will terminate your application.
22 | //
23 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
24 | {
25 | Xam.Forms.VideoPlayer.iOS.VideoPlayerRenderer.Init();
26 | global::Xamarin.Forms.Forms.Init();
27 | LoadApplication(new App());
28 |
29 | return base.FinishedLaunching(app, options);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Android.App;
4 | using Android.Content.PM;
5 | using Android.Runtime;
6 | using Android.Views;
7 | using Android.Widget;
8 | using Android.OS;
9 | using Android.Content;
10 |
11 | namespace Xam.Forms.VideoPlayer.Samples.Droid
12 | {
13 | [Activity(Label = "Xam.Forms.VideoPlayer.Samples", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
14 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
15 | {
16 | protected override void OnCreate(Bundle savedInstanceState)
17 | {
18 | TabLayoutResource = Resource.Layout.Tabbar;
19 | ToolbarResource = Resource.Layout.Toolbar;
20 |
21 | base.OnCreate(savedInstanceState);
22 | Xam.Forms.VideoPlayer.Android.VideoPlayerRenderer.Init();
23 | global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
24 | LoadApplication(new App());
25 | }
26 |
27 | protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
28 | {
29 | base.OnActivityResult(requestCode, resultCode, data);
30 | Android.VideoPicker.OnActivityResult(requestCode, resultCode, data);
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIDeviceFamily
6 |
7 | 1
8 | 2
9 |
10 | UISupportedInterfaceOrientations
11 |
12 | UIInterfaceOrientationPortrait
13 | UIInterfaceOrientationLandscapeLeft
14 | UIInterfaceOrientationLandscapeRight
15 |
16 | UISupportedInterfaceOrientations~ipad
17 |
18 | UIInterfaceOrientationPortrait
19 | UIInterfaceOrientationPortraitUpsideDown
20 | UIInterfaceOrientationLandscapeLeft
21 | UIInterfaceOrientationLandscapeRight
22 |
23 | CFBundleDisplayName
24 | Xam.Forms.VideoPlayer.Samples
25 | CFBundleIdentifier
26 | com.pro777.Xam-Forms-VideoPlayer-Samples
27 | CFBundleVersion
28 | 1.0
29 | UILaunchStoryboardName
30 | LaunchScreen
31 | CFBundleName
32 | Xam.Forms.VideoPlayer.Samples
33 | XSAppIconAssets
34 | Assets.xcassets/AppIcon.appiconset
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using Android.App;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("Xam.Forms.VideoPlayer.Samples.Android")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("Xam.Forms.VideoPlayer.Samples.Android")]
14 | [assembly: AssemblyCopyright("Copyright © 2014")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: ComVisible(false)]
18 |
19 | // Version information for an assembly consists of the following four values:
20 | //
21 | // Major Version
22 | // Minor Version
23 | // Build Number
24 | // Revision
25 | //
26 | // You can specify all the values or you can default the Build and Revision Numbers
27 | // by using the '*' as shown below:
28 | // [assembly: AssemblyVersion("1.0.*")]
29 | [assembly: AssemblyVersion("1.0.0.0")]
30 | [assembly: AssemblyFileVersion("1.0.0.0")]
31 |
32 | // Add some common permissions, these can be removed if not needed
33 | [assembly: UsesPermission(Android.Manifest.Permission.Internet)]
34 | [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]
35 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Xamarin.Forms;
7 |
8 | namespace Xam.Forms.VideoPlayer.Samples
9 | {
10 | public partial class MainPage : ContentPage
11 | {
12 | public MainPage()
13 | {
14 | InitializeComponent();
15 | }
16 |
17 | async void OnShowVideoLibraryClicked(object sender, EventArgs args)
18 | {
19 | Button btn = (Button)sender;
20 | btn.IsEnabled = false;
21 |
22 | string filename = await DependencyService.Get().GetVideoFileAsync();
23 |
24 | if (!String.IsNullOrWhiteSpace(filename))
25 | {
26 | FileVideoSource fileVideoSource = new FileVideoSource
27 | {
28 | File = filename
29 | };
30 | await Navigation.PushAsync(new PlayVideoPage(fileVideoSource), true);
31 | }
32 |
33 | btn.IsEnabled = true;
34 | }
35 |
36 | private async void ButtonPlayBunny_Clicked(object sender, EventArgs e)
37 | {
38 | UriVideoSource uriVideoSurce = new UriVideoSource()
39 | {
40 | Uri = "https://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"
41 | };
42 | await Navigation.PushAsync(new PlayVideoPage(uriVideoSurce), true);
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
26 |
27 |
30 |
31 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.iOS/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Xam.Forms.VideoPlayer.iOS")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Xam.Forms.VideoPlayer.iOS")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("50c7b8c9-e664-45af-b88e-0c9b8b9c1be1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Xam.Forms.VideoPlayer.Samples.iOS")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Xam.Forms.VideoPlayer.Samples.iOS")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Android.App;
7 | using Android.Content;
8 | using Android.OS;
9 | using Android.Runtime;
10 | using Android.Views;
11 | using Android.Widget;
12 |
13 | namespace Xam.Forms.VideoPlayer.Android
14 | {
15 | [Application]
16 | public partial class MainActivity : Application, Application.IActivityLifecycleCallbacks
17 | {
18 | internal static Context Current { get; private set; }
19 |
20 | public MainActivity(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer) { }
21 |
22 | public override void OnCreate()
23 | {
24 | base.OnCreate();
25 | RegisterActivityLifecycleCallbacks(this);
26 | }
27 |
28 | public override void OnTerminate()
29 | {
30 | base.OnTerminate();
31 | UnregisterActivityLifecycleCallbacks(this);
32 | }
33 |
34 | public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
35 | {
36 | Current = activity;
37 | }
38 |
39 | public void OnActivityResumed(Activity activity)
40 | {
41 | Current = activity;
42 | }
43 |
44 | public void OnActivityStarted(Activity activity)
45 | {
46 | Current = activity;
47 | }
48 |
49 | public void OnActivityDestroyed(Activity activity) { }
50 | public void OnActivityPaused(Activity activity) { }
51 | public void OnActivitySaveInstanceState(Activity activity, Bundle outState) { }
52 | public void OnActivityStopped(Activity activity) { }
53 | }
54 | }
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.UWP/Properties/Xam.Forms.VideoPlayer.UWP.rd.xml:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.axml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable/
12 | icon.png
13 |
14 | layout/
15 | main.axml
16 |
17 | values/
18 | strings.xml
19 |
20 | In order to get the build system to recognize Android resources, set the build action to
21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
22 | instead operate on resource IDs. When you compile an Android application that uses resources,
23 | the build system will package the resources for distribution and generate a class called "R"
24 | (this is an Android convention) that contains the tokens for each one of the resources
25 | included. For example, for the above Resources layout, this is what the R class would expose:
26 |
27 | public class R {
28 | public class drawable {
29 | public const int icon = 0x123;
30 | }
31 |
32 | public class layout {
33 | public const int main = 0x456;
34 | }
35 |
36 | public class strings {
37 | public const int first_string = 0xabc;
38 | public const int second_string = 0xbcd;
39 | }
40 | }
41 |
42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first
44 | string in the dictionary file values/strings.xml.
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.xml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable-hdpi/
12 | icon.png
13 |
14 | drawable-ldpi/
15 | icon.png
16 |
17 | drawable-mdpi/
18 | icon.png
19 |
20 | layout/
21 | main.xml
22 |
23 | values/
24 | strings.xml
25 |
26 | In order to get the build system to recognize Android resources, set the build action to
27 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
28 | instead operate on resource IDs. When you compile an Android application that uses resources,
29 | the build system will package the resources for distribution and generate a class called
30 | "Resource" that contains the tokens for each one of the resources included. For example,
31 | for the above Resources layout, this is what the Resource class would expose:
32 |
33 | public class Resource {
34 | public class drawable {
35 | public const int icon = 0x123;
36 | }
37 |
38 | public class layout {
39 | public const int main = 0x456;
40 | }
41 |
42 | public class strings {
43 | public const int first_string = 0xabc;
44 | public const int second_string = 0xbcd;
45 | }
46 | }
47 |
48 | You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main
49 | to reference the layout/main.xml file, or Resource.strings.first_string to reference the first
50 | string in the dictionary file values/strings.xml.
51 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/VideoPicker.Android.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Android.App;
4 | using Android.Content;
5 | using Xamarin.Forms;
6 |
7 | using Xam.Forms.VideoPlayer.Android;
8 | using Application = Android.App.Application;
9 | //using MainActivity = Xamarin.Forms.Platform.Android.FormsAppCompatActivity;
10 |
11 | [assembly: Dependency(typeof(VideoPicker))]
12 |
13 | namespace Xam.Forms.VideoPlayer.Android
14 | {
15 | public class VideoPicker : IVideoPicker
16 | {
17 | public static readonly int RequestCode = 1000;
18 | public static TaskCompletionSource TaskCompletionSource { get; set; }
19 |
20 | public Task GetVideoFileAsync()
21 | {
22 | // Define the Intent for getting images
23 | Intent intent = new Intent();
24 | intent.SetType("video/*");
25 | intent.SetAction(Intent.ActionGetContent);
26 |
27 | // Get the MainActivity instance
28 | var activity = MainActivity.Current as Activity;
29 | // Start the picker activity (resumes in MainActivity.cs)
30 | activity.StartActivityForResult(
31 | Intent.CreateChooser(intent, Resources.SelectVideo), RequestCode);
32 |
33 | //Save the TaskCompletionSource object as a MainActivity property
34 | TaskCompletionSource = new TaskCompletionSource();
35 |
36 | //Return Task object
37 | return TaskCompletionSource.Task;
38 | }
39 |
40 | public static void OnActivityResult(int requestCode, Result resultCode, Intent data)
41 | {
42 | if (requestCode == RequestCode)
43 | {
44 | if ((resultCode == Result.Ok) && (data != null))
45 | {
46 | // Set the filename as the completion of the Task
47 | TaskCompletionSource.SetResult(data.DataString);
48 | }
49 | else
50 | {
51 | TaskCompletionSource.SetResult(null);
52 | }
53 | }
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Xam.Forms.VideoPlayer.Samples.UWP
7 | 9fae93e1-bcfe-4a13-83bb-6c84139b6aef
8 | Assets\StoreLogo.png
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples/PlayVideoPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Xamarin.Forms;
8 | using Xamarin.Forms.Xaml;
9 |
10 | namespace Xam.Forms.VideoPlayer.Samples
11 | {
12 | [XamlCompilation(XamlCompilationOptions.Compile)]
13 | public partial class PlayVideoPage : ContentPage
14 | {
15 | private VideoSource _videoSource;
16 |
17 | public PlayVideoPage(VideoSource videoSource)
18 | {
19 | _videoSource = videoSource;
20 | InitializeComponent();
21 | //Device.StartTimer(TimeSpan.FromSeconds(30), () => { videoPlayer.Position += TimeSpan.FromMinutes(1); return false; });
22 | //Device.StartTimer(TimeSpan.FromSeconds(10), () => { videoPlayer.Pause(); videoPlayer.ShowTransportControls(); return false; });
23 | }
24 |
25 | protected override void OnAppearing()
26 | {
27 | base.OnAppearing();
28 | videoPlayer.Source = _videoSource;
29 | if (Device.RuntimePlatform == Device.Android)
30 | {
31 | //NavigationPage.SetHasNavigationBar(this, false);
32 | DependencyService.Get().HideStatusBar();
33 | }
34 | }
35 |
36 | private async void VideoPlayer_PlayCompletion(object sender, EventArgs e)
37 | {
38 | await Navigation.PopAsync();
39 | }
40 |
41 | private async void VideoPlayer_PlayError(object sender, VideoPlayer.PlayErrorEventArgs e)
42 | {
43 | await Navigation.PopAsync();
44 | }
45 |
46 | protected override void OnDisappearing()
47 | {
48 | if (Device.RuntimePlatform == Device.Android)
49 | {
50 | //NavigationPage.SetHasNavigationBar(this, true);
51 | DependencyService.Get().ShowStatusBar();
52 | }
53 | videoPlayer.Stop();
54 | base.OnDisappearing();
55 | }
56 |
57 | private void VideoPlayer_BufferingStart(object sender, EventArgs e)
58 | {
59 |
60 | }
61 |
62 | private void VideoPlayer_BufferingEnd(object sender, EventArgs e)
63 | {
64 |
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/PositionSlider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 |
4 | namespace Xam.Forms.VideoPlayer
5 | {
6 | public class PositionSlider : Slider
7 | {
8 | public static readonly BindableProperty DurationProperty =
9 | BindableProperty.Create(nameof(Duration), typeof(TimeSpan), typeof(PositionSlider), new TimeSpan(1),
10 | propertyChanged: (bindable, oldValue, newValue) =>
11 | {
12 | double seconds = ((TimeSpan)newValue).TotalSeconds;
13 | ((Slider)bindable).Maximum = seconds <= 0 ? 1 : seconds;
14 | });
15 |
16 | public TimeSpan Duration
17 | {
18 | set { SetValue(DurationProperty, value); }
19 | get { return (TimeSpan)GetValue(DurationProperty); }
20 | }
21 |
22 | public static readonly BindableProperty PositionProperty =
23 | BindableProperty.Create(nameof(Position), typeof(TimeSpan), typeof(PositionSlider), new TimeSpan(0),
24 | defaultBindingMode: BindingMode.TwoWay,
25 | propertyChanged: (bindable, oldValue, newValue) =>
26 | {
27 | double seconds = ((TimeSpan)newValue).TotalSeconds;
28 | ((Slider)bindable).Value = seconds;
29 | });
30 |
31 | public TimeSpan Position
32 | {
33 | set { SetValue(PositionProperty, value); }
34 | get { return (TimeSpan)GetValue(PositionProperty); }
35 | }
36 |
37 | public PositionSlider()
38 | {
39 | PropertyChanged += (sender, args) =>
40 | {
41 | if (args.PropertyName == "Value")
42 | {
43 | TimeSpan newPosition = TimeSpan.FromSeconds(Value);
44 |
45 | if (Math.Abs(newPosition.TotalSeconds - Position.TotalSeconds) / Duration.TotalSeconds > 0.01)
46 | {
47 | Position = newPosition;
48 | }
49 | }
50 | };
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.iOS/VideoPicker.iOS.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using UIKit;
4 | using Xam.Forms.VideoPlayer.iOS;
5 | using Xamarin.Forms;
6 |
7 | [assembly: Dependency(typeof(VideoPicker))]
8 |
9 | namespace Xam.Forms.VideoPlayer.iOS
10 | {
11 | public class VideoPicker : IVideoPicker
12 | {
13 | TaskCompletionSource taskCompletionSource;
14 | UIImagePickerController imagePicker;
15 |
16 | public Task GetVideoFileAsync()
17 | {
18 | // Create and define UIImagePickerController
19 | imagePicker = new UIImagePickerController
20 | {
21 | SourceType = UIImagePickerControllerSourceType.SavedPhotosAlbum,
22 | MediaTypes = new string[] { "public.movie" }
23 | };
24 |
25 | // Set event handlers
26 | imagePicker.FinishedPickingMedia += OnImagePickerFinishedPickingMedia;
27 | imagePicker.Canceled += OnImagePickerCancelled;
28 |
29 | // Present UIImagePickerController;
30 | UIWindow window = UIApplication.SharedApplication.KeyWindow;
31 | var viewController = window.RootViewController;
32 | viewController.PresentModalViewController(imagePicker, true);
33 |
34 | // Return Task object
35 | taskCompletionSource = new TaskCompletionSource();
36 | return taskCompletionSource.Task;
37 | }
38 |
39 | void OnImagePickerFinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs args)
40 | {
41 | if (args.MediaType == "public.movie")
42 | {
43 | taskCompletionSource.SetResult(args.MediaUrl.AbsoluteString);
44 | }
45 | else
46 | {
47 | taskCompletionSource.SetResult(null);
48 | }
49 | imagePicker.DismissModalViewController(true);
50 | DetachHandlers();
51 | }
52 |
53 | void OnImagePickerCancelled(object sender, EventArgs args)
54 | {
55 | taskCompletionSource.SetResult(null);
56 | imagePicker.DismissModalViewController(true);
57 | DetachHandlers();
58 | }
59 |
60 | void DetachHandlers()
61 | {
62 | imagePicker.FinishedPickingMedia -= OnImagePickerFinishedPickingMedia;
63 | imagePicker.Canceled -= OnImagePickerCancelled;
64 | }
65 | }
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # Xam.Forms.VideoPlayer control for Xamarin Forms
2 |
3 | #### Setup
4 | * Available on NuGet: https://www.nuget.org/packages/Xam.Forms.VideoPlayer/
5 | * Install in your .Net Standard 2.0 and client projects.
6 |
7 | **Platform Support**
8 |
9 | |Platform|Supported|Version|Renderer|
10 | | ------------------- | :-----------: | :-----------: | :------------------: |
11 | |Xamarin.iOS Unified|Yes|iOS 10.1+|UIView|
12 | |Xamarin.Android|Yes|API 21+|ARelativeLayout|
13 | |UWP|Yes|10.0|MediaElement|
14 |
15 | #### Usage
16 |
17 | In your Android projects (MainActivity.cs) call:
18 |
19 | ```
20 | Xam.Forms.VideoPlayer.Android.VideoPlayerRenderer.Init();
21 | Xamarin.Forms.Init();
22 | ```
23 |
24 | In your iOS projects (AppDelegate.cs) call:
25 |
26 | ```
27 | Xam.Forms.VideoPlayer.iOS.VideoPlayerRenderer.Init();
28 | Xamarin.Forms.Init();
29 | ```
30 |
31 | In UWP platform (App.xaml.cs) call:
32 |
33 | ```
34 | Xamarin.Forms.DependencyService.Register();
35 | Xam.Forms.VideoPlayer.UWP.VideoPlayerRenderer.Init();
36 | Xamarin.Forms.Forms.Init(e);
37 | ```
38 |
39 | For more information, see the folder Samples.
40 |
41 | #### Release Notes
42 |
43 | 1.0.8
44 |
45 | [All] BufferingStart and BufferingEnd events are added.
46 |
47 | 1.0.7
48 |
49 | [All] Removed ShowTransportControls property. Instead, the ShowTransportControls() and HideTransportControls() methods are added.
50 | [UWP] Project compilation error due to the lack of a Xam.Forms.VideoPlayer.UWP.xr.xml file has been fixed.
51 |
52 | 1.0.6
53 |
54 | [All] ShowTransportControls property added.
55 | [Android] Fixed bug when setting the AreTransportControlsEnabled property.
56 |
57 | 1.0.5
58 |
59 | [Android] Fixed a potential error that occurred when on get video info.
60 |
61 | 1.0.4
62 |
63 | [All] Fixed a potential error that occurred when calculating the remaining playback time.
64 | [Android] Increased font size to display video size.
65 | [Android] Fixed a error that occurred when getting info about tracks
66 |
67 | 1.0.3
68 |
69 | [Android] Fixed positioning of the button for changing the visibility of the statusbar. Added video size output.
70 |
71 | 1.0.2
72 |
73 | [Android] Changed class MainActivity. Now it implements the interface IActivityLifecycleCallbacks.
74 | [All] Made refactoring and minor bugs fixed.
75 |
76 | 1.0.1
77 |
78 | [All] Added the event handler PlayError an play error occur.
79 |
80 | 1.0.0
81 |
82 | [All] Added the ability to show/hide window statusbar using IStatusbar interface.
83 | [Android] Added the ability to enter/exit full-screen mode using FullscreenMediaController class. Added the corresponding button in the video player interface.
84 | [All] Implemented the event PlayCompletion announcing the end of playback.
85 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Resources/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples/PlayVideoPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 | Black
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
33 |
34 |
38 |
39 |
40 |
41 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "scale": "2x",
5 | "size": "20x20",
6 | "idiom": "iphone",
7 | "filename": "Icon40.png"
8 | },
9 | {
10 | "scale": "3x",
11 | "size": "20x20",
12 | "idiom": "iphone",
13 | "filename": "Icon60.png"
14 | },
15 | {
16 | "scale": "2x",
17 | "size": "29x29",
18 | "idiom": "iphone",
19 | "filename": "Icon58.png"
20 | },
21 | {
22 | "scale": "3x",
23 | "size": "29x29",
24 | "idiom": "iphone",
25 | "filename": "Icon87.png"
26 | },
27 | {
28 | "scale": "2x",
29 | "size": "40x40",
30 | "idiom": "iphone",
31 | "filename": "Icon80.png"
32 | },
33 | {
34 | "scale": "3x",
35 | "size": "40x40",
36 | "idiom": "iphone",
37 | "filename": "Icon120.png"
38 | },
39 | {
40 | "scale": "2x",
41 | "size": "60x60",
42 | "idiom": "iphone",
43 | "filename": "Icon120.png"
44 | },
45 | {
46 | "scale": "3x",
47 | "size": "60x60",
48 | "idiom": "iphone",
49 | "filename": "Icon180.png"
50 | },
51 | {
52 | "scale": "1x",
53 | "size": "20x20",
54 | "idiom": "ipad",
55 | "filename": "Icon20.png"
56 | },
57 | {
58 | "scale": "2x",
59 | "size": "20x20",
60 | "idiom": "ipad",
61 | "filename": "Icon40.png"
62 | },
63 | {
64 | "scale": "1x",
65 | "size": "29x29",
66 | "idiom": "ipad",
67 | "filename": "Icon29.png"
68 | },
69 | {
70 | "scale": "2x",
71 | "size": "29x29",
72 | "idiom": "ipad",
73 | "filename": "Icon58.png"
74 | },
75 | {
76 | "scale": "1x",
77 | "size": "40x40",
78 | "idiom": "ipad",
79 | "filename": "Icon40.png"
80 | },
81 | {
82 | "scale": "2x",
83 | "size": "40x40",
84 | "idiom": "ipad",
85 | "filename": "Icon80.png"
86 | },
87 | {
88 | "scale": "1x",
89 | "size": "76x76",
90 | "idiom": "ipad",
91 | "filename": "Icon76.png"
92 | },
93 | {
94 | "scale": "2x",
95 | "size": "76x76",
96 | "idiom": "ipad",
97 | "filename": "Icon152.png"
98 | },
99 | {
100 | "scale": "2x",
101 | "size": "83.5x83.5",
102 | "idiom": "ipad",
103 | "filename": "Icon167.png"
104 | },
105 | {
106 | "scale": "1x",
107 | "size": "1024x1024",
108 | "idiom": "ios-marketing",
109 | "filename": "Icon1024.png"
110 | }
111 | ],
112 | "properties": {},
113 | "info": {
114 | "version": 1,
115 | "author": "xcode"
116 | }
117 | }
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Этот код создан программой.
4 | // Исполняемая версия:4.0.30319.42000
5 | //
6 | // Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
7 | // повторной генерации кода.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Xam.Forms.VideoPlayer.Android {
12 | using System;
13 |
14 |
15 | ///
16 | /// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
17 | ///
18 | // Этот класс создан автоматически классом StronglyTypedResourceBuilder
19 | // с помощью такого средства, как ResGen или Visual Studio.
20 | // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
21 | // с параметром /str или перестройте свой проект VS.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Xam.Forms.VideoPlayer.Android.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Перезаписывает свойство CurrentUICulture текущего потока для всех
51 | /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Ищет локализованную строку, похожую на Select Video.
65 | ///
66 | internal static string SelectVideo {
67 | get {
68 | return ResourceManager.GetString("SelectVideo", resourceCulture);
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/Xam.Forms.VideoPlayer.Android.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {20076AA6-47DB-4CF3-A732-2148B76E1025}
9 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10 | {9ef11e43-1701-4396-8835-8392d57abb70}
11 | Library
12 | Properties
13 | Xam.Forms.VideoPlayer.Android
14 | Xam.Forms.VideoPlayer.Android
15 | 512
16 | Resources\Resource.designer.cs
17 | Off
18 | false
19 | v8.1
20 |
21 |
22 | true
23 | portable
24 | false
25 | bin\Debug\
26 | DEBUG;TRACE
27 | prompt
28 | 4
29 |
30 |
31 | pdbonly
32 | true
33 | bin\Release\
34 | TRACE
35 | prompt
36 | 4
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | True
51 | True
52 | Resources.resx
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | {7133710c-433b-4e29-989e-5a95db59cf79}
69 | Xam.Forms.VideoPlayer
70 |
71 |
72 |
73 |
74 | ResXFileCodeGenerator
75 | Resources.Designer.cs
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | 4.4.0.991265
88 |
89 |
90 |
91 |
98 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 | using Windows.UI.Xaml.Controls.Primitives;
13 | using Windows.UI.Xaml.Data;
14 | using Windows.UI.Xaml.Input;
15 | using Windows.UI.Xaml.Media;
16 | using Windows.UI.Xaml.Navigation;
17 | using Xam.Forms.VideoPlayer.UWP;
18 |
19 | namespace Xam.Forms.VideoPlayer.Samples.UWP
20 | {
21 | ///
22 | /// Provides application-specific behavior to supplement the default Application class.
23 | ///
24 | sealed partial class App : Application
25 | {
26 | ///
27 | /// Initializes the singleton application object. This is the first line of authored code
28 | /// executed, and as such is the logical equivalent of main() or WinMain().
29 | ///
30 | public App()
31 | {
32 | this.InitializeComponent();
33 | this.Suspending += OnSuspending;
34 | }
35 |
36 | ///
37 | /// Invoked when the application is launched normally by the end user. Other entry points
38 | /// will be used such as when the application is launched to open a specific file.
39 | ///
40 | /// Details about the launch request and process.
41 | protected override void OnLaunched(LaunchActivatedEventArgs e)
42 | {
43 |
44 |
45 | Frame rootFrame = Window.Current.Content as Frame;
46 |
47 | // Do not repeat app initialization when the Window already has content,
48 | // just ensure that the window is active
49 | if (rootFrame == null)
50 | {
51 | // Create a Frame to act as the navigation context and navigate to the first page
52 | rootFrame = new Frame();
53 |
54 | rootFrame.NavigationFailed += OnNavigationFailed;
55 |
56 | // For Release configuration, you need to add code to resolve dependencies,
57 | // as described here: https://docs.microsoft.com/ru-ru/xamarin/xamarin-forms/internals/dependency-resolution.
58 | Xamarin.Forms.DependencyService.Register();
59 | Xam.Forms.VideoPlayer.UWP.VideoPlayerRenderer.Init();
60 | Xamarin.Forms.Forms.Init(e);
61 |
62 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
63 | {
64 | //TODO: Load state from previously suspended application
65 | }
66 |
67 | // Place the frame in the current Window
68 | Window.Current.Content = rootFrame;
69 | }
70 |
71 | if (rootFrame.Content == null)
72 | {
73 | // When the navigation stack isn't restored navigate to the first page,
74 | // configuring the new page by passing required information as a navigation
75 | // parameter
76 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
77 | }
78 | // Ensure the current window is active
79 | Window.Current.Activate();
80 | }
81 |
82 | ///
83 | /// Invoked when Navigation to a certain page fails
84 | ///
85 | /// The Frame which failed navigation
86 | /// Details about the navigation failure
87 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
88 | {
89 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
90 | }
91 |
92 | ///
93 | /// Invoked when application execution is being suspended. Application state is saved
94 | /// without knowing whether the application will be terminated or resumed with the contents
95 | /// of memory still intact.
96 | ///
97 | /// The source of the suspend request.
98 | /// Details about the suspend request.
99 | private void OnSuspending(object sender, SuspendingEventArgs e)
100 | {
101 | var deferral = e.SuspendingOperation.GetDeferral();
102 | //TODO: Save application state and stop any background activity
103 | deferral.Complete();
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/FullScreenMediaController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | using Android.App;
7 | using Android.Content;
8 | using Android.Graphics;
9 | using Android.OS;
10 | using Android.Runtime;
11 | using Android.Util;
12 | using Android.Views;
13 | using Android.Widget;
14 |
15 | namespace Xam.Forms.VideoPlayer.Android
16 | {
17 | public class FullScreenMediaController : MediaController
18 | {
19 | private static readonly int fullScreenImageId, fullScreenExitImageId;
20 | private ImageButton ibFullScreen;
21 | private StatusBar statusBar;
22 | private TextView tvVideoSize;
23 |
24 | public FullScreenMediaController(Context context) : base(context)
25 | {
26 | statusBar = new StatusBar();
27 | }
28 |
29 | static FullScreenMediaController()
30 | {
31 | fullScreenImageId = GetResourceDrawableId("ic_fullscreen");
32 | fullScreenExitImageId = GetResourceDrawableId("ic_fullscreen_exit");
33 | }
34 |
35 | public override void SetAnchorView(View view)
36 | {
37 | base.SetAnchorView(view);
38 | ibFullScreen = new ImageButton(Context);
39 | ibFullScreen.SetBackgroundColor(Color.Transparent);
40 | int layoutPx = DiPtoPx(40, view.Context);
41 | int topMarginPx = DiPtoPx(10, view.Context);
42 | int leftMarginPx = DiPtoPx(5, view.Context);
43 | LayoutParams layoutParams =
44 | new LayoutParams(layoutPx, layoutPx, GravityFlags.NoGravity)
45 | {
46 | TopMargin = topMarginPx,
47 | LeftMargin = leftMarginPx,
48 | };
49 | int imageId = IsFullScreen() ? fullScreenExitImageId : fullScreenImageId;
50 | ibFullScreen.SetImageResource(imageId);
51 | ibFullScreen.ScaleX = 0.5f;
52 | ibFullScreen.ScaleY = 0.5f;
53 | AddView(ibFullScreen, layoutParams);
54 | ibFullScreen.SetOnClickListener(new OnClickListener());
55 | layoutParams =
56 | new LayoutParams(DiPtoPx(56, view.Context), DiPtoPx(16, view.Context), GravityFlags.Right)
57 | {
58 | TopMargin = DiPtoPx(5, view.Context),
59 | RightMargin = DiPtoPx(5, view.Context),
60 | };
61 | tvVideoSize = new TextView(Context);
62 | tvVideoSize.SetBackgroundColor(Color.Transparent);
63 | tvVideoSize.SetTextColor(Color.White);
64 | tvVideoSize.SetTextSize(ComplexUnitType.Pt, 6);
65 | tvVideoSize.Gravity = GravityFlags.Right;
66 | AddView(tvVideoSize, layoutParams);
67 | }
68 |
69 | public void ShowVideoSize(int width, int height)
70 | {
71 | if (tvVideoSize is null)
72 | return;
73 | string videoSizeText = width + "x" + height;
74 | tvVideoSize.SetText(videoSizeText.ToCharArray(), 0, videoSizeText.Length);
75 | }
76 |
77 | private static int DiPtoPx(float dp, Context context)
78 | {
79 | float fpx = TypedValue.ApplyDimension(ComplexUnitType.Dip, dp, context.Resources.DisplayMetrics);
80 | return (int)Math.Round(fpx);
81 | }
82 |
83 | private static int GetResourceDrawableId(string imageFileName)
84 | {
85 | return (int)typeof(Resource.Drawable).GetField(imageFileName).GetValue(null);
86 | }
87 |
88 | private class OnClickListener : Java.Lang.Object, IOnClickListener
89 | {
90 | void IOnClickListener.OnClick(View view)
91 | {
92 | FullScreenMediaController mediaController = view.Parent as FullScreenMediaController;
93 | mediaController.InvertScreenMode();
94 | }
95 | }
96 |
97 | private void InvertScreenMode()
98 | {
99 | if (IsFullScreen())
100 | {
101 | ExitFromFullScreen();
102 | }
103 | else
104 | {
105 | EnterToFullScreen();
106 | }
107 | }
108 |
109 | private void EnterToFullScreen()
110 | {
111 | ibFullScreen.SetImageResource(fullScreenExitImageId);
112 | statusBar.HideStatusBar();
113 | }
114 |
115 | private void ExitFromFullScreen()
116 | {
117 | ibFullScreen.SetImageResource(fullScreenImageId);
118 | statusBar.ShowStatusBar();
119 | }
120 |
121 | public static bool IsFullScreen()
122 | {
123 | var activity = MainActivity.Current as Activity;
124 | var attrs = activity.Window.Attributes;
125 | return (attrs.Flags & WindowManagerFlags.Fullscreen) == WindowManagerFlags.Fullscreen;
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.iOS/Xam.Forms.VideoPlayer.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | 8.0.30703
8 | 2.0
9 | {E71F3053-056C-4381-9638-048ED73BDFF6}
10 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
11 | {a52b8a63-bc84-4b47-910d-692533484892}
12 | Library
13 | Xam.Forms.VideoPlayer.iOS
14 | Resources
15 | Xam.Forms.VideoPlayer.iOS
16 |
17 |
18 |
19 |
20 | true
21 | full
22 | false
23 | bin\Debug
24 | DEBUG;
25 | prompt
26 | 4
27 | false
28 |
29 |
30 | full
31 | true
32 | bin\Release
33 | prompt
34 | 4
35 | false
36 |
37 |
38 |
39 |
40 |
41 |
42 | ..\packages\Xamarin.Forms.4.4.0.991265\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll
43 |
44 |
45 | ..\packages\Xamarin.Forms.4.4.0.991265\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll
46 |
47 |
48 | ..\packages\Xamarin.Forms.4.4.0.991265\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll
49 |
50 |
51 | ..\packages\Xamarin.Forms.4.4.0.991265\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | {7133710c-433b-4e29-989e-5a95db59cf79}
67 | Xam.Forms.VideoPlayer
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | Данный проект ссылается на пакеты NuGet, отсутствующие на этом компьютере. Используйте восстановление пакетов NuGet, чтобы скачать их. Дополнительную информацию см. по адресу: http://go.microsoft.com/fwlink/?LinkID=322105. Отсутствует следующий файл: {0}.
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/Nuget/Xam.Forms.VideoPlayer.1.0.8.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Xam.Forms.VideoPlayer
5 | 1.0.8
6 | Video Player Control for Xamarin.Forms
7 | Roman Pristinsky
8 | pro777
9 | https://github.com/pro777s/Xam.Forms.VideoPlayer
10 | false
11 | MIT
12 |
13 | The package Xam.Forms.VideoPlayer is intended for Xamarin.Forms, contains a cross-platform video player for Android, iOS and Windows UWP, based on the code provided by Charles Petzold.
14 | More information about the video player can be found here: https://docs.microsoft.com/ru-ru/samples/xamarin/xamarin-forms-samples/customrenderers-videoplayerdemos/.
15 | This package can be freely used for distribution, commercial use and modification.
16 | The package Xam.Forms.VideoPlayer is intended for Xamarin.Forms, contains a cross-platform video player for Android, iOS and Windows UWP, based on the code provided by Charles Petzold.
17 |
18 | 1.0.8
19 | [All] BufferingStart and BufferingEnd events are added.
20 | 1.0.7
21 | [All] Removed ShowTransportControls property. Instead, the ShowTransportControls() and HideTransportControls() methods are added.
22 | [UWP] Project compilation error due to the lack of a Xam.Forms.VideoPlayer.UWP.xr.xml file has been fixed.
23 | 1.0.6
24 | [All] ShowTransportControls property added.
25 | [Android] Fixed bug when setting the AreTransportControlsEnabled property.
26 | 1.0.5
27 | [Android] Fixed a potential error that occurred when on get video info.
28 | 1.0.4
29 | [All] Fixed a potential error that occurred when calculating the remaining playback time.
30 | [Android] Increased font size to display video size.
31 | [Android] Fixed a error that occurred when getting info about tracks
32 | 1.0.3
33 | [Android] Fixed positioning of the button for changing the visibility of the statusbar. Added video size output.
34 | 1.0.2
35 | [Android] Changed class MainActivity. Now it implements the interface IActivityLifecycleCallbacks.
36 | [All] Made refactoring and minor bugs fixed.
37 | 1.0.1
38 | [All] Added the event handler PlayError an play error occur. Made changes to the file nuspec.
39 | 1.0.0
40 | [All] Added the ability to show/hide window statusbar using IStatusbar interface.
41 | [Android] Added the ability to enter/exit full-screen mode using FullscreenMediaController class. Added the corresponding button in the video player interface.
42 | [All] Implemented the event PlayCompletion announcing the end of playback.
43 | Xamarin, VideoPlayer
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.Android/Xam.Forms.VideoPlayer.Samples.Android.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {532232AA-7D07-4B9B-8B16-580034A09A46}
7 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | {c9e5eea5-ca05-42a1-839b-61506e0a37df}
9 | Library
10 | Xam.Forms.VideoPlayer.Samples.Droid
11 | Xam.Forms.VideoPlayer.Samples.Android
12 | True
13 | Resources\Resource.designer.cs
14 | Resource
15 | Properties\AndroidManifest.xml
16 | Resources
17 | Assets
18 | false
19 | v8.1
20 | Xamarin.Android.Net.AndroidClientHandler
21 |
22 |
23 |
24 |
25 | true
26 | portable
27 | false
28 | bin\Debug
29 | DEBUG;
30 | prompt
31 | 4
32 | None
33 | false
34 | false
35 | false
36 |
37 |
38 | true
39 | pdbonly
40 | true
41 | bin\Release
42 | prompt
43 | 4
44 | true
45 | false
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | 4.4.0.991265
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | {20076aa6-47db-4cf3-a732-2148b76e1025}
102 | Xam.Forms.VideoPlayer.Android
103 |
104 |
105 | {67C2BBB1-2E92-42D1-8C69-78962C11D161}
106 | Xam.Forms.VideoPlayer.Samples
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Select Video
122 |
123 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/Resources.ru.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Выберите видео
122 |
123 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.iOS/Xam.Forms.VideoPlayer.Samples.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | iPhoneSimulator
6 | 8.0.30703
7 | 2.0
8 | {BC6F0BAB-01BA-4F8E-AB20-745C7E903638}
9 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10 | {6143fdea-f3c2-4a09-aafa-6e230626515e}
11 | Exe
12 | Xam.Forms.VideoPlayer.Samples.iOS
13 | Resources
14 | Xam.Forms.VideoPlayer.Samples.iOS
15 | NSUrlSessionHandler
16 |
17 |
18 |
19 |
20 | true
21 | full
22 | false
23 | bin\iPhoneSimulator\Debug
24 | DEBUG
25 | prompt
26 | 4
27 | false
28 | x86_64
29 | None
30 | true
31 |
32 |
33 | none
34 | true
35 | bin\iPhoneSimulator\Release
36 | prompt
37 | 4
38 | None
39 | x86_64
40 | false
41 |
42 |
43 | true
44 | full
45 | false
46 | bin\iPhone\Debug
47 | DEBUG
48 | prompt
49 | 4
50 | false
51 | ARM64
52 | iPhone Developer: dc06@yandex.ru (5RHU4FPA8A)
53 | true
54 | Entitlements.plist
55 |
56 |
57 | none
58 | true
59 | bin\iPhone\Release
60 | prompt
61 | 4
62 | ARM64
63 | false
64 | iPhone Developer
65 | Entitlements.plist
66 |
67 |
68 | none
69 | True
70 | bin\iPhone\Ad-Hoc
71 | prompt
72 | 4
73 | False
74 | ARM64
75 | True
76 | Automatic:AdHoc
77 | iPhone Distribution
78 | Entitlements.plist
79 |
80 |
81 | none
82 | True
83 | bin\iPhone\AppStore
84 | prompt
85 | 4
86 | False
87 | ARM64
88 | Automatic:AppStore
89 | iPhone Distribution
90 | Entitlements.plist
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | false
103 |
104 |
105 | false
106 |
107 |
108 | false
109 |
110 |
111 | false
112 |
113 |
114 | false
115 |
116 |
117 | false
118 |
119 |
120 | false
121 |
122 |
123 | false
124 |
125 |
126 | false
127 |
128 |
129 | false
130 |
131 |
132 | false
133 |
134 |
135 | false
136 |
137 |
138 | false
139 |
140 |
141 | false
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | {e71f3053-056c-4381-9638-048ed73bdff6}
154 | Xam.Forms.VideoPlayer.iOS
155 | false
156 | false
157 |
158 |
159 | {67C2BBB1-2E92-42D1-8C69-78962C11D161}
160 | Xam.Forms.VideoPlayer.Samples
161 |
162 |
163 |
164 |
165 | 4.4.0.991265
166 |
167 |
168 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.UWP/Xam.Forms.VideoPlayer.UWP.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B8C0F852-1501-4146-B424-5766014EF4D9}
8 | Library
9 | Properties
10 | Xam.Forms.VideoPlayer.UWP
11 | Xam.Forms.VideoPlayer.UWP
12 | ru-RU
13 | UAP
14 | 10.0.18362.0
15 | 10.0.17763.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 |
20 |
21 | AnyCPU
22 | true
23 | full
24 | false
25 | bin\Debug\
26 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
27 | prompt
28 | 4
29 |
30 |
31 | AnyCPU
32 | pdbonly
33 | true
34 | bin\Release\
35 | TRACE;NETFX_CORE;WINDOWS_UWP
36 | prompt
37 | 4
38 |
39 |
40 | x86
41 | true
42 | bin\x86\Debug\
43 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
44 | ;2008
45 | full
46 | false
47 | prompt
48 |
49 |
50 | x86
51 | bin\x86\Release\
52 | TRACE;NETFX_CORE;WINDOWS_UWP
53 | true
54 | ;2008
55 | pdbonly
56 | false
57 | prompt
58 |
59 |
60 | ARM
61 | true
62 | bin\ARM\Debug\
63 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
64 | ;2008
65 | full
66 | false
67 | prompt
68 |
69 |
70 | ARM
71 | bin\ARM\Release\
72 | TRACE;NETFX_CORE;WINDOWS_UWP
73 | true
74 | ;2008
75 | pdbonly
76 | false
77 | prompt
78 |
79 |
80 | ARM64
81 | true
82 | bin\ARM64\Debug\
83 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
84 | ;2008
85 | full
86 | false
87 | prompt
88 |
89 |
90 | ARM64
91 | bin\ARM64\Release\
92 | TRACE;NETFX_CORE;WINDOWS_UWP
93 | true
94 | ;2008
95 | pdbonly
96 | false
97 | prompt
98 |
99 |
100 | x64
101 | true
102 | bin\x64\Debug\
103 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
104 | ;2008
105 | full
106 | false
107 | prompt
108 |
109 |
110 | x64
111 | bin\x64\Release\
112 | TRACE;NETFX_CORE;WINDOWS_UWP
113 | true
114 | ;2008
115 | pdbonly
116 | false
117 | prompt
118 |
119 |
120 | PackageReference
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | 6.2.10
132 |
133 |
134 | 4.4.0.991265
135 |
136 |
137 |
138 |
139 | {7133710c-433b-4e29-989e-5a95db59cf79}
140 | Xam.Forms.VideoPlayer
141 |
142 |
143 |
144 |
145 | Windows Mobile Extensions for the UWP
146 |
147 |
148 |
149 | 14.0
150 |
151 |
152 |
159 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer/VideoPlayer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using Xamarin.Forms;
4 |
5 | namespace Xam.Forms.VideoPlayer
6 | {
7 | public class VideoPlayer : View, IVideoPlayerController
8 | {
9 | public event EventHandler UpdateStatus;
10 |
11 | public VideoPlayer()
12 | {
13 | Device.StartTimer(TimeSpan.FromMilliseconds(100), () =>
14 | {
15 | UpdateStatus?.Invoke(this, EventArgs.Empty);
16 | return true;
17 | });
18 | }
19 |
20 | // AreTransportControlsEnabled property
21 | public static readonly BindableProperty AreTransportControlsEnabledProperty =
22 | BindableProperty.Create(nameof(AreTransportControlsEnabled), typeof(bool), typeof(VideoPlayer), true);
23 |
24 | public bool AreTransportControlsEnabled
25 | {
26 | set { SetValue(AreTransportControlsEnabledProperty, value); }
27 | get { return (bool)GetValue(AreTransportControlsEnabledProperty); }
28 | }
29 |
30 | // Source property
31 | public static readonly BindableProperty SourceProperty =
32 | BindableProperty.Create(nameof(Source), typeof(VideoSource), typeof(VideoPlayer), null);
33 |
34 | [TypeConverter(typeof(VideoSourceConverter))]
35 | public VideoSource Source
36 | {
37 | set { SetValue(SourceProperty, value); }
38 | get { return (VideoSource)GetValue(SourceProperty); }
39 | }
40 |
41 | // AutoPlay property
42 | public static readonly BindableProperty AutoPlayProperty =
43 | BindableProperty.Create(nameof(AutoPlay), typeof(bool), typeof(VideoPlayer), true);
44 |
45 | public bool AutoPlay
46 | {
47 | set { SetValue(AutoPlayProperty, value); }
48 | get { return (bool)GetValue(AutoPlayProperty); }
49 | }
50 |
51 | // Status read-only property
52 | private static readonly BindablePropertyKey StatusPropertyKey =
53 | BindableProperty.CreateReadOnly(nameof(Status), typeof(VideoStatus), typeof(VideoPlayer), VideoStatus.NotReady);
54 |
55 | public static readonly BindableProperty StatusProperty = StatusPropertyKey.BindableProperty;
56 |
57 | public VideoStatus Status
58 | {
59 | get { return (VideoStatus)GetValue(StatusProperty); }
60 | }
61 |
62 | VideoStatus IVideoPlayerController.Status
63 | {
64 | set { SetValue(StatusPropertyKey, value); }
65 | get { return Status; }
66 | }
67 |
68 | // Duration read-only property
69 | private static readonly BindablePropertyKey DurationPropertyKey =
70 | BindableProperty.CreateReadOnly(nameof(Duration), typeof(TimeSpan), typeof(VideoPlayer), new TimeSpan(),
71 | propertyChanged: (bindable, oldValue, newValue) => ((VideoPlayer)bindable).SetTimeToEnd());
72 |
73 | public static readonly BindableProperty DurationProperty = DurationPropertyKey.BindableProperty;
74 |
75 | public TimeSpan Duration
76 | {
77 | get { return (TimeSpan)GetValue(DurationProperty); }
78 | }
79 |
80 | TimeSpan IVideoPlayerController.Duration
81 | {
82 | set { SetValue(DurationPropertyKey, value); }
83 | get { return Duration; }
84 | }
85 |
86 | // Position property
87 | public static readonly BindableProperty PositionProperty =
88 | BindableProperty.Create(nameof(Position), typeof(TimeSpan), typeof(VideoPlayer), new TimeSpan(),
89 | propertyChanged: (bindable, oldValue, newValue) => ((VideoPlayer)bindable).SetTimeToEnd());
90 |
91 | public TimeSpan Position
92 | {
93 | set { SetValue(PositionProperty, value); }
94 | get { return (TimeSpan)GetValue(PositionProperty); }
95 | }
96 |
97 | // TimeToEnd property
98 | private static readonly BindablePropertyKey TimeToEndPropertyKey =
99 | BindableProperty.CreateReadOnly(nameof(TimeToEnd), typeof(TimeSpan), typeof(VideoPlayer), new TimeSpan());
100 |
101 | public static readonly BindableProperty TimeToEndProperty = TimeToEndPropertyKey.BindableProperty;
102 |
103 | public TimeSpan TimeToEnd
104 | {
105 | private set { SetValue(TimeToEndPropertyKey, value); }
106 | get { return (TimeSpan)GetValue(TimeToEndProperty); }
107 | }
108 |
109 | void SetTimeToEnd()
110 | {
111 | try { TimeToEnd = Duration - Position; }
112 | catch (Exception ex)
113 | {
114 | Debug.WriteLine(ex.Message);
115 | Debug.WriteLine("Duration: {Duration}");
116 | Debug.WriteLine("Position: {Position}");
117 | }
118 | }
119 |
120 | // IsBuffering property
121 | public static readonly BindableProperty IsBufferingProperty = BindableProperty.Create(
122 | propertyName: "IsBuffering",
123 | returnType: typeof(Boolean),
124 | declaringType: typeof(VideoPlayer),
125 | defaultValue: false,
126 | defaultBindingMode: BindingMode.TwoWay);
127 | public Boolean IsBuffering
128 | {
129 | get { return (Boolean)GetValue(IsBufferingProperty); }
130 | set { SetValue(IsBufferingProperty, value); }
131 | }
132 |
133 | // Methods handled by renderers
134 | public event EventHandler PlayRequested;
135 |
136 | public void Play()
137 | {
138 | PlayRequested?.Invoke(this, EventArgs.Empty);
139 | }
140 |
141 | public event EventHandler PauseRequested;
142 |
143 | public void Pause()
144 | {
145 | PauseRequested?.Invoke(this, EventArgs.Empty);
146 | }
147 |
148 | public event EventHandler StopRequested;
149 |
150 | public void Stop()
151 | {
152 | StopRequested?.Invoke(this, EventArgs.Empty);
153 | }
154 |
155 | public event EventHandler ShowTransportControlsRequested;
156 |
157 | public void ShowTransportControls()
158 | {
159 | ShowTransportControlsRequested?.Invoke(this, EventArgs.Empty);
160 | }
161 |
162 | public event EventHandler HideTransportControlsRequested;
163 |
164 | public void HideTransportControls()
165 | {
166 | HideTransportControlsRequested?.Invoke(this, EventArgs.Empty);
167 | }
168 |
169 | public event EventHandler PlayCompletion;
170 |
171 | public void OnPlayCompletion()
172 | {
173 | PlayCompletion?.Invoke(this, EventArgs.Empty);
174 | }
175 |
176 | public class PlayErrorEventArgs : EventArgs
177 | {
178 | public string ErrorMessage;
179 | public PlayErrorEventArgs(string errorMessage) { ErrorMessage = errorMessage; }
180 | }
181 | public delegate void PlayErrorEventHandler(object sender, PlayErrorEventArgs e);
182 | public event PlayErrorEventHandler PlayError;
183 |
184 | public void OnPlayError(object sender, PlayErrorEventArgs e)
185 | {
186 | PlayError?.Invoke(this, e);
187 | }
188 |
189 | public event EventHandler BufferingStart;
190 |
191 | public void OnBufferingStart()
192 | {
193 | if(IsBuffering == false)
194 | {
195 | IsBuffering = true;
196 | BufferingStart?.Invoke(this, EventArgs.Empty);
197 | }
198 | }
199 |
200 | public event EventHandler BufferingEnd;
201 |
202 | public void OnBufferingEnd()
203 | {
204 | if (IsBuffering)
205 | {
206 | IsBuffering = false;
207 | BufferingEnd?.Invoke(this, EventArgs.Empty);
208 | }
209 | }
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/Samples/Xam.Forms.VideoPlayer.Samples.UWP/Xam.Forms.VideoPlayer.Samples.UWP.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {6F7C2A83-F1F7-4DB0-889B-92A2A71B5350}
8 | AppContainerExe
9 | Properties
10 | Xam.Forms.VideoPlayer.Samples.UWP
11 | Xam.Forms.VideoPlayer.Samples.UWP
12 | en-US
13 | UAP
14 | 10.0.18362.0
15 | 10.0.17763.0
16 | 14
17 | true
18 | 512
19 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
20 | Xam.Forms.VideoPlayer.Samples.UWP_TemporaryKey.pfx
21 |
22 |
23 | true
24 | bin\ARM\Debug\
25 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
26 | ;2008
27 | full
28 | ARM
29 | false
30 | prompt
31 | true
32 |
33 |
34 | bin\ARM\Release\
35 | TRACE;NETFX_CORE;WINDOWS_UWP
36 | true
37 | ;2008
38 | pdbonly
39 | ARM
40 | false
41 | prompt
42 | true
43 | true
44 |
45 |
46 | true
47 | bin\x64\Debug\
48 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
49 | ;2008
50 | full
51 | x64
52 | false
53 | prompt
54 | true
55 |
56 |
57 | bin\x64\Release\
58 | TRACE;NETFX_CORE;WINDOWS_UWP
59 | true
60 | ;2008
61 | pdbonly
62 | x64
63 | false
64 | prompt
65 | true
66 | true
67 |
68 |
69 | true
70 | bin\x86\Debug\
71 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
72 | ;2008
73 | full
74 | x86
75 | false
76 | prompt
77 | true
78 |
79 |
80 | bin\x86\Release\
81 | TRACE;NETFX_CORE;WINDOWS_UWP
82 | true
83 | ;2008
84 | pdbonly
85 | x86
86 | false
87 | prompt
88 | true
89 | true
90 |
91 |
92 |
93 | App.xaml
94 |
95 |
96 | MainPage.xaml
97 |
98 |
99 |
100 |
101 |
102 | Designer
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | MSBuild:Compile
138 | Designer
139 |
140 |
141 | MSBuild:Compile
142 | Designer
143 |
144 |
145 |
146 |
147 |
148 | 4.4.0.991265
149 |
150 |
151 |
152 |
153 | {b8c0f852-1501-4146-b424-5766014ef4d9}
154 | Xam.Forms.VideoPlayer.UWP
155 |
156 |
157 | {67C2BBB1-2E92-42D1-8C69-78962C11D161}
158 | Xam.Forms.VideoPlayer.Samples
159 |
160 |
161 |
162 | 14.0
163 |
164 |
165 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.UWP/VideoPlayerRenderer.UWP.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | using Windows.Storage;
5 | using Windows.Storage.Streams;
6 | using Windows.UI.Xaml;
7 | using Windows.UI.Xaml.Controls;
8 | using Windows.UI.Xaml.Media;
9 |
10 | using Xamarin.Forms;
11 | using Xamarin.Forms.Platform.UWP;
12 |
13 | [assembly: ExportRenderer(typeof(Xam.Forms.VideoPlayer.VideoPlayer),
14 | typeof(Xam.Forms.VideoPlayer.UWP.VideoPlayerRenderer))]
15 |
16 | namespace Xam.Forms.VideoPlayer.UWP
17 | {
18 | public class VideoPlayerRenderer : ViewRenderer
19 | {
20 | public static void Init() { }
21 |
22 | protected override void OnElementChanged(ElementChangedEventArgs args)
23 | {
24 | base.OnElementChanged(args);
25 |
26 | if (args.NewElement != null)
27 | {
28 | if (Control == null)
29 | {
30 | MediaElement mediaElement = new MediaElement();
31 | SetNativeControl(mediaElement);
32 |
33 | mediaElement.MediaOpened += OnMediaElementMediaOpened;
34 | mediaElement.CurrentStateChanged += OnMediaElementCurrentStateChanged;
35 | mediaElement.MediaEnded += OnMediaElement_MediaEnded;
36 | mediaElement.MediaFailed += MediaElement_MediaFailed;
37 | }
38 |
39 | SetAreTransportControlsEnabled();
40 | SetSource();
41 | SetAutoPlay();
42 |
43 | args.NewElement.UpdateStatus += OnUpdateStatus;
44 | args.NewElement.PlayRequested += OnPlayRequested;
45 | args.NewElement.PauseRequested += OnPauseRequested;
46 | args.NewElement.StopRequested += OnStopRequested;
47 | args.NewElement.ShowTransportControlsRequested += OnShowTransportControls;
48 | args.NewElement.HideTransportControlsRequested += OnHideTransportControls;
49 | }
50 |
51 | if (args.OldElement != null)
52 | {
53 | args.OldElement.UpdateStatus -= OnUpdateStatus;
54 | args.OldElement.PlayRequested -= OnPlayRequested;
55 | args.OldElement.PauseRequested -= OnPauseRequested;
56 | args.OldElement.StopRequested -= OnStopRequested;
57 | args.OldElement.ShowTransportControlsRequested -= OnShowTransportControls;
58 | args.OldElement.HideTransportControlsRequested -= OnHideTransportControls;
59 | }
60 | }
61 |
62 | private void OnMediaElement_MediaEnded(object sender, RoutedEventArgs e)
63 | {
64 | Element.OnPlayCompletion();
65 | }
66 |
67 | private void MediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e)
68 | {
69 | Element.OnPlayError(sender, new VideoPlayer.PlayErrorEventArgs(e.ErrorMessage));
70 | }
71 |
72 | protected override void Dispose(bool disposing)
73 | {
74 | if (Control != null)
75 | {
76 | Control.MediaOpened -= OnMediaElementMediaOpened;
77 | Control.CurrentStateChanged -= OnMediaElementCurrentStateChanged;
78 | }
79 |
80 | base.Dispose(disposing);
81 | }
82 |
83 | void OnMediaElementMediaOpened(object sender, RoutedEventArgs args)
84 | {
85 | ((IVideoPlayerController)Element).Duration = Control.NaturalDuration.TimeSpan;
86 | }
87 |
88 | void OnMediaElementCurrentStateChanged(object sender, RoutedEventArgs args)
89 | {
90 | VideoStatus videoStatus = VideoStatus.NotReady;
91 |
92 | switch (Control.CurrentState)
93 | {
94 | case MediaElementState.Buffering:
95 | Element.OnBufferingStart();
96 | break;
97 | case MediaElementState.Playing:
98 | Element.OnBufferingEnd();
99 | videoStatus = VideoStatus.Playing;
100 | break;
101 | case MediaElementState.Paused:
102 | case MediaElementState.Stopped:
103 | Element.OnBufferingEnd();
104 | videoStatus = VideoStatus.Paused;
105 | break;
106 | }
107 |
108 | ((IVideoPlayerController)Element).Status = videoStatus;
109 | }
110 |
111 | protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
112 | {
113 | base.OnElementPropertyChanged(sender, args);
114 |
115 | if (args.PropertyName == VideoPlayer.AreTransportControlsEnabledProperty.PropertyName)
116 | {
117 | SetAreTransportControlsEnabled();
118 | }
119 | else if (args.PropertyName == VideoPlayer.SourceProperty.PropertyName)
120 | {
121 | SetSource();
122 | }
123 | else if (args.PropertyName == VideoPlayer.AutoPlayProperty.PropertyName)
124 | {
125 | SetAutoPlay();
126 | }
127 | else if (args.PropertyName == VideoPlayer.PositionProperty.PropertyName)
128 | {
129 | if (!Control.CanSeek)
130 | return;
131 | if (Math.Abs((Control.Position - Element.Position).TotalSeconds) > 1)
132 | {
133 | if (Element.AreTransportControlsEnabled)
134 | {
135 | Control.TransportControls.Show();
136 | Device.StartTimer(TimeSpan.FromSeconds(2), () =>
137 | {
138 | Control.TransportControls.Hide();
139 | return false;
140 | });
141 | }
142 | Control.Position = Element.Position;
143 | }
144 | }
145 | }
146 |
147 | private void OnShowTransportControls(object sender, EventArgs args)
148 | {
149 | if (Element.AreTransportControlsEnabled)
150 | {
151 | Control.TransportControls.Show();
152 | }
153 | }
154 |
155 | private void OnHideTransportControls(object sender, EventArgs args)
156 | {
157 | if (Element.AreTransportControlsEnabled)
158 | {
159 | Control.TransportControls.Hide();
160 | }
161 | }
162 |
163 | void SetAreTransportControlsEnabled()
164 | {
165 | Control.AreTransportControlsEnabled = Element.AreTransportControlsEnabled;
166 | }
167 |
168 | async void SetSource()
169 | {
170 | bool hasSetSource = false;
171 |
172 | if (Element.Source is UriVideoSource)
173 | {
174 | string uri = (Element.Source as UriVideoSource).Uri;
175 |
176 | if (!String.IsNullOrWhiteSpace(uri))
177 | {
178 | Control.Source = new Uri(uri);
179 | hasSetSource = true;
180 | }
181 | }
182 | else if (Element.Source is FileVideoSource)
183 | {
184 | // Code requires Pictures Library in Package.appxmanifest Capabilities to be enabled
185 | string filename = (Element.Source as FileVideoSource).File;
186 |
187 | if (!String.IsNullOrWhiteSpace(filename))
188 | {
189 | StorageFolder storageFolder = KnownFolders.VideosLibrary;
190 | StorageFile storageFile = await storageFolder.GetFileAsync(System.IO.Path.GetFileName(filename));
191 | //StorageFile storageFile = await StorageFile.GetFileFromPathAsync(filename);
192 | IRandomAccessStreamWithContentType stream = await storageFile.OpenReadAsync();
193 | Control.SetSource(stream, storageFile.ContentType);
194 | hasSetSource = true;
195 | }
196 | }
197 | else if (Element.Source is ResourceVideoSource)
198 | {
199 | string path = "ms-appx:///" + (Element.Source as ResourceVideoSource).Path;
200 |
201 | if (!String.IsNullOrWhiteSpace(path))
202 | {
203 | Control.Source = new Uri(path);
204 | hasSetSource = true;
205 | }
206 | }
207 |
208 | if (!hasSetSource)
209 | {
210 | Control.Source = null;
211 | }
212 | }
213 |
214 | void SetAutoPlay()
215 | {
216 | Control.AutoPlay = Element.AutoPlay;
217 | }
218 |
219 | // Event handler to update status
220 | void OnUpdateStatus(object sender, EventArgs args)
221 | {
222 | ((IElementController)Element).SetValueFromRenderer(VideoPlayer.PositionProperty, Control.Position);
223 | }
224 |
225 | // Event handlers to implement methods
226 | void OnPlayRequested(object sender, EventArgs args)
227 | {
228 | Control.Play();
229 | }
230 |
231 | void OnPauseRequested(object sender, EventArgs args)
232 | {
233 | Control.Pause();
234 | }
235 |
236 | void OnStopRequested(object sender, EventArgs args)
237 | {
238 | Control.Stop();
239 | }
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.Android/VideoPlayerRenderer.Android.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.IO;
4 |
5 | using Android.App;
6 | using Android.Content;
7 | using Android.Widget;
8 | using NSUri = Android.Net.Uri;
9 | using ARelativeLayout = Android.Widget.RelativeLayout;
10 |
11 | using Xamarin.Forms;
12 | using Xamarin.Forms.Platform.Android;
13 | using Xam.Forms.VideoPlayer;
14 | using Xam.Forms.VideoPlayer.Android;
15 | using Android.Graphics;
16 | using Android.Media;
17 | using System.Collections.Generic;
18 | using System.Linq;
19 | using Android.Runtime;
20 | using Java.Util;
21 | using Color = Android.Graphics.Color;
22 |
23 | [assembly: ExportRenderer(typeof(VideoPlayer), typeof(VideoPlayerRenderer))]
24 |
25 | namespace Xam.Forms.VideoPlayer.Android
26 | {
27 | public class MediaPlayerVideoSizeChangedListener : Java.Lang.Object, MediaPlayer.IOnVideoSizeChangedListener
28 | {
29 | void MediaPlayer.IOnVideoSizeChangedListener.OnVideoSizeChanged(MediaPlayer mp, int width, int height)
30 | {
31 |
32 | }
33 | }
34 |
35 | public class VideoPlayerRenderer : ViewRenderer
36 | {
37 | VideoView videoView;
38 | FullScreenMediaController mediaController; // Used to display transport controls
39 | bool isPrepared;
40 | int videoHeight, videoWidth;
41 |
42 | public VideoPlayerRenderer(Context context) : base(context)
43 | {
44 | }
45 |
46 | public static void Init() { }
47 |
48 | protected override void OnElementChanged(ElementChangedEventArgs args)
49 | {
50 | base.OnElementChanged(args);
51 |
52 | if (args.NewElement != null)
53 | {
54 | if (Control == null)
55 | {
56 | // Save the VideoView for future reference
57 | videoView = new VideoView(Context);
58 | videoView.SetBackgroundColor(Color.Transparent);
59 | videoView.Info += VideoView_Info;
60 | videoView.Completion += VideoView_Completion;
61 | videoView.Error += VideoView_Error;
62 |
63 | // Put the VideoView in a RelativeLayout
64 | ARelativeLayout relativeLayout = new ARelativeLayout(Context);
65 | relativeLayout.AddView(videoView);
66 |
67 | // Center the VideoView in the RelativeLayout
68 | ARelativeLayout.LayoutParams layoutParams =
69 | new ARelativeLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent);
70 | layoutParams.AddRule(LayoutRules.CenterInParent);
71 | videoView.LayoutParameters = layoutParams;
72 |
73 | // Handle a VideoView event
74 | videoView.Prepared += OnVideoViewPrepared;
75 |
76 | SetNativeControl(relativeLayout);
77 | }
78 |
79 | SetAreTransportControlsEnabled();
80 | SetSource();
81 |
82 | args.NewElement.UpdateStatus += OnUpdateStatus;
83 | args.NewElement.PlayRequested += OnPlayRequested;
84 | args.NewElement.PauseRequested += OnPauseRequested;
85 | args.NewElement.StopRequested += OnStopRequested;
86 | args.NewElement.ShowTransportControlsRequested += OnShowTransportControls;
87 | args.NewElement.HideTransportControlsRequested += OnHideTransportControls;
88 | }
89 |
90 | if (args.OldElement != null)
91 | {
92 | args.OldElement.UpdateStatus -= OnUpdateStatus;
93 | args.OldElement.PlayRequested -= OnPlayRequested;
94 | args.OldElement.PauseRequested -= OnPauseRequested;
95 | args.OldElement.StopRequested -= OnStopRequested;
96 | args.OldElement.ShowTransportControlsRequested -= OnShowTransportControls;
97 | args.OldElement.HideTransportControlsRequested -= OnHideTransportControls;
98 | }
99 | }
100 |
101 | private void VideoView_Error(object sender, MediaPlayer.ErrorEventArgs e)
102 | {
103 | Element.OnPlayError(sender, new VideoPlayer.PlayErrorEventArgs(e.What.ToString()));
104 | }
105 |
106 | private void VideoView_Completion(object sender, EventArgs e)
107 | {
108 | Element.OnPlayCompletion();
109 | }
110 |
111 | private void VideoView_Info(object sender, MediaPlayer.InfoEventArgs e)
112 | {
113 | try
114 | {
115 | switch (e.What)
116 | {
117 | case MediaInfo.BufferingStart:
118 | Element.OnBufferingStart();
119 | break;
120 | case MediaInfo.BufferingEnd:
121 | Element.OnBufferingEnd();
122 | break;
123 | case MediaInfo.VideoRenderingStart:
124 | //e.Mp.SetOnVideoSizeChangedListener(new MediaPlayerVideoSizeChangedListener());
125 | MediaPlayer.TrackInfo[] trackInfoArray = e.Mp.GetTrackInfo();
126 | if (trackInfoArray != null)
127 | {
128 | for (int i = 0; i < trackInfoArray.Length; i++)
129 | {
130 | // you can switch out the language comparison logic to whatever works for you
131 | if (trackInfoArray[i].TrackType == MediaTrackType.Audio
132 | && trackInfoArray[i].Language == Locale.Default.ISO3Language)
133 | {
134 | e.Mp.SelectTrack(i);
135 | break;
136 | }
137 | }
138 | //MediaPlayer.TrackInfo videoTrack = new List(trackInfoArray)
139 | //.Where(x => x.TrackType == MediaTrackType.Video).FirstOrDefault();
140 | //if (videoTrack != null)
141 | //{
142 | // int descrFlags = videoTrack.DescribeContents();
143 | // MediaFormat mediaFormat = videoTrack.Format;
144 | //}
145 | }
146 | MediaPlayer mp = e.Mp;
147 | videoHeight = mp.VideoHeight;
148 | videoWidth = mp.VideoWidth;
149 | if (Element.AreTransportControlsEnabled)
150 | mediaController.ShowVideoSize(videoWidth, videoHeight);
151 | break;
152 | }
153 | }
154 | catch (Exception ex)
155 | {
156 | System.Diagnostics.Debug.WriteLine(ex.Message);
157 | }
158 | }
159 |
160 | protected override void Dispose(bool disposing)
161 | {
162 | if (Control != null && videoView != null)
163 | {
164 | videoView.Prepared -= OnVideoViewPrepared;
165 | }
166 | if (Element != null)
167 | {
168 | Element.UpdateStatus -= OnUpdateStatus;
169 | }
170 |
171 | base.Dispose(disposing);
172 | }
173 |
174 | void OnVideoViewPrepared(object sender, EventArgs args)
175 | {
176 | isPrepared = true;
177 | ((IVideoPlayerController)Element).Duration = TimeSpan.FromMilliseconds(videoView.Duration);
178 | }
179 |
180 | protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
181 | {
182 | base.OnElementPropertyChanged(sender, args);
183 |
184 | if (args.PropertyName == VideoPlayer.AreTransportControlsEnabledProperty.PropertyName)
185 | {
186 | SetAreTransportControlsEnabled();
187 | }
188 | else if (args.PropertyName == VideoPlayer.SourceProperty.PropertyName)
189 | {
190 | SetSource();
191 | }
192 | else if (args.PropertyName == VideoPlayer.PositionProperty.PropertyName)
193 | {
194 | if (videoView.CurrentPosition < Element.Position.TotalMilliseconds)
195 | {
196 | if (!videoView.CanSeekForward())
197 | return;
198 | }
199 | if (videoView.CurrentPosition > Element.Position.TotalMilliseconds)
200 | {
201 | if (!videoView.CanSeekBackward())
202 | return;
203 | }
204 | if (Math.Abs(videoView.CurrentPosition - Element.Position.TotalMilliseconds) > 1000)
205 | {
206 | if (Element.AreTransportControlsEnabled)
207 | {
208 | //mediaController.Show(1000);
209 | mediaController.Show();
210 | Device.StartTimer(TimeSpan.FromSeconds(2), () =>
211 | {
212 | mediaController.Hide();
213 | return false;
214 | });
215 | }
216 | videoView.SeekTo((int)Element.Position.TotalMilliseconds);
217 | }
218 | }
219 | }
220 |
221 | private void OnShowTransportControls(object sender, EventArgs args)
222 | {
223 | if (Element.AreTransportControlsEnabled)
224 | {
225 | mediaController.Show();
226 | }
227 | }
228 |
229 | private void OnHideTransportControls(object sender, EventArgs args)
230 | {
231 | if (Element.AreTransportControlsEnabled)
232 | {
233 | mediaController.Hide();
234 | }
235 | }
236 |
237 | void SetAreTransportControlsEnabled()
238 | {
239 | if (Element.AreTransportControlsEnabled)
240 | {
241 | mediaController = new FullScreenMediaController(Context);
242 | mediaController.SetMediaPlayer(videoView);
243 | videoView.SetMediaController(mediaController);
244 | }
245 | else
246 | {
247 | videoView.SetMediaController(null);
248 |
249 | if (mediaController != null)
250 | {
251 | mediaController.SetMediaPlayer(null);
252 | mediaController = null;
253 | }
254 | }
255 | }
256 |
257 | void SetSource()
258 | {
259 | isPrepared = false;
260 | bool hasSetSource = false;
261 |
262 | if (Element.Source is UriVideoSource)
263 | {
264 | string uri = (Element.Source as UriVideoSource).Uri;
265 |
266 | if (!String.IsNullOrWhiteSpace(uri))
267 | {
268 | videoView.SetVideoURI(NSUri.Parse(uri));
269 | hasSetSource = true;
270 | }
271 | }
272 | else if (Element.Source is FileVideoSource)
273 | {
274 | string filename = (Element.Source as FileVideoSource).File;
275 |
276 | if (!String.IsNullOrWhiteSpace(filename))
277 | {
278 | videoView.SetVideoPath(filename);
279 | hasSetSource = true;
280 | }
281 | }
282 | else if (Element.Source is ResourceVideoSource)
283 | {
284 | string package = Context.PackageName;
285 | string path = (Element.Source as ResourceVideoSource).Path;
286 |
287 | if (!String.IsNullOrWhiteSpace(path))
288 | {
289 | string filename = System.IO.Path.GetFileNameWithoutExtension(path).ToLowerInvariant();
290 | string uri = "android.resource://" + package + "/raw/" + filename;
291 | videoView.SetVideoURI(NSUri.Parse(uri));
292 | hasSetSource = true;
293 | }
294 | }
295 |
296 | if (hasSetSource && Element.AutoPlay)
297 | {
298 | videoView.Start();
299 | }
300 | }
301 |
302 | // Event handler to update status
303 | void OnUpdateStatus(object sender, EventArgs args)
304 | {
305 | VideoStatus status = VideoStatus.NotReady;
306 |
307 | if (isPrepared)
308 | {
309 | status = videoView.IsPlaying ? VideoStatus.Playing : VideoStatus.Paused;
310 | }
311 |
312 | ((IVideoPlayerController)Element).Status = status;
313 |
314 | // Set Position property
315 | TimeSpan timeSpan = TimeSpan.FromMilliseconds(videoView.CurrentPosition);
316 | ((IElementController)Element).SetValueFromRenderer(VideoPlayer.PositionProperty, timeSpan);
317 |
318 | if (videoView.IsPlaying == false)
319 | Element.OnBufferingEnd();
320 | }
321 |
322 | // Event handlers to implement methods
323 | void OnPlayRequested(object sender, EventArgs args)
324 | {
325 | videoView.Start();
326 | }
327 |
328 | void OnPauseRequested(object sender, EventArgs args)
329 | {
330 | videoView.Pause();
331 | }
332 |
333 | void OnStopRequested(object sender, EventArgs args)
334 | {
335 | videoView.StopPlayback();
336 | }
337 | }
338 | }
--------------------------------------------------------------------------------
/Xam.Forms.VideoPlayer.iOS/VideoPlayerRenderer.iOS.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Diagnostics;
4 | using System.IO;
5 |
6 | using AVFoundation;
7 | using AVKit;
8 | using CoreMedia;
9 | using Foundation;
10 | using UIKit;
11 |
12 | using Xamarin.Forms;
13 | using Xamarin.Forms.Platform.iOS;
14 |
15 | [assembly: ExportRenderer(typeof(Xam.Forms.VideoPlayer.VideoPlayer),
16 | typeof(Xam.Forms.VideoPlayer.iOS.VideoPlayerRenderer))]
17 |
18 | namespace Xam.Forms.VideoPlayer.iOS
19 | {
20 | public class VideoPlayerRenderer : ViewRenderer
21 | {
22 | public new static void Init() { }
23 |
24 | AVPlayer player;
25 | AVPlayerItem playerItem;
26 | AVPlayerViewController _playerViewController; // solely for ViewController property
27 | NSObject playCompleteNotification, playerItemFailedToPlayToEndTimeNotification;
28 | NSObject playbackBufferEmptyObserver, playbackLikelyToKeepUpObserver, playbackBufferFullObserver;
29 |
30 | public override UIViewController ViewController => _playerViewController;
31 |
32 | protected override void OnElementChanged(ElementChangedEventArgs args)
33 | {
34 | base.OnElementChanged(args);
35 |
36 | if (args.NewElement != null)
37 | {
38 | if (Control == null)
39 | {
40 | // Create AVPlayerViewController
41 | _playerViewController = new AVPlayerViewController();
42 |
43 | // Set Player property to AVPlayer
44 | player = new AVPlayer();
45 | _playerViewController.Player = player;
46 |
47 | // End of play notification
48 | playCompleteNotification = NSNotificationCenter.DefaultCenter.AddObserver(
49 | AVPlayerItem.DidPlayToEndTimeNotification,
50 | OnAVPlayerItemDidPlayToEndTime, player.CurrentItem);
51 |
52 | // Play error occured notification
53 | playerItemFailedToPlayToEndTimeNotification =
54 | AVPlayerItem.Notifications.ObserveItemFailedToPlayToEndTime(OnAVPlayerItemFailedToPlayToEndTime);
55 |
56 | // Use the View from the controller as the native control
57 | SetNativeControl(_playerViewController.View);
58 | }
59 |
60 | SetAreTransportControlsEnabled();
61 | SetSource();
62 |
63 | args.NewElement.UpdateStatus += OnUpdateStatus;
64 | args.NewElement.PlayRequested += OnPlayRequested;
65 | args.NewElement.PauseRequested += OnPauseRequested;
66 | args.NewElement.StopRequested += OnStopRequested;
67 | args.NewElement.ShowTransportControlsRequested += OnShowTransportControls;
68 | args.NewElement.HideTransportControlsRequested += OnHideTransportControls;
69 | }
70 |
71 | if (args.OldElement != null)
72 | {
73 | args.OldElement.UpdateStatus -= OnUpdateStatus;
74 | args.OldElement.PlayRequested -= OnPlayRequested;
75 | args.OldElement.PauseRequested -= OnPauseRequested;
76 | args.OldElement.StopRequested -= OnStopRequested;
77 | args.OldElement.ShowTransportControlsRequested -= OnShowTransportControls;
78 | args.OldElement.HideTransportControlsRequested -= OnHideTransportControls;
79 | }
80 | }
81 |
82 | private void OnAVPlayerItemDidPlayToEndTime(NSNotification notification)
83 | {
84 | Element.OnPlayCompletion();
85 | }
86 |
87 | private void OnAVPlayerItemFailedToPlayToEndTime(object sender, AVPlayerItemErrorEventArgs e)
88 | {
89 | Element.OnPlayError(sender, new VideoPlayer.PlayErrorEventArgs(player.Error?.Description));
90 | }
91 |
92 | protected override void Dispose(bool disposing)
93 | {
94 | base.Dispose(disposing);
95 |
96 | if (player != null)
97 | {
98 |
99 | playerItemFailedToPlayToEndTimeNotification.Dispose();
100 | NSNotificationCenter.DefaultCenter.RemoveObserver(playCompleteNotification);
101 | player.ReplaceCurrentItemWithPlayerItem(null);
102 | DisposePlaybackBufferObservers();
103 | }
104 | }
105 |
106 | private void DisposePlaybackBufferObservers()
107 | {
108 | playbackBufferEmptyObserver?.Dispose();
109 | playbackLikelyToKeepUpObserver?.Dispose();
110 | playbackBufferFullObserver?.Dispose();
111 | }
112 |
113 | protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
114 | {
115 | base.OnElementPropertyChanged(sender, args);
116 |
117 | if (args.PropertyName == VideoPlayer.AreTransportControlsEnabledProperty.PropertyName)
118 | {
119 | SetAreTransportControlsEnabled();
120 | }
121 | else if (args.PropertyName == VideoPlayer.SourceProperty.PropertyName)
122 | {
123 | SetSource();
124 | }
125 | else if (args.PropertyName == VideoPlayer.PositionProperty.PropertyName)
126 | {
127 | TimeSpan controlPosition = ConvertTime(player.CurrentTime);
128 |
129 | if (Math.Abs((controlPosition - Element.Position).TotalSeconds) > 1)
130 | {
131 | if (Element.AreTransportControlsEnabled)
132 | {
133 | ((AVPlayerViewController)ViewController).ShowsPlaybackControls = true;
134 | Device.StartTimer(TimeSpan.FromSeconds(2), () =>
135 | {
136 | ((AVPlayerViewController)ViewController).ShowsPlaybackControls = false;
137 | return false;
138 | });
139 | }
140 | player.Seek(CMTime.FromSeconds(Element.Position.TotalSeconds, 1));
141 | }
142 | }
143 | }
144 |
145 | private void OnShowTransportControls(object sender, EventArgs args)
146 | {
147 | if (Element.AreTransportControlsEnabled)
148 | {
149 | ((AVPlayerViewController)ViewController).ShowsPlaybackControls = true;
150 | }
151 | }
152 |
153 | private void OnHideTransportControls(object sender, EventArgs args)
154 | {
155 | if (Element.AreTransportControlsEnabled)
156 | {
157 | ((AVPlayerViewController)ViewController).ShowsPlaybackControls = false;
158 | }
159 | }
160 |
161 | void SetAreTransportControlsEnabled()
162 | {
163 | ((AVPlayerViewController)ViewController).ShowsPlaybackControls = Element.AreTransportControlsEnabled;
164 | }
165 |
166 | void SetSource()
167 | {
168 | AVAsset asset = null;
169 |
170 | if (Element.Source is UriVideoSource)
171 | {
172 | string uri = (Element.Source as UriVideoSource).Uri;
173 |
174 | if (!String.IsNullOrWhiteSpace(uri))
175 | {
176 | //asset = AVAsset.FromUrl(new NSUrl(uri));
177 | NSUrl url = null;
178 | try
179 | {
180 | string absUri = new Uri(uri).AbsoluteUri;
181 | url = new NSUrl(absUri);
182 | }
183 | catch (Exception ex)
184 | {
185 | Debug.WriteLine(ex.Message);
186 | }
187 | if (url != null)
188 | asset = AVAsset.FromUrl(url);
189 | }
190 | }
191 | else if (Element.Source is FileVideoSource)
192 | {
193 | string uri = (Element.Source as FileVideoSource).File;
194 |
195 | if (!String.IsNullOrWhiteSpace(uri))
196 | {
197 | asset = AVAsset.FromUrl(new NSUrl(uri));
198 | }
199 | }
200 | else if (Element.Source is ResourceVideoSource)
201 | {
202 | string path = (Element.Source as ResourceVideoSource).Path;
203 |
204 | if (!String.IsNullOrWhiteSpace(path))
205 | {
206 | string directory = Path.GetDirectoryName(path);
207 | string filename = Path.GetFileNameWithoutExtension(path);
208 | string extension = Path.GetExtension(path).Substring(1);
209 | NSUrl url = NSBundle.MainBundle.GetUrlForResource(filename, extension, directory);
210 | asset = AVAsset.FromUrl(url);
211 | }
212 | }
213 |
214 | if (asset != null)
215 | {
216 | //ExploreProperties(asset);
217 | playerItem = new AVPlayerItem(asset);
218 | }
219 | else
220 | {
221 | playerItem = null;
222 | }
223 |
224 | player.ReplaceCurrentItemWithPlayerItem(playerItem);
225 |
226 | if (playerItem != null)
227 | {
228 |
229 | //playbackBufferEmptyObserver = (NSObject)playerItem.AddObserver("playbackBufferEmpty",
230 | // NSKeyValueObservingOptions.New,
231 | // AVPlayerItem_BufferUpdated);
232 |
233 | playbackLikelyToKeepUpObserver = (NSObject)playerItem.AddObserver("playbackLikelyToKeepUp",
234 | NSKeyValueObservingOptions.New,
235 | AVPlayerItem_BufferUpdated);
236 |
237 | //playbackBufferFullObserver = (NSObject)playerItem.AddObserver("playbackBufferFull",
238 | // NSKeyValueObservingOptions.New,
239 | // AVPlayerItem_BufferUpdated);
240 |
241 | if (Element.AutoPlay)
242 | player.Play();
243 | }
244 | }
245 |
246 | #if DEBUG
247 |
248 | private static void ExploreProperties(AVAsset asset)
249 | {
250 | AVMediaSelection[] aVMediaSelections = asset.AllMediaSelections;
251 | string[] mDataFormats = asset.AvailableMetadataFormats;
252 | string description = asset.Description;
253 | AVAssetTrack[] avAssetVideoTracks = asset.GetTracks(AVMediaTypes.Video);
254 | foreach (AVAssetTrack avAssetVideoTrack in avAssetVideoTracks)
255 | {
256 | string cDescription = avAssetVideoTrack.Description;
257 | string dDescription = avAssetVideoTrack.DebugDescription;
258 | NSObject[] nsObjects = avAssetVideoTrack.FormatDescriptionsAsObjects;
259 | string descr = nsObjects[0].Description;
260 | //NSObject nsoDimension = avAssetVideoTrack.ValueForKey(new NSString("dimension"));
261 | AVMetadataItem[] avCommonMetadataItems = avAssetVideoTrack.CommonMetadata;
262 | AVMetadataItem[] avMetadataItems = avAssetVideoTrack.Metadata;
263 | CMFormatDescription[] cmFormatDescriptions = avAssetVideoTrack.FormatDescriptions;
264 | foreach (CMFormatDescription cmFormatDescription in cmFormatDescriptions)
265 | {
266 | CMVideoCodecType cmVideoCodecType = cmFormatDescription.VideoCodecType;
267 | CMSubtitleFormatType cmSubtitleFormatType = cmFormatDescription.SubtitleFormatType;
268 | CMMetadataFormatType cmMetadataFormatType = cmFormatDescription.MetadataFormatType;
269 | AudioToolbox.AudioFormat[] atAudioFormats = cmFormatDescription.AudioFormats;
270 | }
271 | }
272 | }
273 |
274 | #endif
275 |
276 | // Event handler to update status
277 | void OnUpdateStatus(object sender, EventArgs args)
278 | {
279 | VideoStatus videoStatus = VideoStatus.NotReady;
280 |
281 | switch (player.Status)
282 | {
283 | case AVPlayerStatus.ReadyToPlay:
284 | switch (player.TimeControlStatus)
285 | {
286 | case AVPlayerTimeControlStatus.Playing:
287 | videoStatus = VideoStatus.Playing;
288 | break;
289 |
290 | case AVPlayerTimeControlStatus.Paused:
291 | Element.OnBufferingEnd();
292 | videoStatus = VideoStatus.Paused;
293 | break;
294 | }
295 | break;
296 | }
297 | ((IVideoPlayerController)Element).Status = videoStatus;
298 |
299 | if (playerItem != null)
300 | {
301 | ((IVideoPlayerController)Element).Duration = ConvertTime(playerItem.Duration);
302 | ((IElementController)Element).SetValueFromRenderer(VideoPlayer.PositionProperty, ConvertTime(playerItem.CurrentTime));
303 | }
304 | }
305 |
306 | TimeSpan ConvertTime(CMTime cmTime)
307 | {
308 | return TimeSpan.FromSeconds(Double.IsNaN(cmTime.Seconds) ? 0 : cmTime.Seconds);
309 |
310 | }
311 |
312 | // Event handlers to implement methods
313 | void OnPlayRequested(object sender, EventArgs args)
314 | {
315 | player.Play();
316 | }
317 |
318 | void OnPauseRequested(object sender, EventArgs args)
319 | {
320 | player.Pause();
321 | }
322 |
323 | void OnStopRequested(object sender, EventArgs args)
324 | {
325 | player.Pause();
326 | player.Seek(new CMTime(0, 1));
327 | }
328 |
329 | //private void AVPlayerItem_BufferUpdated(NSObservedChange e)
330 | //{
331 | // if (playerItem.PlaybackBufferEmpty)
332 | // {
333 | // Element.OnBufferingStart();
334 | // }
335 | // else if (playerItem.PlaybackBufferFull)
336 | // {
337 | // Element.OnBufferingEnd();
338 | // }
339 | //}
340 |
341 | private void AVPlayerItem_BufferUpdated(NSObservedChange e)
342 | {
343 | var isBuffering = !playerItem?.PlaybackLikelyToKeepUp;
344 | if (isBuffering == true && Element.IsBuffering == false)
345 | {
346 | Element.OnBufferingStart();
347 | }
348 | else if(Element.IsBuffering)
349 | {
350 | Element.OnBufferingEnd();
351 | }
352 | }
353 | }
354 | }
--------------------------------------------------------------------------------