I need to implement the possibility to pick multiple images and load them in my app, after some researches I camer across this Package called MediaPlugin and I noticed that it has a method called PickPhotosAsync() that allows users to pick multiple images from the gallery.
So I set everything up in the iOs and Android as it's said in the page on GitHub and copy & pasted the code of the MainPage.
By the time I'm writing this I tried other solutions but all of them allow me just to pick a single image and I can't figure out why it doesn't work as it's expected to.
Here's some C# code (even though it's the same of the sample given by James Montamagno)
files.Clear();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert("Photos Not Supported", ":( Permission not granted to photos.", "OK");
return;
}
var picked = await CrossMedia.Current.PickPhotosAsync();
if (picked == null)
return;
foreach (var file in picked)
files.Add(file);
And here's the Xaml page
<StackLayout>
<Button x:Name="pickPhoto" Text="Carica Foto" />
<Button x:Name="takePhoto" Text="Scatta Foto" />
<Label x:Name="label" />
</StackLayout>
I will not post the entire code (since it is too much) but here is a complete tutorial on how to achieve that.
It uses a Native iOS library, and the complete implementation on Android.
Related
I have a basic webpage that I am attempting to load into a WebView on a XAML page. The relevant code is such:
<WebView x:Name="WebViewQuestionText" Source="editor.html" HeightRequest="500" WidthRequest="500" />
As per the official Microsoft .NET MAUI documentation, I have editor.html located in /Resources/Raw/editor.html and set to a Build Action of MauiAsset.
During runtime I don't generate any errors but the WebView is blank. An inspection of the WebView reveals a webpage that is barebones with nothing in it, I assume is the default for a WebView control. If I throw an actual URL in, the page loads up and works as expected, displaying the contents of the given website.
I believe it's simply not finding my page to display it. I'm building for Windows currently but this application will be eventually deployed to both Windows and Mac. How can I ensure it finds it correctly?
As pointed out below - I have also tried it this way, with the same result - when I click the link, I get a blank page.
<WebView x:Name="WebViewQuestionText" HeightRequest="500" WidthRequest="500">
<WebView.Source>
<HtmlWebViewSource>
<HtmlWebViewSource.Html>
<![CDATA[
<html>
<head>
</head>
<body>
<h1>.NET MAUI</h1>
<p>The CSS and image are loaded from local files!</p>
<p>next page</p>
</body>
</html>
]]>
</HtmlWebViewSource.Html>
</HtmlWebViewSource>
</WebView.Source>
</WebView>
My editor.html page is as follows:
<!DOCTYPE html>
<HTML>
<BODY>
<H1>This is a test</H1>
<P>This is only a test</P>
</BODY>
</HTML>
I've fixed this with this PR into .Net Maui. Will be in the SR2 release due in the next few weeks.
The docs suggested it worked consistently on all platforms, but it simply had never been implemented on Windows... slightly concerning.
The workaround I've posted on the PR (mentioned also by Reinaldo below) will get around this for the mean time, however you should probably remove it once SR2 is released and you update to it.
This ends up being a currently open bug against .NET MAUI on the Windows platform.
https://github.com/dotnet/maui/issues/5523
There appears to be a workaround here but it is not ideal. The issue appears to be one of resolving the correct path on Windows for the local file, so the workaround solution is to load the file directly via StreamReader
As mentioned before it is an open bug at the moment. However there is a workaround besides using a StreamReader.
#if WINDOWS
private static readonly System.Lazy<bool> _isPackagedAppLazy = new System.Lazy<bool>(() =>
{
try
{
if (Windows.ApplicationModel.Package.Current != null)
return true;
}
catch
{
// no-op
}
return false;
});
private static bool IsPackagedApp => _isPackagedAppLazy.Value;
// Allow for packaged/unpackaged app support
string ApplicationPath => IsPackagedApp
? Windows.ApplicationModel.Package.Current.InstalledLocation.Path
: System.AppContext.BaseDirectory;
#endif
private async void WebView_HandlerChanged(object sender, EventArgs e)
{
#if WINDOWS
await ((sender as WebView).Handler.PlatformView as Microsoft.Maui.Platform.MauiWebView).EnsureCoreWebView2Async();
((sender as WebView).Handler.PlatformView as Microsoft.Maui.Platform.MauiWebView).CoreWebView2.SetVirtualHostNameToFolderMapping(
"localhost",
ApplicationPath,
Microsoft.Web.WebView2.Core.CoreWebView2HostResourceAccessKind.Allow);
var wv = (sender as WebView).Handler.PlatformView as Microsoft.Maui.Platform.MauiWebView;
wv.LoadUrl($"https://localhost/{wv.Source.AbsolutePath}");
#endif
}
The WebView would look something like this:
<WebView x:Name="dashBoardWebView" BackgroundColor="Transparent"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
IsVisible="True"
HandlerChanged="WebView_HandlerChanged"
Source="test.html"></WebView>
Hope it helps.
Note: Taken from https://github.com/dotnet/maui/pull/7672
I am trying to find a resource that would explain how to retrieve a YouTube video URL to play in an external player. Of course, I have taken a look at the YouTube Data API, but there doesn't seem to be a way to do this.
However, I know it is possible, given that there exist YouTube client applications that are able to stream video (MetroTube is one example).
I saw the related post (How to play a YouTube video in WPF using C#), but it was posted a long time ago. I would like to avoid having to use a WebBrowser control (or WebView in UWP).
Can someone suggest an approach or point to a resource that allows this?
I have used MyToolKit.Extended in the past to integrate Youtube Videos in one of my App.
Install Nuget Package from Here
Once done, you need to call this method
internal async Task<Uri> GetYoutubeUri(string VideoID)
{
YouTubeUri uri = await YouTube.GetVideoUriAsync(VideoID, YouTubeQuality.Quality1080P);
return uri.Uri;
}
Make sure you are passing only VideoID. i.e, If your URL is
https://www.youtube.com/watch?v=UO-8CMdeSHA
you need to pass only UO-8CMdeSHA.
Once done, you will receive the actual Media Uri. You can now set this as a source to MediaPlayer. Something like below.
Uri _videoUri = await GetYoutubeUri("UO-8CMdeSHA");
if (_videoUri != null)
{
player.Source = _videoUri;
player.Play();
}
To ensure you see basic Play/Pause button and few others, Use Below in your XAML.
MediaElement x:Name="player" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" AreTransportControlsEnabled="True" />
And you should be able to play YouTube Videos.
Good Luck.
Solution at the end.
I have a hard time finding informations about a youtubeplayer in uwp following the MVVM pattern.
What are the differences between <MediaElement> and <WebView> in this context and what would be better/easier to use?
How do I handle the events of the Player in my VM?
VS2017 tells me that i can't use the MediaPlayerElement
Error Message
I tried other versions/builds of VS2017 but get the same error.
Are there other ways to do this?
TY
Edit:
<WebView> seems to be pretty easy. Are there any downsides using it?
<WebView x:Name="webView" Width="300"
Height="225" Source="https://www.youtube.com/watch?v=2Rg1XmzzrTM"
RelativePanel.AlignHorizontalCenterWithPanel="True"
RelativePanel.Below="linkYT"/>
Edit2:
Thanks to Aditya Sharma I got on the right Track and found this Question
So I ended up with the following:
View:
<MediaElement x:Name="ytPlayer"
AreTransportControlsEnabled="True"
Source="{Binding Test1, Mode=OneWay}"
Width="600"
AutoPlay="True"
Height="400"/>
VM:
public void doSomething()
{
...
test1 = new Uri(convertLink(currentMovie.TrailerSource));
...
}
private string convertLink(string link)
{
IEnumerable<VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(link, false);
VideoInfo video = videoInfos
.First(info => info.VideoType == VideoType.Mp4 && info.Resolution == 720
);
return video.DownloadUrl;
}
Where Test1 is of Type Uri and currentMovie.TrailerSource is a string
For this to work I had to get the NuGet YouTubeExtractor.
Hope this Helps somebody get it done MVVM.
So here is the thing, We have 1. WebView and 2. MediaElement
Let's take up a deep dive into these:
WebView: is basically a phone in app browser. you can give it a link and it'll navigate to the webPage. You can use it for your youtube screening but there will be downsides:
You won't be able to use native controls like pause/play/seek locally. All the controls will be handled by the website rendered in a WebView.
You have no control on the UI as well. You'll see the basic embedded youtube UI in your app WebView that might just break your UI and might also just provide a pixelated view when scaled.
MediaElement on the other hand is quite convenient, it has a source property that takes a Uri datatype as well so the great thing is that you can pass in your Uri as the embedded link for the youtube vid, the MediaElement will handle everything for you plus, it'll give you some additional advantages like control over your UI, Play/Pause or even custom styling and autoplay/playRate options.
So In my opinion, I would say use a MediaElement over the webView as it'll provide you with more control over whats happening and also provide a native experience to the user.
You can find some more information on it here
in this question and in it's comments section.
Also, since you'll be using mvvm on windows 10, I would recommend you x:bind the Source property of the MediaElement to a Uri DataType property in a oneWay Mode in your ViewModel
I tried to localize my Windows Universal App with the Multilingual app toolkit.
Because you can't bind strings directly from a .resw file in XAML, I used the ReswFileCodeGenerator tool. It works great in code behind, but in XAML I can't get this right.
In Windows Phone 8.0 I could use:
Text="{Binding Path=LocalizedResources.StringName, Source={StaticResource Strings}}"
Is there a similar way in Windows (Phone) 8.1 with the ReswFileGenerator tool?
I would still suggest you do it as Depechie already suggested: use x:Uid attribute.
If you need to get the localized string from code, just replace . in resource name with /. So, in XAML you'll write:
<TextBlock x:Uid="appString" />
In code you'll use:
var resourceLoader = new ResourceLoader();
var localizedText = resourceLoader.GetString("appString/Text");
When doing resource translations in wp8.1 with .resw files, you need to use the x:Uid attribute on your xaml control!
Like <TextBlock x:Uid="FieldKey" />
Details are mentioned here...
I've coded something to help me with this. It may not be perfect, but works great for me. Here's a link to the helper. You build it and put the .exe file in some easy-to-reach folder.
In the project with the resources, you set the pre-build action to something like this (you only need to change the "path\to\ResourcesHelper.exe" part):
call "path\to\ResourcesHelper.exe" "$(TargetName)" "$(ProjectDir)\" "$(RootNameSpace)" "universal"
Also, the main resources must be in Resources/en-US folder of your project (you can change it in the code, though).
This way, when you build the project, it will generate a file called LocalizedStrings.cs which is something like the file generated for .resx files. It contains some additional properties called LC (for lower case), UC (for upper case) and UCF (for upper case first) which return the strings in that casing. I hope you'll find it useful. :)
Note: The tool wasn't meant for other people, so I really just coded what I needed, so it may not work flawlessly.
I am creating a windows phone quiz app. it also displays short videos as questions which the users answers on. i have been able to use this code to display videos from a local directory. but my app package file gets so large if i will have to include too many videos locally. so i decided to try loading from internet once the users needs it.
this is my XAML code:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid HorizontalAlignment="Left" Height="186" Margin="10,132,0,0" VerticalAlignment="Top" Width="436">
<Core:SMFPlayer PositionLiveBuffer="0:0:9" EstimatedLiveDuration="0:0:30" VolumeLevel="0.9">
<Core:SMFPlayer.SelectedAudioStream>
<Media:StreamMetadata/>
</Core:SMFPlayer.SelectedAudioStream>
<Core:SMFPlayer.Playlist>
<Media:PlaylistItem x:Name="media" DeliveryMethod="ProgressiveDownload" MediaSource="Assets/Kedike.wmv" MediaType="Entertainment" Title="song" FileSize="2413589" FrameRate="1045" VideoHeight="268" VideoWidth="512" Description=" vodeo" JumpToLive="True"/>
</Core:SMFPlayer.Playlist>
</Core:SMFPlayer>
</Grid>
</Grid>
This code works when the videos are loaded from a local source i.e /videos/kedike.wmv. i saw this code online and it actually was able to get a video with this:
mediasource = "http://ecn.channel9.msdn.com/o9/content/smf/smoothcontent/bbbwp7/big buck bunny.ism/manifest"
But to do this from the net, the DeliveryMehod property is set to ="AdaptiveStreaming"
i wondered what file type is that and i tried replacing the source with a youtube video link and a facebook video link. none of these works.
I need help in doing this.
Then i want to change the mediasource programatically. i.e through the xaml.cs file. i think declaring
media.MediaSource = new Uri("http://....", UriKind=Relative);
Dont know if this will work.
I tried doing this since i have been able to load videos locally but i get error that i have not initialised or created a new instance of the media element (not the windows phone xna media)
i got some other errors while trying to change some other things.
my C# CODE IS:
private void secondvideo()
{
media.MediaSource = new Uri("Videos/kedike2.wmv", UriKind.Relative);
}
i want to play a second video with this code and i get error. this is the link to where i got the code.code link
You can't just use any kind of link in MMPPF due to its limitation. You need to have the exact URL of the video.
Youtube videos' URL(the exact ones) are generally too large. If you really want to load youtube videos in MMPPF(though I think it's not legal to use Youtube videos in your own Media Player) use this which is available via NuGet.
You can use this toolkit to fetch the exact youtube video URL and use it in your own player.