UWP custom toast notification sound doesn't play on mobile - notifications

So I have an xml as notification body witch includes audio element with source (src) attribute pointing to preset windows sound and it doesn't play the sound I want and instead plays the default system sound. My notification xml looks like this (I use this as a test message to send trough Azure notification hubs debug option)
<?xml version="1.0" encoding="utf-8"?>
<toast>
<visual>
<binding template="ToastText01">
<text id="1">Test message</text>
</binding>
</visual>
<audio src="ms-winsoundevent:Notification.Looping.Alarm" loop="false"/>
</toast>
I don't have any toast handling on my app (no background task is launched or anything). Funny thing is that my PC plays the sound it should when it recieves the notification, but phone plays default sound every time.
I need to at least play preset windows sound, but playing custom sound from local files would be ace (this doesn't work with custom sounds neither). Also if you know if there's a possibility to start playing music from background task triggered by toast notification let me know, I couldn't find any info on google on this matter.
This is the microsoft link that tells my xml is good (even though it doesn't work): https://msdn.microsoft.com/en-us/library/windows/apps/br230842.aspx

I don't have any toast handling on my app (no background task is launched or anything). Funny thing is that my PC plays the sound it should when it recieves the notification, but phone plays default sound every time.
Looks like all values which prefix is ms-winsoundevent:Notification.Looping will be replaced by system sound while set loop element to false. Based on my understanding, this should be an expected result, these values are for Looping audio, if you need to disable looping, use the first 5 values, for example: ms-winsoundevent:Notification.IM
but playing custom sound from local files would be ace (this doesn't work with custom sounds neither)
This is a known issue which was mentioned in this article
The reason is path parser has an issue to resolve ms-appx:/// path, so the audio src will be regarded as Invalid, then the default sound will be played.
The workaround is copying your wav audio file programmatically to LocalFolder and using the "ms-appdata:///local/" protocol, for example:
private async void Button_Click(object sender, RoutedEventArgs e)
{
Windows.Storage.StorageFile audioFile = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/sound.wav"));
Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
await audioFile.CopyAsync(localFolder);
AddNotification();
}
public void AddNotification()
{
ToastTemplateType toastTemplate = ToastTemplateType.ToastText02;
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);
XmlNodeList toastTextElements = toastXml.GetElementsByTagName("text");
toastTextElements[0].AppendChild(toastXml.CreateTextNode("This is a Toast Message"));
IXmlNode toastNode = toastXml.SelectSingleNode("/toast");
((XmlElement)toastNode).SetAttribute("launch", "MainPage.xaml");
XmlElement audio = toastXml.CreateElement("audio");
audio.SetAttribute("src", "ms-appdata:///local/sound.wav"); //Here
toastNode.AppendChild(audio);
ToastNotification toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier().Show(toast);
}

Related

Open Camera app installed from a UWP app and capture image

Instead of creating a Windows built-in camera UI (CameraCaptureUI) or using a custom MediaCapture control and capture picture I want to open any Camera App downloaded in the device to capture an image and get the result.
I have used
string uriToLaunch = "microsoft.windows.camera:";
var uri = new Uri(uriToLaunch);
var success = await Windows.System.Launcher.LaunchUriAsync(uri);
But this just opens the camera app, I need to get the result file back to the app and save it.
Is there a way to do this?
The method you are using:
var success = await Windows.System.Launcher.LaunchUriAsync(uri);
just opens the default camera, nothing more, the result is a boolean with information if the application has been opened successfully, nothing more.
With CameraCaptureUI you don't need to create camera - this seems to be designed for the task like you have described. With lines:
var captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg;
captureUI.PhotoSettings.CroppedSizeInPixels = new Size(200, 200);
var photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
you just launch the camera app and your app waits for the photo, which you can process further/save.
If you don't want to use it or implement own camera capture, you can think of sharing a picture taken by other app. This is described well at app-to-app communication at MSDN. In this case user will have to click Share button and choose your app as a target. That will invoke OnShareTargetActivated event where you can process the received content.

Captured photos are black when using MediaCapture on Windows Phone 8.1

I am using MediaCapture to capture photos and store them. It works in the emulator. But when running the app on a real phone (Nokia Lumia 530) the captured photos are just black. They have a correct size and the file has a certain byte length, but when displaying the photo it's black. Please note that I do not use Silverlight and am fixed on using MediaCapture. The camera on the phone works when using the default camera app. The App's manifest includes the capabilities "Pictures Library" and "Webcam".
Does someone know what could be wrong?
Here is the test code I use:
using (var mediaCapture = new MediaCapture())
{
await mediaCapture.InitializeAsync();
ImageEncodingProperties imageFormat = ImageEncodingProperties.CreateJpeg();
StorageFile photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync("TestPhoto.jpg", CreationCollisionOption.GenerateUniqueName);
await mediaCapture.CapturePhotoToStorageFileAsync(imageFormat, photoFile);
BitmapImage bitmap = new BitmapImage();
using (var photoStream = await photoFile.OpenReadAsync())
{
bitmap.SetSource(photoStream);
}
}
Edit
I found a solution. The photo is captured correctly if we have a CaptureElement, set it's source to the MediaCapture object, invoke MediaCapture.StartPreviewAsync before taking the photo, take the photo (using CapturePhotoToStorageFileAsync) and finally invoke StopPreviewAsync. It seems that MediaCapture needs an existing (and displayed) preview to be able to capture photos. Strange that this is not documented and using CapturePhotoToStorageFileAsync without a preview does not throw an Exception.
The photo is captured correctly if we have a CaptureElement, set it's source to the MediaCapture object, invoke MediaCapture.StartPreviewAsync before taking the photo, take the photo (using CapturePhotoToStorageFileAsync) and finally invoke StopPreviewAsync. It seems that MediaCapture needs an existing (and displayed) preview to be able to capture photos. Strange that this is not documented and using CapturePhotoToStorageFileAsync without a preview does not throw an Exception.

Using Tiles templates windows8

I'm trying to use tiles templates(a tile which shows an image and switches to show text)
http://msdn.microsoft.com/en-us/library/windows/apps/hh761491.aspx#TileSquarePeekImageAndText04
The question is: where do I put this XML and how can I call it in XAML?
You don't call it in XAML, you provide it to a TileUpdater instance, as you can see from the documentation for TileUpdateManager below. This simplistic scenario handles a local notification (but there are also scheduled, periodic, and push notifications you can leverage).
Take a look at the App tiles and badges and Push and periodic notifications samples for guidance.
function sendTileTextNotification() {
var Notifications = Windows.UI.Notifications;
// Get an XML DOM version of a specific template by using getTemplateContent.
var tileXml = Notifications.TileUpdateManager.getTemplateContent(Notifications.TileTemplateType.tileWideText03);
// You will need to look at the template documentation to know how many text fields a particular template has.
// Get the text attribute for this template and fill it in.
var tileAttributes = tileXml.getElementsByTagName("text");
tileAttributes[0].appendChild(tileXml.createTextNode("Hello World!"));
// Create the notification from the XML.
var tileNotification = new Notifications.TileNotification(tileXml);
// Send the notification to the calling app's tile.
Notifications.TileUpdateManager.createTileUpdaterForApplication().update(tileNotification);
}

headphone plug-in plug-out event when audio route doesn't change - iOS

I'm working on iPad.
I would like to detect when user plug-out headphone. First I used a listener on the property kAudioSessionProperty_AudioRouteChange. So all was working well until I've decided to add a button to switch to speakers when headphone was still plugged. So I’m now facing a problem, maybe someone would have an idea to fix it.
Here is the scenario :
I plug a headphone -> my audio route change callback is called
then I switch sound to speakers (without unplugging my headphone) -> audio route change callback is called
then I unplug my headphone (when sound is still outputting to speakers) -> audio route change callback is NOT called, which seems logical.
But here is my problem ! So my question is : Do you see a way to detect that headphone was unplugged for this last case ?
Thanks for your help
EDIT :
Ok I found a workaround :
To detect whether or not headphones are plugged, I execute a test function all the times I need to know it (instead using a boolean), this might be less good for performances but it's working, here is my code for the ones who may need it :
//set back the default audio route
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None;
AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);
//check if this default audio route is Heaphone or Speaker
CFStringRef newAudioRoute;
UInt32 newAudioRouteSize = sizeof(newAudioRoute);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &newAudioRouteSize, &newAudioRoute);
NSString *newAudioRouteString = (__bridge NSString *)newAudioRoute;
CFRelease(newAudioRoute);
//if this default audio route is not Headphone, it means no headphone is plugged
if ([newAudioRouteString rangeOfString:#"Headphones"].location != NSNotFound){
NSLog(#"Earphone available");
return true;
}
else {
NSLog(#"No Earphone available");
return false;
}
Hope it will help someone !
I imagine a solution it in the following way:
You create in the AppDelegate a boolean for the speakers, let's say:
BOOL isSpeakerOn. And every time the audio route callback is called you have to verify what the current situation with the speakers and what you want to do then.
This is the best tutorial dealing this issue:
http://www.techotopia.com/index.php/Detecting_when_an_iPhone_Headphone_or_Docking_Connector_is_Unplugged_(iOS_4)

YouTube video on Flash Banner CS4 AS3

I am trying to make a flash banner in CS4 with AS3.
In this banner I have to embed youtube videos.
My problem is.. after the video loaded I cant have/see usual controls (fullscreen, pause, stop, etc) on the video.. and the video has the autoplay by default.
I am using this code:
Security.allowDomain("*");
Security.allowDomain("www.youtube.com");
Security.allowDomain("youtube.com");
Security.allowDomain("s.ytimg.com");
Security.allowDomain("i.ytimg.com");
var my_player1:Object;
var my_loader1:Loader = new Loader();
my_loader1.load(new URLRequest("http://www.youtube.com/apiplayer?version=3"));
my_loader1.contentLoaderInfo.addEventListener(Event.INIT, onLoaderInit);
function onLoaderInit(e:Event):void{
addChild(my_loader1);
my_player1 = my_loader1.content;
my_player1.addEventListener("onReady", onPlayerReady);
}
function onPlayerReady(e:Event):void{
my_player1.setSize(200,100);
/////////////////////////////////
//this example is with parameter//
//my_player1.loadVideoByUrl("http://www.youtube.com/v/ID-YOUTUBE?autohide=1&autoplay=0&fs=1&rel=0",0);
//////////////////////////////////
// this one is only the video id//
my_player1.loadVideoByUrl("http://www.youtube.com/v/ID-YOUTUBE",0);
}
I was trying to pass the parameter in the url to try but seems to be is not working.
I was checking too the google API for AS3 (http://code.google.com/apis/youtube/flash_api_reference.html) but honestly I dont find the way to implement that I need.
Whats is the way to see this controls in the video??
Thank you :)
I was trying different thing and I found a partial solution that i want to share with:
Security.allowDomain("www.youtube.com");
Security.allowDomain("youtube.com");
Security.allowDomain("s.ytimg.com");
Security.allowDomain("i.ytimg.com");
Security.allowDomain("s.youtube.com");
var my_player1:Object;
var my_loader1:Loader = new Loader();
//before I used that:
//my_loader1.load(new URLRequest("http://www.youtube.com/apiplayer?version=3"));
//Now is use this:
my_loader1.load(new URLRequest("http://www.youtube.com/v/ID_VIDEO?version=3));
my_loader1.contentLoaderInfo.addEventListener(Event.INIT, onLoaderInit);
function onLoaderInit(e:Event):void{
addChild(my_loader1);
my_player1 = my_loader1.content;
my_player1.addEventListener("onReady", onPlayerReady);
}
function onPlayerReady(e:Event):void{
my_player1.setSize(200,100);
my_player1.loadVideoByUrl("http://www.youtube.com/v/ID_VIDEO",0);
}
Basically Instead of use the "Loading the chromeless player" I use the "Loading the embedded player"
My problem now is How I can modify for example the size of the controls bar.. because is taking 35px height and I want to reduce it
Thank