Fatal error when camera is initializing and back button is pressed or page navigating - windows-phone-7

I'm working on WP7/8 application with barcode scanning. And have a problem with disposing camera. Camera initialize too long, and when camera is still initializing and I press back button, I've got a fatal error:
A first chance exception of type 'System.ObjectDisposedException'
occurred in Microsoft.Devices.Camera.ni.dll WinRT information: Fatal
error. Disposing capture device.
Could anybody helps me how to avoid this error?
my code:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
InitializeAndGo();
base.OnNavigatedTo(e);
}
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
disposeCamera();
}
private void PhotoCameraOnInitialized(object sender, CameraOperationCompletedEventArgs cameraOperationCompletedEventArgs)
{
_width = Convert.ToInt32(_photoCamera.PreviewResolution.Width);
_height = Convert.ToInt32(_photoCamera.PreviewResolution.Height);
_luminance = new PhotoCameraLuminanceSource(_width, _height);
if (_photoCamera.IsFlashModeSupported(FlashMode.Auto))
{
_photoCamera.FlashMode = FlashMode.Off;
}
cameraInitialized = true;
Dispatcher.BeginInvoke(() =>
{
FlashCheckbox.IsEnabled = true;
if (_photoCamera.IsFlashModeSupported(FlashMode.Auto))
{
_photoCamera.FlashMode = FlashMode.Off;
}
});
_photoCamera.Focus();
}
private void InitializeAndGo()
{
stopScan = false;
_photoCamera = new PhotoCamera();
_photoCamera.Initialized += PhotoCameraOnInitialized;
_photoCamera.AutoFocusCompleted += PhotoCameraOnAutoFocusCompleted;
viewfinderBrush.SetSource(_photoCamera);
_previewTransform.Rotation = _photoCamera.Orientation;
_results = new ObservableCollection<Result>();
_barcodeReader = new BarcodeReader();
_barcodeReader.TryHarder = true;
_barcodeReader.AutoRotate = true;
_service = new MyMoviesDataService(ErrorDataService);
}
private void disposeCamera()
{
try
{
cameraInitialized = false;
StopScan();
_photoCamera.Initialized -= PhotoCameraOnInitialized;
_photoCamera.AutoFocusCompleted -= PhotoCameraOnAutoFocusCompleted;
_photoCamera.Dispose();
_photoCamera = null;
}
catch (Exception ex)
{
App.ShowErrorToast(ex.Message);
}
}

