how to turn on flashlight on windows phone 8.1 - windows-phone-8.1

I created project based on:
https://github.com/Microsoft/real-time-filter-demo/tree/master/RealtimeFilterDemoWP
My question is how to enable flash light (torch) on WP8.1
Should I use MediaCapture() ?
var mediaDev = new MediaCapture();
await mediaDev.InitializeAsync();
var videoDev = mediaDev.VideoDeviceController;
var tc = videoDev.TorchControl;
if (tc.Supported)
{
if (tc.PowerSupported)
tc.PowerPercent = 100;
tc.Enabled = true;
}
when I used it it crash on
var videoDev = mediaDev.VideoDeviceController;
by unhandled exception
How to add flashlight to this sample project ?

You haven't initialized the MediaCaptureSettings, thus when you attempt to initialize the videoController the exception occurs. You need to initialize the settings, let MediaCapture know what device you'd like to use, and setup the VideoDeviceController. In addition, for Windows Phone 8.1 camera drivers, some require you to start the preview, or others require you to start video recording to turn on flash. This is due to the flash being tightly coupled with the camera device.
Here's some general code to give you the idea. *Disclaimer, this is untested. Best sure to call this in an async Task method so you can assure the awaited calls complete before you attempt to toggle the Torch Control property.
private async Task InitializeAndToggleTorch()
{
// Initialize Media Capture and Settings Objects, mediaCapture declared global outside this method
mediaCapture = new MediaCapture();
MediaCaptureInitializationSettings settings = new MediaCaptureInitializationSettings();
// Grab all available VideoCapture Devices and find rear device (usually has flash)
DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
DeviceInformation device = devices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back);
// Set Video Device to device with flash obtained from DeviceInformation
settings.VideoDeviceId = device.Id;
settings.AudioDeviceId = "";
settings.PhotoCaptureSource = PhotoCaptureSource.VideoPreview;
settings.StreamingCaptureMode = StreamingCaptureMode.Video;
mediaCapture.VideoDeviceController.PrimaryUse = Windows.Media.Devices.CaptureUse.Video;
// Initialize mediacapture now that settings are configured
await mediaCapture.InitializeAsync(settings);
if (mediaCapture.VideoDeviceController.TorchControl.Supported)
{
// Get resolutions and set to lowest available for temporary video file.
var resolutions = mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoRecord).Select(x => x as VideoEncodingProperties);
var lowestResolution = resolutions.OrderBy(x => x.Height * x.Width).ThenBy(x => (x.FrameRate.Numerator / (double)x.FrameRate.Denominator)).FirstOrDefault();
await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoRecord, lowestResolution);
// Get resolutions and set to lowest available for preview.
var previewResolutions = mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties (MediaStreamType.VideoPreview).Select(x => x as VideoEncodingProperties);
var lowestPreviewResolution = previewResolutions.OrderByDescending(x => x.Height * x.Width).ThenBy(x => (x.FrameRate.Numerator / (double)x.FrameRate.Denominator)).LastOrDefault();
await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, lowestPreviewResolution);
// Best practice, you should handle Media Capture Error events
mediaCapture.Failed += MediaCapture_Failed;
mediaCapture.RecordLimitationExceeded += MediaCapture_RecordLimitationExceeded;
}
else
{
// Torch not supported, exit method
return;
}
// Start Preview
var captureElement = new CaptureElement();
captureElement.Source = mediaCapture;
await mediaCapture.StartPreviewAsync();
// Prep for video recording
// Get Application temporary folder to store temporary video file folder
StorageFolder tempFolder = ApplicationData.Current.TemporaryFolder;
// Create a temp Flash folder
var folder = await tempFolder.CreateFolderAsync("TempFlashlightFolder", CreationCollisionOption.OpenIfExists);
// Create video encoding profile as MP4
var videoEncodingProperties = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);
// Create new unique file in the Flash folder and record video
var videoStorageFile = await folder.CreateFileAsync("TempFlashlightFile", CreationCollisionOption.GenerateUniqueName);
// Start recording
await mediaCapture.StartRecordToStorageFileAsync(videoEncodingProperties, videoStorageFile);
// Now Toggle TorchControl property
mediaCapture.VideoDeviceController.TorchControl.Enabled = true;
}
Phew! That's a lot of code just to toggle flash huh? Good news is this is fixed in Windows 10 with new Windows.Devices.Lights.Lamp API. You can do same work in just a few lines of code:
Windows 10 Sample for Windows.Devices.Lights.Lamp
For reference, check this thread:
MSDN using Win8.1 VideoDeviceController.TorchControl

