WP8 - WebBrowser class : How to handle downloading of file? - windows-phone-8

I have created a simple app in WP8 to display web pages using the Microsoft.Phone.Controls.WebBrowser class.
I am able to load the page, navigate links, move back and forward in history.
Apart from this basic functionality I also want to provide means to download files which cannot be displayed within the browser like say .ppt or .mp3.
I have not been able to find anything in the WebBrowser class documentation to initiate a download. There is just a Navigate function which takes a URL to load.
So can a download be done using WebBrowser class?

You'll have to intercept the navigation events and handle it on your own.
The following code sample should point you in the right direction. (You'll want to polish that up, I just put that together to show it can work with a random mp3 site that came up on Google when I searched for test mp3 files)
using Microsoft.Phone.Controls;
using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Net;
using System.Threading.Tasks;
using System.Windows;
namespace PhoneApp2
{
public partial class MainPage
{
public MainPage()
{
InitializeComponent();
MyWebBrowser.Navigate(new Uri("http://robtowns.com/music/"));
}
private async void MyWebBrowser_OnNavigating(object sender, NavigatingEventArgs e)
{
if (!e.Uri.AbsolutePath.EndsWith(".mp3")) return; //Find a more reliable way to detect mp3 files
e.Cancel = true; // Cancel the browser control navigation, and take over from here
MessageBox.Show("Now downloading an mp3 file");
var fileWebStream = await GetStream(e.Uri);
using(var isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
var filePath = "downloadedfile.mp3";
var localFile = isolatedStorage.CreateFile(filePath);
await fileWebStream.CopyToAsync(localFile.AsOutputStream().AsStreamForWrite());
fileWebStream.Close();
MessageBox.Show("File saved as 'downloadedfile.mp3'");
}
}
public static Task<Stream> GetStream(Uri url)
{
var tcs = new TaskCompletionSource<Stream>();
var wc = new WebClient();
wc.OpenReadCompleted += (s, e) =>
{
if (e.Error != null) tcs.TrySetException(e.Error);
else if (e.Cancelled) tcs.TrySetCanceled();
else tcs.TrySetResult(e.Result);
};
wc.OpenReadAsync(url);
return tcs.Task;
}
}
}

Related

How can I specify the download location of pdf?

How can I specify the download location of the converted pdf in the server?
When I run in the server I want to save the pdf in server files but I don't know how can I manipulate the memory stream or how to do it.
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Syncfusion.HtmlConverter;
using Syncfusion.Pdf;
using System.IO;
using Microsoft.AspNetCore.Hosting;
namespace HospitalQR.Web.Controllers
{
public class FormController : Controller
{
private readonly IHostingEnvironment _hostingEnvironment;
public FormController(IHostingEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
}
public IActionResult Index()
{
return View("PreForm");
}
public IActionResult PdfConverter()
{
HtmlToPdfConverter converter = new HtmlToPdfConverter();
WebKitConverterSettings settings = new WebKitConverterSettings();
settings.WebKitPath = Path.Combine(_hostingEnvironment.ContentRootPath, "QtBinariesWindows");
converter.ConverterSettings = settings;
PdfDocument document = converter.Convert("https://localhost:44334/form");
MemoryStream ms = new MemoryStream();
document.Save(ms);
document.Close(true);
ms.Position = 0;
FileStreamResult fileStreamResult = new FileStreamResult(ms, "application/pdf");
fileStreamResult.FileDownloadName = "PreForm.pdf";
return fileStreamResult;
}
}
}
By default, it will automatically save the downloaded file in your browser location. We could not able set the defined path in an ASP NET Core Web application and download it from the browser. If you want the save the pdf in a defined path, please change the browser path setting to that predefined path.
However, if you want to save the PDF document in your “wwwroot” location, please refer the below code snippet,
//Initialize HTML to PDF converter with WebKit rendering engine
HtmlToPdfConverter htmlConverter = new HtmlToPdfConverter(HtmlRenderingEngine.WebKit);
WebKitConverterSettings settings = new WebKitConverterSettings();
//Set the QtBinaries folder path
settings.WebKitPath= Path.Combine(_hostingEnvironment.ContentRootPath, "QtBinariesWindows");
//Assign WebKit settings to HTML converter
htmlConverter.ConverterSettings = settings;
//Convert URL to PDF
PdfDocument document = htmlConverter.Convert("https://www.google.com");
string path = _hostingEnvironment.ContentRootPath+ "\\wwwroot\\output.pdf";
FileStream file = new FileStream(path,FileMode.Create, FileAccess.Write);
document.Save(file);
document.Close(true);
Please try the above solution on your end and let us know if it suits your requirement.
Note: I work for Syncfusion.

Reading data from Arduino Bluetooth on Windows Phone 8.1

I am developing a code that will allow me to send small amounts of data between my arduino mega and my windows 8.1 phone using a HC-05 bluetooth module.
Sending data from the phone to the arduino was pretty simple, but I am having a dire time attempting to read data that comes back from the arduino that I send on the serial port.
For testing purposes my code is simple, sending ascii charaters 'a' & 'b' to turn an LED on & off, this could not work any better, but I am having trouble trying to figure out how to correctly read the data that I send back to my phone.
I send a single arbitrary ascii character back to the phone but I cannot for the life of me figure out the correct way of reading this data from the bluetooth stream I have setup.
I have been trying for nearly two days, but everything I try ends up freezing my phone with no exceptions thrown? A lot of posts online send me to the Nokia dev site which is now inactive.
I have tried using the 'datareader' and the 'streamreader' classes to do this but it always freezes, does anyone know how to make this work? And why my streamreader keeps freezing my phone?
I have tried to annotate my code appropriatley (seen below). The problem occurs in the 'Tick' event handler at the bottom of the code.
(FYI: All capabilities have been added to the manifest files so this shouldn't be the problem).
Thank you.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Bluetooth_SL.Resources;
using Windows.Networking;
using Windows.Networking.Proximity;
using Windows.Networking.Sockets;
using Windows.Devices.Bluetooth;
using System.IO;
using Microsoft.Xna.Framework;
using System.Windows.Threading;
using Windows.Storage.Streams; // <-- for the datareader class
namespace Bluetooth_SL // silverlight, does this matter?
{
public partial class MainPage : PhoneApplicationPage
{
DispatcherTimer Timer = new DispatcherTimer();
StreamSocket socket = new StreamSocket();
StreamWriter writer;
StreamReader reader;
public MainPage()
{
InitializeComponent();
Timer.Interval = TimeSpan.FromMilliseconds(1000); // dispatcher timer used to check for incoming data from arduino
Timer.Tick += Timer_Tick; // event handler for dispatcher timer
}
protected override void OnNavigatedFrom(NavigationEventArgs e) // frees up memory
{
socket.Dispose();
}
private void Connect_But_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
ConnectToBluetooth();
}
private async void ConnectToBluetooth() // sets up the connection // this works fine
{
// Configure PeerFinder to search for all paired devices.
PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
var pairedDevices = await PeerFinder.FindAllPeersAsync();
if (pairedDevices.Count == 0)
{
Debug_Block.Text = "No paired devices were found.";
}
else
{
Debug_Block.Text = "Found";
PeerInformation selectedDevice = pairedDevices[0]; // pick the first paired device
try // 'try' used in the case the socket has already been connected
{
await socket.ConnectAsync(selectedDevice.HostName, "1");
writer = new StreamWriter(socket.OutputStream.AsStreamForWrite());
writer.AutoFlush = true;
reader = new StreamReader(socket.InputStream.AsStreamForRead());
Debug_Block.Text = "Connected";
}
catch (Exception x)
{
Debug_Block.Text = x.ToString();
}
}
}
private void SendButton_Tap(object sender, System.Windows.Input.GestureEventArgs e) // this works perfectly
{
try { writer.WriteLine("a"); } // attempts to write the ascii 'a' to the arduino which turns on the on-board LED
catch { Debug_Block.Text = "Failed to write"; }
}
private void SendButton_Off_Tap(object sender, System.Windows.Input.GestureEventArgs e) // this works perfectly
{
try { writer.WriteLine("b"); } // attempts to write the ascii 'b' to the arduino which turns off the on-board LED
catch { Debug_Block.Text = "Failed to write"; }
}
private void ReadButtonToggle_Tap(object sender, System.Windows.Input.GestureEventArgs e) // toggles the timer on and off
{
if(Timer.IsEnabled == true)
{
Timer.Stop();
Debug_Block.Text = "Timer Stopped";
}
else
{
Timer.Start();
Debug_Block.Text = "Timer Started";
}
}
void Timer_Tick(object sender, EventArgs e) // THIS IS THE PROBLEM
{
Debug_Block.Text = "Tick";
Debug_Block.Text = reader.ReadLine(); // <-- ALWAYS FREEZES HERE
Timer.Stop(); // This line is temporary for debugging
}
}
}

play music on windows phone 8.1

I tried to get all the music files into listbox and play the selected file.
The below code is what i did to play music but unfortunately it doesn't play. Can anyone tell me what the mistake is?
private async void button1_Click(object sender, RoutedEventArgs e)
{
StorageFolder folder = Windows.Storage.KnownFolders.MusicLibrary;
IReadOnlyList<StorageFile> files = await folder.GetFilesAsync();
foreach (var file in files)
{
MusicProperties music = await file.Properties.GetMusicPropertiesAsync();
listBox2.Items.Add(music.Title);
}
}
private async void listBox2_Tapped(object sender, TappedRoutedEventArgs e)
{
try
{
StorageFolder folder = Windows.Storage.KnownFolders.MusicLibrary;
IReadOnlyList<StorageFile> files = await folder.GetFilesAsync();
if (files.Count > 0)
{
var file = files[listBox2.SelectedIndex];
mediaElement1.Source = new Uri(files[listBox2.SelectedIndex].Path);
textBlock1.Text = files[listBox2.SelectedIndex].Path;
mediaElement1.Play();
}
}
catch(Exception ex)
{
textBlock1.Text = ex.Message;
}
}
Instead mediaElement1.Source = new Uri(files[listBox2.SelectedIndex].Path); you need use the code bellow:
var fileStream = await file.OpenReadAsync();
mediaElement.SetSource(fileStream, file.ContentType);
You need to use BackgroundMediaPlayer with background task.
MSDN
You can write apps for Windows Phone 8.1 that play audio in the background. This means that even after the user has left your app by pressing the Back button or the Start button on their device, your app can continue to play audio.
Scenarios for background audio playback include:
Long-running playlists The user briefly brings up a foreground app to select and start a playlist, after which the user expects the playlist to continue playing in the background.
Using task switcher The user briefly brings up a foreground app to start playing audio, then switches to another open app using the task
switch. The user expects the audio to continue playing in the
background.

Change VS reload files behaviour

I am having one VSIX project, which will made some changes in Project.json file of ASPNET5 project. am using the following to edit .json file.
ProjectJson jsonObj = JsonConvert.DeserializeObject<ProjectJson>(jsonContents);
jsonObj = JsonConvert.DeserializeObject<ProjectJson>(jsonContents);
var resultJson = JsonConvert.SerializeObject(jsonObj, Formatting.Indented);
JsonSerializer serializer = new JsonSerializer();
using (StreamWriter sw = new StreamWriter(projectObjects.ProjectJsonPath))
{
var writer = new JsonTextWriter(sw);
serializer.Serialize(writer, resultJson);
}
// File.WriteAllText(projectObjects.ProjectJsonPath, resultJson);
by using both stream writer and writealltext am getting the following message in ASPNET 5 project
The file has unsaved changes inside this editor and has been changed
externally. do you want to reload it?
how to edit .json file without getting the above message?
Its actually the opposite. Since the environment thinks that the file wants to reload with unsaved changes.
You should uncheck the detect file changes. And when you do, it won't detect the external changes and will not warn you, beware though, that if you try to save the file after it has been modified you will lose the external change.(not a problem in your case I guess) and in order to see the changes you will have to close, not save the file and reopen it.
Source : VS2008: Disable asking whether to reload files changed outside the IDE
This is the option you want to check programmatically. I don't know how exactly you can do that but you can find topics about settings at MSDN (Creating an option page and Creating a setting category). Using those topics you can have a sense of how options are created.
Basically what you need to do is to load VS settings file (VS.vssettings) and inject another Xml line. (Have a look at Examining the Settings File section on MSDN)
Update
To be extremely clear the VS settings file is located under
Documents\Your_VS_Version\Settings\CurrentSettings.vssettings
and you need to load the xml and change 'AutoloadExternalChanges' to value 'true'.
You need to tell the environment to ignore file changes. This can be achieved using the IVsFileChangeEx and IVsDocDataFileChangeControl interfaces.
Here is a utility class (derived from the original Visual Studio 2010 SDK Managed Package Framework sample that you can still find here: http://www.getcodesamples.com/src/8641B4F/98B3955E) that should help:
using (SuspendFileChanges suspend = new SuspendFileChanges(site, filePath))
{
// do something with files
suspend.Sync(); // if you optionally want to tell the IDE it has changed
}
The utility class:
public class SuspendFileChanges: IDisposable
{
private readonly IServiceProvider _serviceProvider;
private readonly List<string> _urls;
private readonly IVsDocDataFileChangeControl[] _controls;
public SuspendFileChanges(IServiceProvider serviceProvider, string url)
: this(serviceProvider, new string[] { url })
{
}
public SuspendFileChanges(IServiceProvider serviceProvider, params string[] urls)
{
if (serviceProvider == null)
throw new ArgumentNullException("serviceProvider");
if (urls == null)
throw new ArgumentNullException("urls");
_serviceProvider = serviceProvider;
_urls = new List<string>(urls);
_controls = new IVsDocDataFileChangeControl[_urls.Count];
// or use Package.GetGlobalService ...
IVsRunningDocumentTable rdt = (IVsRunningDocumentTable)serviceProvider.GetService(typeof(SVsRunningDocumentTable));
IVsFileChangeEx fileChange = (IVsFileChangeEx)serviceProvider.GetService(typeof(SVsFileChangeEx));
for(int i = 0; i < _urls.Count; i++)
{
string url = _urls[i];
if (url == null)
continue;
fileChange.IgnoreFile(0, url, 1);
IVsHierarchy hierarchy;
uint itemId;
uint docCookie;
IntPtr docData;
rdt.FindAndLockDocument((uint)_VSRDTFLAGS.RDT_NoLock, url, out hierarchy, out itemId, out docData, out docCookie);
if (docData != IntPtr.Zero)
{
_controls[i] = Marshal.GetObjectForIUnknown(docData) as IVsDocDataFileChangeControl;
if (_controls[i] != null)
{
_controls[i].IgnoreFileChanges(1);
}
Marshal.Release(docData);
}
}
}
public void Sync()
{
IVsFileChangeEx fileChange = (IVsFileChangeEx)_serviceProvider.GetService(typeof(SVsFileChangeEx));
if (fileChange == null)
throw new InvalidOperationException();
foreach (string url in _urls)
{
if (url == null)
continue;
fileChange.SyncFile(url);
}
}
public void Dispose()
{
IVsFileChangeEx fileChange = (IVsFileChangeEx)_serviceProvider.GetService(typeof(SVsFileChangeEx));
if (fileChange != null)
{
foreach (string url in _urls)
{
if (url == null)
continue;
fileChange.IgnoreFile(0, url, 0);
}
}
foreach (IVsDocDataFileChangeControl control in _controls)
{
if (control != null)
{
control.IgnoreFileChanges(0);
}
}
}
}

Update text block from downloaded text file = RPC_E_WRONG_THREAD WP8.1

I am learning Windows Phone 8.1 development, I have probably done something utterly incorrectly programming wise
The need: I want to download a text file from the web using HttpClient() and display it in the TextBlock1
From variety of tutorials I have found the following:
public async void DownloadDataAsync()
{
string data = "some link to Textfile.txt";
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(data);
HttpContent content = response.Content;
string result = await content.ReadAsStringAsync();
UpdateTextBlock1(result);
}
Then the other functions.
public void UpdateTextBlock1(string result)
{
TextBlock1.Text = result;
}
private void BtnDownloadData_Click(object sender, RoutedEventArgs e)
{
Task t = new Task(DownloadDataAsync);
t.Start();
}
The code starts well enough - on button pressed, I receive RPC_E_WRONG_THREAD.
Is it that I'm trying to call the method when all threads haven't finished? How can I code that efficently so the TextBlock1 is updated with txt data?
Thanks for understanding, baby steps here in programming, and I couldn't find a relevant answer over google. (Maybe I don't yet know how to ask?)
You need to update the textblock on the UI thread like so:
Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
TextBlock1.Text = result;
});
There are many posts on this subject.