Don't use the camera until it's been successfully initialized (You can check this in the camera's Initialized event).
Also, wrap any usages of the camera in a
try
{
// camera code here
}
catch (ObjectDisposedException)
{
// re-initialize the camera?
}
to handle situations like suspension, which will dispose of the camera automatically.
As for the
An exception of type 'System.ObjectDisposedException' occurred in
Microsoft.Devices.Camera.ni.dll and wasn't handled before a
managed/native boundary WinRT information: Fatal error. Disposing
capture device.
This is something Microsoft needs to fix; I mean, how are you supposed to handle a native code exception if it isn't allowed to propagate to managed code?

Where is the exception coming from (which code line / block)?
I would for starter put a try...catch around InitializeAndGo() in the OnNavigatedTo event handler. And on the whole PhotoCameraOnInitialized event handler also.
Cheers,

Related

Xamarin Forms Cross and Camera control

For my studying project, I need to realize an application that has a CameraView or a CameraPage, with a special design. However, I’m not able to figure out how to realize it.
I found a lot of information, to be honest, but they are either obsolete or incomplete, so, I would like to make a point about it, through this thread!
How to implement a Camera?
Well, two solutions can be considered based on what I read.
Camera Page
Let’s say that it’s the first “official” solution. It’s proposed by Xamarin itself, with the Customizing a ContentPage tutorial/documentation. It explains you, through a web page how to implement the camera service with a cross-platform solution.
I then tried the UWP solution:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CameraPreviewProject.Sources.Pages.CameraPage">
<ContentPage.Content>
<AbsoluteLayout>
<Button Text="Click me !" AbsoluteLayout.LayoutBounds="0.5, 0.5, 0.1, 0.1" AbsoluteLayout.LayoutFlags="All" />
</AbsoluteLayout>
</ContentPage.Content>
</ContentPage>
Finally, the C# side gives us this:
public partial class CameraPage : ContentPage
{
public CameraPage()
{
InitializeComponent();
}
}
Then, we create a renderer in the UWP side :
using CameraPreviewProject.Sources.Pages;
using CameraPreviewProject.UWP.Sources.PageRenderers;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.Devices.Enumeration;
using Windows.Devices.Sensors;
using Windows.Foundation;
using Windows.Graphics.Display;
using Windows.Graphics.Imaging;
using Windows.Media;
using Windows.Media.Capture;
using Windows.Media.MediaProperties;
using Windows.Storage;
using Windows.Storage.FileProperties;
using Windows.Storage.Streams;
using Windows.System.Display;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Xamarin.Forms.Platform.UWP;
[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CameraPreviewProject.UWP.Sources.PageRenderers
{
public class CameraPageRenderer : PageRenderer
{
private readonly DisplayInformation displayInformation = DisplayInformation.GetForCurrentView();
private readonly SimpleOrientationSensor orientationSensor = SimpleOrientationSensor.GetDefault();
private readonly DisplayRequest displayRequest = new DisplayRequest();
private SimpleOrientation deviceOrientation = SimpleOrientation.NotRotated;
private DisplayOrientations displayOrientation = DisplayOrientations.Portrait;
// Rotation metadata to apply to preview stream (https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh868174.aspx)
private static readonly Guid RotationKey = new Guid("C380465D-2271-428C-9B83-ECEA3B4A85C1"); // (MF_MT_VIDEO_ROTATION)
private StorageFolder captureFolder = null;
private readonly SystemMediaTransportControls systemMediaControls = SystemMediaTransportControls.GetForCurrentView();
private MediaCapture mediaCapture;
private CaptureElement captureElement;
private bool isInitialized;
private bool isPreviewing;
private bool externalCamera;
private bool mirroringPreview;
private Page page;
private AppBarButton takePhotoButton;
private Application app;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
try
{
app = Application.Current;
app.Suspending += OnAppSuspending;
app.Resuming += OnAppResuming;
SetupUserInterface();
SetupCamera();
this.Children.Add(page);
}
catch (Exception ex)
{
Debug.WriteLine(#" ERROR: ", ex.Message);
}
}
protected override Size ArrangeOverride(Size finalSize)
{
page.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
return finalSize;
}
private void SetupUserInterface()
{
takePhotoButton = new AppBarButton
{
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,
Icon = new SymbolIcon(Symbol.Camera)
};
var commandBar = new CommandBar();
commandBar.PrimaryCommands.Add(takePhotoButton);
captureElement = new CaptureElement();
captureElement.Stretch = Stretch.UniformToFill;
var stackPanel = new StackPanel();
stackPanel.Children.Add(captureElement);
page = new Page();
page.BottomAppBar = commandBar;
page.Content = stackPanel;
page.Unloaded += OnPageUnloaded;
}
private async void SetupCamera()
{
await SetupUIAsync();
await InitializeCameraAsync();
}
#region Event Handlers
private async void OnSystemMediaControlsPropertyChanged(SystemMediaTransportControls sender, SystemMediaTransportControlsPropertyChangedEventArgs args)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
// Only handle event if the page is being displayed
if (args.Property == SystemMediaTransportControlsProperty.SoundLevel && page.Frame.CurrentSourcePageType == typeof(MainPage))
{
// Check if the app is being muted. If so, it's being minimized
// Otherwise if it is not initialized, it's being brought into focus
if (sender.SoundLevel == SoundLevel.Muted)
{
await CleanupCameraAsync();
}
else if (!isInitialized)
{
await InitializeCameraAsync();
}
}
});
}
private void OnOrientationSensorOrientationChanged(SimpleOrientationSensor sender, SimpleOrientationSensorOrientationChangedEventArgs args)
{
// Only update orientatino if the device is not parallel to the ground
if (args.Orientation != SimpleOrientation.Faceup && args.Orientation != SimpleOrientation.Facedown)
{
deviceOrientation = args.Orientation;
}
}
private async void OnDisplayInformationOrientationChanged(DisplayInformation sender, object args)
{
displayOrientation = sender.CurrentOrientation;
if (isPreviewing)
{
await SetPreviewRotationAsync();
}
}
private async void OnTakePhotoButtonClicked(object sender, RoutedEventArgs e)
{
await TakePhotoAsync();
}
/*async void OnHardwareCameraButtonPressed(object sender, CameraEventArgs e)
{
await TakePhotoAsync();
}*/
#endregion Event Handlers
#region Media Capture
private async Task InitializeCameraAsync()
{
if (mediaCapture == null)
{
var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
var cameraDevice = devices.FirstOrDefault(c => c.EnclosureLocation != null && c.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back);
// Get any camera if there isn't one on the back panel
cameraDevice = cameraDevice ?? devices.FirstOrDefault();
if (cameraDevice == null)
{
Debug.WriteLine("No camera found");
return;
}
mediaCapture = new MediaCapture();
try
{
await mediaCapture.InitializeAsync(new MediaCaptureInitializationSettings
{
VideoDeviceId = cameraDevice.Id,
AudioDeviceId = string.Empty,
StreamingCaptureMode = StreamingCaptureMode.Video,
PhotoCaptureSource = PhotoCaptureSource.Photo
});
isInitialized = true;
}
catch (UnauthorizedAccessException)
{
Debug.WriteLine("Camera access denied");
}
catch (Exception ex)
{
Debug.WriteLine("Exception initializing MediaCapture - {0}: {1}", cameraDevice.Id, ex.ToString());
}
if (isInitialized)
{
if (cameraDevice.EnclosureLocation == null || cameraDevice.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Unknown)
{
externalCamera = true;
}
else
{
// Camera is on device
externalCamera = false;
// Mirror preview if camera is on front panel
mirroringPreview = (cameraDevice.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front);
}
await StartPreviewAsync();
}
}
}
private async Task StartPreviewAsync()
{
// Prevent the device from sleeping while the preview is running
displayRequest.RequestActive();
// Setup preview source in UI and mirror if required
captureElement.Source = mediaCapture;
captureElement.FlowDirection = mirroringPreview ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
// Start preview
await mediaCapture.StartPreviewAsync();
isPreviewing = true;
if (isPreviewing)
{
await SetPreviewRotationAsync();
}
}
private async Task StopPreviewAsync()
{
isPreviewing = false;
await mediaCapture.StopPreviewAsync();
// Use dispatcher because sometimes this method is called from non-UI threads
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
// UI cleanup
captureElement.Source = null;
// Allow device screen to sleep now preview is stopped
displayRequest.RequestRelease();
});
}
private async Task SetPreviewRotationAsync()
{
// Only update the orientation if the camera is mounted on the device
if (externalCamera)
{
return;
}
// Derive the preview rotation
int rotation = ConvertDisplayOrientationToDegrees(displayOrientation);
// Invert if mirroring
if (mirroringPreview)
{
rotation = (360 - rotation) % 360;
}
// Add rotation metadata to preview stream
var props = mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview);
props.Properties.Add(RotationKey, rotation);
await mediaCapture.SetEncodingPropertiesAsync(MediaStreamType.VideoPreview, props, null);
}
private async Task TakePhotoAsync()
{
var stream = new InMemoryRandomAccessStream();
await mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream);
try
{
var file = await captureFolder.CreateFileAsync("photo.jpg", CreationCollisionOption.GenerateUniqueName);
var orientation = ConvertOrientationToPhotoOrientation(GetCameraOrientation());
await ReencodeAndSavePhotoAsync(stream, file, orientation);
}
catch (Exception ex)
{
Debug.WriteLine("Exception when taking photo: " + ex.ToString());
}
}
private async Task CleanupCameraAsync()
{
if (isInitialized)
{
if (isPreviewing)
{
await StopPreviewAsync();
}
isInitialized = false;
}
if (mediaCapture != null)
{
mediaCapture.Dispose();
mediaCapture = null;
}
}
#endregion Media Capture
#region Helpers
private async Task SetupUIAsync()
{
// Lock page to landscape to prevent the capture element from rotating
DisplayInformation.AutoRotationPreferences = DisplayOrientations.Landscape;
/*// Hide status bar
if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
{
await Windows.UI.ViewManagement.StatusBar.GetForCurrentView().HideAsync();
}*/
displayOrientation = displayInformation.CurrentOrientation;
if (orientationSensor != null)
{
deviceOrientation = orientationSensor.GetCurrentOrientation();
}
RegisterEventHandlers();
var picturesLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Pictures);
// Fallback to local app storage if no pictures library
captureFolder = picturesLibrary.SaveFolder ?? ApplicationData.Current.LocalFolder;
}
private async Task CleanupUIAsync()
{
UnregisterEventHandlers();
/*if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
{
await Windows.UI.ViewManagement.StatusBar.GetForCurrentView().ShowAsync();
}*/
// Revert orientation preferences
DisplayInformation.AutoRotationPreferences = DisplayOrientations.None;
}
private void RegisterEventHandlers()
{
/*if (ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
{
HardwareButtons.CameraPressed += OnHardwareCameraButtonPressed;
}*/
if (orientationSensor != null)
{
orientationSensor.OrientationChanged += OnOrientationSensorOrientationChanged;
}
displayInformation.OrientationChanged += OnDisplayInformationOrientationChanged;
systemMediaControls.PropertyChanged += OnSystemMediaControlsPropertyChanged;
takePhotoButton.Click += OnTakePhotoButtonClicked;
}
private void UnregisterEventHandlers()
{
/*if (ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
{
HardwareButtons.CameraPressed -= OnHardwareCameraButtonPressed;
}*/
if (orientationSensor != null)
{
orientationSensor.OrientationChanged -= OnOrientationSensorOrientationChanged;
}
displayInformation.OrientationChanged -= OnDisplayInformationOrientationChanged;
systemMediaControls.PropertyChanged -= OnSystemMediaControlsPropertyChanged;
takePhotoButton.Click -= OnTakePhotoButtonClicked;
}
private static async Task ReencodeAndSavePhotoAsync(IRandomAccessStream stream, StorageFile file, PhotoOrientation orientation)
{
using (var inputStream = stream)
{
var decoder = await BitmapDecoder.CreateAsync(inputStream);
using (var outputStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateForTranscodingAsync(outputStream, decoder);
var properties = new BitmapPropertySet
{
{
"System.Photo.Orientation", new BitmapTypedValue(orientation, Windows.Foundation.PropertyType.UInt16)
}
};
await encoder.BitmapProperties.SetPropertiesAsync(properties);
await encoder.FlushAsync();
}
}
}
#endregion Helpers
#region Rotation
private SimpleOrientation GetCameraOrientation()
{
if (externalCamera)
{
// Cameras that aren't attached to the device do not rotate along with it
return SimpleOrientation.NotRotated;
}
var result = deviceOrientation;
// On portrait-first devices, the camera sensor is mounted at a 90 degree offset to the native orientation
if (displayInformation.NativeOrientation == DisplayOrientations.Portrait)
{
switch (result)
{
case SimpleOrientation.Rotated90DegreesCounterclockwise:
result = SimpleOrientation.NotRotated;
break;
case SimpleOrientation.Rotated180DegreesCounterclockwise:
result = SimpleOrientation.Rotated90DegreesCounterclockwise;
break;
case SimpleOrientation.Rotated270DegreesCounterclockwise:
result = SimpleOrientation.Rotated180DegreesCounterclockwise;
break;
case SimpleOrientation.NotRotated:
result = SimpleOrientation.Rotated270DegreesCounterclockwise;
break;
}
}
// If the preview is mirrored for a front-facing camera, invert the rotation
if (mirroringPreview)
{
// Rotating 0 and 180 ddegrees is the same clockwise and anti-clockwise
switch (result)
{
case SimpleOrientation.Rotated90DegreesCounterclockwise:
return SimpleOrientation.Rotated270DegreesCounterclockwise;
case SimpleOrientation.Rotated270DegreesCounterclockwise:
return SimpleOrientation.Rotated90DegreesCounterclockwise;
}
}
return result;
}
private static int ConvertDeviceOrientationToDegrees(SimpleOrientation orientation)
{
switch (orientation)
{
case SimpleOrientation.Rotated90DegreesCounterclockwise:
return 90;
case SimpleOrientation.Rotated180DegreesCounterclockwise:
return 180;
case SimpleOrientation.Rotated270DegreesCounterclockwise:
return 270;
case SimpleOrientation.NotRotated:
default:
return 0;
}
}
private static int ConvertDisplayOrientationToDegrees(DisplayOrientations orientation)
{
switch (orientation)
{
case DisplayOrientations.Portrait:
return 90;
case DisplayOrientations.LandscapeFlipped:
return 180;
case DisplayOrientations.PortraitFlipped:
return 270;
case DisplayOrientations.Landscape:
default:
return 0;
}
}
private static PhotoOrientation ConvertOrientationToPhotoOrientation(SimpleOrientation orientation)
{
switch (orientation)
{
case SimpleOrientation.Rotated90DegreesCounterclockwise:
return PhotoOrientation.Rotate90;
case SimpleOrientation.Rotated180DegreesCounterclockwise:
return PhotoOrientation.Rotate180;
case SimpleOrientation.Rotated270DegreesCounterclockwise:
return PhotoOrientation.Rotate270;
case SimpleOrientation.NotRotated:
default:
return PhotoOrientation.Normal;
}
}
#endregion Rotation
#region Lifecycle
private async void OnAppSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
await CleanupCameraAsync();
await CleanupUIAsync();
deferral.Complete();
}
private async void OnAppResuming(object sender, object o)
{
await SetupUIAsync();
await InitializeCameraAsync();
}
private async void OnPageUnloaded(object sender, RoutedEventArgs e)
{
await CleanupCameraAsync();
await CleanupUIAsync();
}
#endregion Lifecycle
}
}
This idea is pretty logic, you have a basic page, but which have renderer that preview the camera in the background, I mean, this is the idea I understood, however, it only gives you a white screen that throws an exception… (x86)
Exception initializing MediaCapture - \\?\USB#VID_045E&PID_0779&MI_00#6&2E9BBB25&0&0000#{e5323777-f976-4f5b-9b55-b94699c46e44}\GLOBAL: System.Runtime.InteropServices.COMException (0xC00DABE6): The current capture source does not have an independent photo stream.
The current capture source does not have an independent photo stream.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at CameraPreviewProject.UWP.Sources.PageRenderers.CameraPageRenderer.<InitializeCameraAsync>d__25.MoveNext()
Then I click the button of the downside woft menu and get:
Exception thrown: 'System.Runtime.InteropServices.COMException' in System.Private.CoreLib.ni.dll
WinRT information: This object needs to be initialized before the requested operation can be carried out.
I’m a Xamarin Fan, but on that part, I’m not. This link about MediaCapture can be interesting though!
CameraView
To be honest, it’s so way easier to have a control as a button!
<Camera/>
Well, let’s have a look at it! I found a couple of solutions:
Moment MVVM logic - It seems to work only with Android & iOS
Xlabs Camera Unable to try since I can’t start VS2017 from the .sln. Also, I couldn't test the UWP side because it's an MVVM logic..
Xam.Plugin.Media This solution works on UWP !! But run a new activity/instance/page with a native design, so this isn't the solution searched
So, my question is “Does someone could create an element public class Camera() that can be used and declared as a simple xamarin forms button?”
Because, I saw as well 2 others projects about it, one I can’t remember, but the second one is Barcode Scanning but I’m not able to understand or take back the code to implement it as I would like…
It seems so easy and it’s so hard to get, why? Because finally, we’re talking about a view/image that displays a stream from a camera? A camera is just a service where you have methods such as TakePictureAsync() or anything like that? Rotate(), Switch(ViewSide vs), etc etc?
So, I searched about getting a frame view or display the stream of the camera into an image or a view.. I began from those links:
UWP get live webcam video stream by David Pine
UWP stream Webcam over socket to mediaElement I just made some changes
because the subject is a bit different, but.. I couldn't make it work
To be honest, I don’t know what to try now… I’m lost because, at the same time, I tried some Xamarin Forms solution, but also some proper UWP solutions and … nothing…. Maybe my point of view is not good, maybe my idea and just on the side, maybe I should try another approach, I don’t know at all..
I was also thinking about creating a class with some interface that I redefine in each platform renderer, but, still nothing…
Do you have please, any idea or any approach?
Note I have cross-posed this to the Xamarin forums.