Related

Why is my WinRT app closing when trying to debug my background task?

I am trying to experiment with downloading files on a regular basis with background tasks for windows store applications, and am having trouble.
I followed the sample at https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh977055.aspx, and even downloaded/ran it and everything worked perfectly (including being able to step into the timer background task).
So with that I created my own background task in a brand new Windows namespace
Win8BackgroundTest
{
public class TestBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
var deferral = taskInstance.GetDeferral();
var uri = new Uri("http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_480p_h264.mov");
var folder = ApplicationData.Current.LocalFolder;
var downloadFile = await folder.CreateFileAsync(uri.Segments.Last(), CreationCollisionOption.GenerateUniqueName);
var dataFile = await folder.CreateFileAsync("downloadData", CreationCollisionOption.GenerateUniqueName);
var downloader = new BackgroundDownloader();
var operation = downloader.CreateDownload(uri, downloadFile);
await FileIO.WriteTextAsync(dataFile, "Success at " + DateTime.Now);
deferral.Complete();
}
public static async void RegisterTask()
{
const string taskName = "TestBackgroundTask";
try
{
var status = await BackgroundExecutionManager.RequestAccessAsync();
if (status == BackgroundAccessStatus.Denied)
{
return;
}
}
catch
{
// already accepted
}
var tasks = BackgroundTaskRegistration.AllTasks
.Where(x => x.Value.Name == taskName)
.ToArray();
if (tasks.Any())
{
return;
}
var builder = new BackgroundTaskBuilder
{
Name = taskName,
TaskEntryPoint = "Win8BackgroundTest.TestBackgroundTask",
};
builder.SetTrigger(new TimeTrigger(60, false));
var registeredTask = builder.Register();
}
}
}
I set up the application's manifest with a Background Tasks declaration, checking the Timer properties checkbox, and set the EntryPoint to Win8BackgroundTest.TestBackgroundTask.
I then added the following at the end of my App.xaml.cs's OnLaunched() method:
TestBackgroundTask.RegisterTask();
Stepping through seems to have task registration work successfully with no exceptions. I then go back to visual studio, added a breakpoint to the first line in my task's Run() method, I then go to the debug locations toolbar, click the down arrow and select TestBackgroundTask. A few seconds later visual studio exits (as does my app).
Does anyone see what I am doing wrong that is causing background tasks to fail?
So after much frustration and a lot of trial and error the issue was a combination of both of the comments.
So first of all, it appears like you cannot have a background task in the same project as the rest of your windows store application. It must be in it's own windows runtime component project.
Finally, there are times where it just doesn't work and for whatever reason deleting the bin and obj folders fix it.

CaptureElement preview not available sometimes

I have problem with initialization camera on Windows Universal Apps. This code works and never throw any exception, but i have wrapped it into dialog control. Problem is sometimes (1/10 dialog openings) i don't see preview from camera. Have you any idea how to fix that or at least check if preview is displayed?
private async Task InitCameraAsync()
{
var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
var backCam = devices.FirstOrDefault(q => q.EnclosureLocation != null && q.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back);
var mediaCapture = new MediaCapture();
if (backCam != null)
{
await mediaCapture.InitializeAsync(new MediaCaptureInitializationSettings()
{
VideoDeviceId = backCam.Id,
AudioDeviceId = String.Empty,
StreamingCaptureMode = StreamingCaptureMode.Video,
PhotoCaptureSource = PhotoCaptureSource.VideoPreview
});
}
else
{
await mediaCapture.InitializeAsync();
}
CameraControl.Source = mediaCapture;
SetImageEncodingProperties(); // get encoding properties to save images
await SetPreviewResolutionAsync();
await CameraControl.Source.StartPreviewAsync();
}
}
Are you sure that you are calling the function from the UI thread to access the camera for the API to run reliably?
https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.core.coredispatcher.runasync.aspx

"Index was outside the bounds of the array" in ZXing.Net Decode method