Global Exception Handling in Xamarin Cross platform

Can you please let me know how to handle the global exception(without App crash) in Xamarin Cross platform project.
There isn't a 'Xamarin.Forms' way of doing it that I know of. You need to hook into Android and iOS, what you could do is create one method that handles them both in the same way.
A nice post about this is by Peter Norman. He describes that to implement it in Android you can do this in your MainActivity.cs.
// In MainActivity
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException;
Xamarin.Forms.Forms.Init(this, bundle);
DisplayCrashReport();
var app = new App();
LoadApplication(app);
}
‪#‎region‬ Error handling
private static void TaskSchedulerOnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs unobservedTaskExceptionEventArgs)
{
var newExc = new Exception("TaskSchedulerOnUnobservedTaskException", unobservedTaskExceptionEventArgs.Exception);
LogUnhandledException(newExc);
}
private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
var newExc = new Exception("CurrentDomainOnUnhandledException", unhandledExceptionEventArgs.ExceptionObject as Exception);
LogUnhandledException(newExc);
}
internal static void LogUnhandledException(Exception exception)
{
try
{
const string errorFileName = "Fatal.log";
var libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // iOS: Environment.SpecialFolder.Resources
var errorFilePath = Path.Combine(libraryPath, errorFileName);
var errorMessage = String.Format("Time: {0}\r\nError: Unhandled Exception\r\n{1}",
DateTime.Now, exception.ToString());
File.WriteAllText(errorFilePath, errorMessage);
// Log to Android Device Logging.
Android.Util.Log.Error("Crash Report", errorMessage);
}
catch
{
// just suppress any error logging exceptions
}
}
/// <summary>
// If there is an unhandled exception, the exception information is diplayed
// on screen the next time the app is started (only in debug configuration)
/// </summary>
[Conditional("DEBUG")]
private void DisplayCrashReport()
{
const string errorFilename = "Fatal.log";
var libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var errorFilePath = Path.Combine(libraryPath, errorFilename);
if (!File.Exists(errorFilePath))
{
return;
}
var errorText = File.ReadAllText(errorFilePath);
new AlertDialog.Builder(this)
.SetPositiveButton("Clear", (sender, args) =>
{
File.Delete(errorFilePath);
})
.SetNegativeButton("Close", (sender, args) =>
{
// User pressed Close.
})
.SetMessage(errorText)
.SetTitle("Crash Report")
.Show();
}
‪#‎endregion‬
And for iOS you can add code like this in your AppDelegate.cs.
//iOS: Different than Android. Must be in FinishedLaunching, not in Main.
// In AppDelegate
public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary options)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException;
// Rest of your code...
}
/// <summary>
// If there is an unhandled exception, the exception information is diplayed
// on screen the next time the app is started (only in debug configuration)
/// </summary>
[Conditional("DEBUG")]
private static void DisplayCrashReport()
{
const string errorFilename = "Fatal.log";
var libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Resources);
var errorFilePath = Path.Combine(libraryPath, errorFilename);
if (!File.Exists(errorFilePath))
{
return;
}
var errorText = File.ReadAllText(errorFilePath);
var alertView = new UIAlertView("Crash Report", errorText, null, "Close", "Clear") { UserInteractionEnabled = true };
alertView.Clicked += (sender, args) =>
{
if (args.ButtonIndex != 0)
{
File.Delete(errorFilePath);
}
};
alertView.Show();
}
It also includes the ability to show the log when you're debugging the application. Of course you can implement your own logging or handling methods. One thing you could look at is HockeyApp. This handles unhandled exceptions by default and sends them back to you, amongst other things.
Update, since this is still found on Google: For crash reporting and analytics you now want to start looking at App Center. This is the evolvement of HockeyApp and Xamarin Insights (among others like building, distributing and push notifications) and now acts as the mission dashboard for everything that has to do with apps, and not just Xamarin.
For UWP and WinPhone 8.1 there should be a UnhandledException handler in the Application object. Check out this answer for more information. I quote:
For XAML-based apps, you can use UnhandledException; however, that
only captures exceptions that come up through the XAML (UI) framework
and you don't always get a lot of information about what the root
cause is, even in InnerException.
Update for Windows 8.1: UnhandledException also will capture
exceptions that are created by an async void method. In Windows 8,
such exceptions would just crash the app. LunarFrog has a good
discussion of this on their website.
Basically you should add a event handler in the constructor of your App() in App.xaml.cs: this.UnhandledException += (o, s) => {}.
This is what I did for xamarin forms Android global exception handling and app crashes.
This solution will handle both background and foreground exceptions.
AppDomain.CurrentDomain.UnhandledException += (s,e)=>
{
System.Diagnostics.Debug.WriteLine("AppDomain.CurrentDomain.UnhandledException: {0}. IsTerminating: {1}", e.ExceptionObject, e.IsTerminating);
};
AndroidEnvironment.UnhandledExceptionRaiser += (s, e) =>
{
System.Diagnostics.Debug.WriteLine("AndroidEnvironment.UnhandledExceptionRaiser: {0}. IsTerminating: {1}", e.Exception, e.Handled);
e.Handled = true;
};
As a result, I have different behavior for both types of exceptions:
foreground:
background:

GLSurfaceView.Renderer crashes when resuming because "bitmap is recycled"

once again I need some help:
yesterday I asked this question that was about the way to use a large jpg image as a Bitmap (http://stackoverflow.com/questions/13511657/problems-with-big-drawable-jpg-image) and I resolved myself (Is my own response on that question) but whenever I resume my activity, as it uses that bitmap as the GLRenderer texture it crashes. I've tried many things, the last try was to make that bitmap static in order to keep it as a member variable into the activity but it crashes because, I supose, it looses it's mBuffer.
More details on the Activity code:
I declared it as SingletonInstance into the manifest:
android:launchMode="singleInstance"
in order to keep the tiles for the renderer.
and here some code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLSurfaceView = new GLSurfaceView(this);
mGLSurfaceView.setEGLConfigChooser(true);
mSimpleRenderer = new GLRenderer(this);
getTextures();
if (!mIsTileMapInitialized){
tileMap = new LandSquareGrid(1, 1, mHeightmap, mLightmap, false, true, true, 128, true);
tileMap.setupSkybox(mSkyboxBitmap, true);
mIsTileMapInitialized = true;
}
initializeRenderer();
mGLSurfaceView.setRenderer(mSimpleRenderer);
setContentView( R.layout.game_layout );
setOnTouchListener();
initializeGestureDetector();
myCompassView = (MyCompassView)findViewById(R.id.mycompassview);
// Once set the content view we can set the TextViews:
coordinatesText = (TextView) findViewById(R.id.coordDynamicText);
altitudeText = (TextView) findViewById(R.id.altDynamicText);
directionText = (TextView) findViewById(R.id.dirDynamicText);
//if (!mIsGLInitialized){
mOpenGLLayout = (LinearLayout)findViewById(R.id.openGLLayout);
mOpenGLLayout.addView(mGLSurfaceView);
mVirtual3DMap = new Virtual3DMap(mSimpleRenderer, tileMap);
if (mGameThread == null){
mGameThread = new Thread(mVirtual3DMap);
mGameThread.start();
}
}
On getTextures method I get few small textures and the largest one as in my last question self response:
if (mTerrainBitmap==null){
InputStream is = getResources().openRawResource(R.drawable.terrain);
try {
// Set terrain bitmap options to 16-bit, 565 format.
terrainBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap auxBitmap = BitmapFactory.decodeStream(is, null, terrainBitmapOptions);
mTerrainBitmap = Bitmap.createBitmap(auxBitmap);
}
catch (Exception e){
}
finally {
try {
is.close();
}
catch (IOException e) {
// Ignore.
}
}
}
So, again, first time it works great but when I go back I do:
protected void onPause() {
super.onPause();
mGLSurfaceView.onPause();
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
if (mVirtual3DMap != null) {
try {
mVirtual3DMap.cancel();
mGameThread=null;
mVirtual3DMap = null;
mGLSurfaceView.destroyDrawingCache();
mSimpleRenderer=null;
System.gc();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And whan I resume the activity:
#Override
protected void onResume() {
super.onResume();
mGLSurfaceView.onResume();
if (mVirtual3DMap != null) {
try {
mVirtual3DMap.resume();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
And it crashes.
Why?? Ok, here is the exception cause on the GLThread:
java.lang.IllegalArgumentException: bitmap is recycled...
I tried this messy stuff because launching more than two times the original activity the application crashes bacuse of this or because of the amount of memory used and now I don't know if revert all these changes or what todo with this.
Is there a good way to keep in memory and usable, by this or another application activity, this bitmap?
Please, I need your advices.
Thanks in advance.
Do not handle resources manually or your app's surface will broke up. You can't handle your resources manually.
If you worry about reloading resources and you use API level 11+, you can use setPreserveEGLContextOnPause(). It will perserve your textures and FBOs.
If you can't use API 11+, you can port GLSurfaceView() to your app. You can check my own GLSurfaceView that is ported from ICS.
PS: Sorry about my poor english.
No. Let Android handle all the resources. You must handle the appropriate events and reload the bitmap when the activity is resumed. You cannot expect, that any OpenGL handles are still valid after the activity has been resumed.
Think of it as in the example of a laptop coming out from hibernation. Although all memory has been restored, you cannot expect that any open socket has still a real active connection going.
I am an Android noobie, so please correct me if I am wrong.

Debugger always Break when invoke GetFileAsync in windows 8 store apps (metro style)

This problem confuse me several days, when the code run to
await ApplicationData.Current.LocalFolder.GetFileAsync(udFileName);
The app was always jump to
UnhandledException += (sender, e) =>
{
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
};
The Exception e is:
{Windows.UI.Xaml.UnhandledExceptionEventArgs}
Exception {"Object reference not set to an instance of an object."}
System.Exception {System.NullReferenceException}
Message "System.NullReferenceException.......
Following is the function I invoked:
public async void RestoreUserDefaults()
{
string udFileName = "userdefaults.udef";
bool bExist = true;
{
try
{
await ApplicationData.Current.LocalFolder.GetFileAsync(udFileName);
}
catch (FileNotFoundException)
{
bExist = false;
}
}
}
I had add the file type to the package.appxmanifest.
anyone can help me, so many thanks.....

How to stop led torch/flashlight app using Reflection in Windows Phone 7

I am making an Flashlight app, in which I need to use the camera's LED constantly on pressing ON button and OFF it on pressing the same button. I followed this article Turning on the LED with the video camera using Reflection. The ON/OFF operation works fine only once. The Code is as:
private VideoCamera _videoCamera;
private VideoCameraVisualizer _videoCameraVisualizer;
bool _isFlashOff = true;
private void FlashButton_Click(object sender, RoutedEventArgs e)
{
try
{
if (_isFlashOff)
{
_isFlashOff = false;
// Check to see if the camera is available on the device.
if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary))
{
// Use standard camera on back of device.
_videoCamera = new VideoCamera();
// Event is fired when the video camera object has been initialized.
_videoCamera.Initialized += VideoCamera_Initialized;
// Add the photo camera to the video source
_videoCameraVisualizer = new VideoCameraVisualizer();
_videoCameraVisualizer.SetSource(_videoCamera);
}
}
else
{
_isFlashOff = true;
_videoCamera.StopRecording();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void VideoCamera_Initialized(object sender, EventArgs e)
{
_videoCamera.LampEnabled = true;
_videoCamera.StartRecording();
}
Since there was no implementation of StopRecording Method in VideoCamera class as specified in the article: Turning on the LED with the video camera using Reflection . I made the function as:
public void StopRecording()
{
// Invoke the stop recording method on the video camera object.
_videoCameraStopRecordingMethod.Invoke(_videoCamera, null);
}
The problem is when I again press ON button "Exception' is thrown as "TargetInvocationException". I am unable to figure out the problem that causes exception. Is StopRecording() function right..??
That's because you should initialize the camera only once. Do it during the OnNavigatedTo event, then re-use the same instances:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
// Use standard camera on back of device.
_videoCamera = new VideoCamera();
// Event is fired when the video camera object has been initialized.
_videoCamera.Initialized += VideoCamera_Initialized;
// Add the photo camera to the video source
_videoCameraVisualizer = new VideoCameraVisualizer();
_videoCameraVisualizer.SetSource(_videoCamera);
}
private void VideoCamera_Initialized(object sender, EventArgs e)
{
isInitialized = true;
}
bool isInitialized;
bool isFlashEnabled;
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
if (!isInitialized)
{
MessageBox.Show("Please wait during camera initialization");
return;
}
if (!isFlashEnabled)
{
isFlashEnabled = true;
// Check to see if the camera is available on the device.
if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary))
{
_videoCamera.LampEnabled = true;
_videoCamera.StartRecording();
}
}
else
{
isFlashEnabled = false;
_videoCamera.StopRecording();
}
}
Try this:
http://msdn.microsoft.com/en-us/library/hh202949.aspx

Resources