I'm new in Windows Phone 8.1 development.
I'm doing a simple app to scan barcode using ZXing.Net and Windows Phone 8.1 SDK.
When I call the Decode method I got an exception with text of "Index was outside the bounds of the array"
Here is a portion of code:
InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
await Camera.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream);
stream.Seek(0);
var properties = Camera.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview);
var videoEncodingProperties = properties as VideoEncodingProperties;
WriteableBitmap writableImg = new WriteableBitmap((int)videoEncodingProperties.Width, (int)videoEncodingProperties.Height);
await writableImg.SetSourceAsync(stream);
result = barcode.Decode(writableImg); // The exception is here
if (result != null)
{
debug.Text = result.Text;
}
else
{
debug.Text = "No results";
}
I think the problem is with the size of the WritableImage, because when I run the app on the emulator (and definitely there is no barcode in it), the decoder decodes and returns no value (and that's ok), but when I run it on my WP8.1 device, I got an exception with a text of:
"Index was outside the bounds of the array"
I tried to resize the writable image with no results! but maybe I'm resizing a bad way or values.
Any help with that? Thanks.
You will need to emulate this action:
var stream = await file.OpenReadAsync();
// initialize with 1,1 to get the current size of the image
var writeableBmp = new WriteableBitmap(1, 1);
writeableBmp.SetSource(stream);
// and create it again because otherwise the WB isn't fully initialized and decoding
// results in a IndexOutOfRange
writeableBmp = new WriteableBitmap(writeableBmp.PixelWidth, writeableBmp.PixelHeight);
stream.Seek(0);
writeableBmp.SetSource(stream);
first pull the image out of the stream then do it again with the PixelWidth found on the actual image.

How to update a custom image Live Tile every minute in Windows Phone 8.1?

There are quite a few Windows Phone 8.1 apps (e.g. Clock hub, Analog Clock Tile, etc.) which allow you to pin an analog clock on the main screen.
I am trying to do the same by following this sample which shows me how to update an XML document every minute.
But if I am going to create an analog clock tile then it needs to be an image.
I have tried to use XamlRenderingBackgroundTask with RenderTargetBitmap to generate the image, this bit works. What I am not sure is how can I update this image every minute.
Any help wold be greatly appreciated!
I took the sample you provided and modified it to generate a custom image live tile every minute.
I've tested it on my phone and it seems to be working OK. You might need to do more testing such as memory usage testing to make sure it doesn't go over the cap (maybe can reduce planTill to 30 minutes to generate less tiles in the loop?).
The UserControl xml file SquareFrontTile1.xml
<Border Height="360" Width="360" Background="#00b2f0" xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:mc='http://schemas.openxmlformats.org/markup-compatibility/2006'>
<TextBlock Text="{0}" HorizontalAlignment="Left" VerticalAlignment="Top" Foreground="White" FontSize="50.667" />
</Border>
The code
public static async void UpdateAsync(BackgroundTaskDeferral deferral)
{
TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
IReadOnlyList<ScheduledTileNotification> plannedUpdated = tileUpdater.GetScheduledTileNotifications();
string language = GlobalizationPreferences.Languages.First();
CultureInfo cultureInfo = new CultureInfo(language);
DateTime now = DateTime.Now;
DateTime planTill = now.AddHours(1);
DateTime updateTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0).AddMinutes(1);
if (plannedUpdated.Count > 0)
updateTime = plannedUpdated.Select(x => x.DeliveryTime.DateTime).Union(new[] { updateTime }).Max();
StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
StorageFile file = await folder.GetFileAsync("SquareFrontTile1.xml");
string xml = await Windows.Storage.FileIO.ReadTextAsync(file);
string startXml = string.Format(xml, now.ToString(cultureInfo.DateTimeFormat.ShortTimePattern));
XmlDocument tileDocumentNow = await GetTileXmlDocument(startXml);
TileNotification notification = new TileNotification(tileDocumentNow) { ExpirationTime = now.AddMinutes(1) };
tileUpdater.Update(notification);
for (var startPlanning = updateTime; startPlanning < planTill; startPlanning = startPlanning.AddMinutes(1))
{
Debug.WriteLine(startPlanning);
Debug.WriteLine(planTill);
try
{
string updateXml = string.Format(xml, startPlanning.ToString(cultureInfo.DateTimeFormat.ShortTimePattern));
XmlDocument updatedTileDocument = await GetTileXmlDocument(updateXml);
ScheduledTileNotification scheduledNotification = new ScheduledTileNotification(updatedTileDocument, new DateTimeOffset(startPlanning)) { ExpirationTime = startPlanning.AddMinutes(1) };
tileUpdater.AddToSchedule(scheduledNotification);
Debug.WriteLine("schedule for: " + startPlanning);
}
catch (Exception e)
{
Debug.WriteLine("exception: " + e.Message);
}
}
deferral.Complete();
}
private static async Task<XmlDocument> GetTileXmlDocument(string xml)
{
Border tileUIElement = XamlReader.Load(xml) as Border;
string liveTileImageName = string.Format("UpdatedLiveTile_{0}.png", DateTime.Now.Ticks.ToString());
if (tileUIElement != null)
{
RenderTargetBitmap rtb = new RenderTargetBitmap();
await rtb.RenderAsync(tileUIElement, 150, 150);
IBuffer pixels = await rtb.GetPixelsAsync();
DataReader dReader = Windows.Storage.Streams.DataReader.FromBuffer(pixels);
byte[] data = new byte[pixels.Length];
dReader.ReadBytes(data);
var outputFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.CreateFileAsync(liveTileImageName, Windows.Storage.CreationCollisionOption.ReplaceExisting);
var outputStream = await outputFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
BitmapEncoder enc = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, outputStream);
enc.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, 150, 150, 96, 96, data);
await enc.FlushAsync();
}
var tileDocument = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Image);
var tileImageAttributes = tileDocument.GetElementsByTagName("image");
XmlElement tmp = tileImageAttributes[0] as XmlElement;
tmp.SetAttribute("src", liveTileImageName);
return tileDocument;
}
I am not going to fully answer the question since I am myself trying to get this working at present. However I will set you in right direction. I have done this in past with windows 8.
What you need to do is create Tile Updater and schedule tiles updates every so often.. in this case one every minute. The tile schema chosen can have be image or text or a combination of both.
you can find the TileSchema catalogue here
http://msdn.microsoft.com/en-us/library/windows/apps/hh761491.aspx
and details of Tile Schema here
http://msdn.microsoft.com/en-us/library/windows/apps/br212859.aspx
Here is a Windows 8 sample
http://code.msdn.microsoft.com/windowsapps/scheduled-notifications-da477093
Here is a snippet from my code which isn't working correctly so far.. tile is blank
TileUpdater updater = TileUpdateManager.CreateTileUpdaterForApplication();
XmlDocument document = new XmlDocument();
document.LoadXml(str2);
ScheduledTileNotification notification2 = new ScheduledTileNotification(document, new DateTimeOffset(time4));
notification2.ExpirationTime = (new DateTimeOffset?((DateTimeOffset)time4.AddMinutes(1.0)));
ScheduledTileNotification notification = notification2;
updater.AddToSchedule(notification);
Once I finish this, I will write up a blog post and add a link here
I have created a repro project that tries to do this from within sample app (not background task).
http://1drv.ms/1nai8nn
The sample work for me, I add to Windows Phone Silverlight 8.1. You must change Notification Services from MPN to WNS in WMAppManifest.xml and add Background task, tick System event, Timer in Package.appxmanifest (Declarations tab).
#Justin XL: your code not work for me, error in line
Border tileUIElement = XamlReader.Load(xml) as Border;
Error: The application called an interface that was marshalled for a different thread.

Using backgrounddownloader and savefilepicker together?

Hello everyone I have a small winrt aplication that downloads video from internet and I was trying to implement backgrounddownloader and filesavepicker together but I run on errors for every type of implementation I searched google and I searched microsoft documentation but nothing.I implemented download via HttpClient class but what I want is to get download progress and HttpClient doesn't offer it.Thx in advance
Here's a quick sample, how to do it:
// set download URI
var uri = new Uri("http://s3.amazonaws.com/thetabletshow/thetabletshow_0072_lhotka.mp3");
// get destination file
var picker = new FileSavePicker();
// set allowed extensions
picker.FileTypeChoices.Add("MP3", new List<string> { ".mp3" });
var file = await picker.PickSaveFileAsync();
// create a background download
var downloader = new BackgroundDownloader();
var download = downloader.CreateDownload(uri, file);
// create progress object
var progress = new Progress<DownloadOperation>();
// attach an event handler to get notified on progress
progress.ProgressChanged += (o, operation) =>
{
// use the progress info in Progress.BytesReceived and Progress.TotalBytesToReceive
ProgressText.Text = operation.Progress.BytesReceived.ToString();
};
// start the actual download
await download.StartAsync().AsTask(progress);
You should be able to modify it for your needs from here on.