AirPrint UIWebView content in iOS8 - uiwebview

I am trying to AirPrint the contents of my UIWebView (iOS8.1) and am getting an exception with no detail as to what the problem is. If I toggle "Global Breakpoint State" to OFF in Xcode 6.1 then it occasionally prints, although sometimes the page is blank. I am also using an up-to-date installation of Printopia for printing to the iMac.
Is anyone else experiencing problems with AirPrinting in iOS8? Are there any problems with the code below that could be causing this issue?
// AirPrint functionality
-(void)printBid {
if ([UIPrintInteractionController isPrintingAvailable]) { // check that we can print
// Use UIPrintInteractionController to print the web view content
// This generates an exception when Global Breakpoint State is set to On but seems to work when Off
UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController];
//pic.delegate = self;
UIPrintInfo *printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGeneral;
printInfo.jobName = #"QuickBids";
printInfo.duplex = UIPrintInfoDuplexLongEdge;
pic.printInfo = printInfo;
pic.showsPageRange = YES;
UIViewPrintFormatter *formatter = [bidPreviewWebView viewPrintFormatter];
pic.printFormatter = formatter;
UIPrintInteractionCompletionHandler completionHandler =
^(UIPrintInteractionController *printController, BOOL completed,
NSError *error) {
if(!completed && error){
NSLog(#"Print failed - domain: %# error code %u", error.domain,
error.code);
}
};
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { // The device is an iPad running iPhone 3.2 or later.
// iOS 8 Issue on iPad - As a workaround, I recommend delaying the presentation until the next runloop, using the following method:
// http://stackoverflow.com/questions/24854802/presenting-a-view-controller-modally-from-an-action-sheets-delegate-in-ios8
dispatch_async(dispatch_get_main_queue(), ^ {
[pic presentFromBarButtonItem:shareButton animated:YES completionHandler:completionHandler];
});
}else { // The device is an iPhone or iPod touch.
dispatch_async(dispatch_get_main_queue(), ^ {
[pic presentAnimated:YES completionHandler:completionHandler];
});
}
}else { // we can't print so show an alert
// show simple alert
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:#"Printing Unavailable"
message:#"You cannot print from this device."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction
actionWithTitle:NSLocalizedString(#"OK", #"OK action")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action)
{
NSLog(#"OK action");
}];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
}
}
Thanks in advance for any help.

Related

Xamarin.Forms Warning: Attempt to present * on * whose view is not in the window hierarchy with iOS image/gesture recogniser

I have a modal Navigation page with an image which acts like a button;
<Image Source ="share.png" HeightRequest="32" WidthRequest="32">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="On_Share" />
</Image.GestureRecognizers>
</Image>
And the method behind;
async void On_Share(object sender, EventArgs e)
{
if (CrossConnectivity.Current.IsConnected)
{
var message = "Share this";
var title = "Share";
await CrossShare.Current.Share(new ShareMessage { Text = message, Title = title}, new ShareOptions { ExcludedUIActivityTypes = new[] { ShareUIActivityType.PostToFacebook } });
}
else
{
NoInternetLabel.IsVisible = true;
}
}
I'm getting the error when I try to click on the share image/button. I've put breakpoints into the first line of the On_Share method & they're not being hit.
Warning: Attempt to present <UIActivityViewController: 0x141b60f70> on <Xamarin_Forms_Platform_iOS_ModalWrapper: 0x1419a0920> whose view is not in the window hierarchy!
Please note this works fine in Android, I'm only seeing issues in iOS. I'm not sure what is going on - I'm not trying to present any other windows or anything when I click the image. Regardless, the error appears before the process reaches the beginning of the On_Share method. What am I missing here?
EDIT: The method does get hit now, and I'm still getting the error. It must be trying to send up the share sheet and failing...
There was a problem with the Share plugin in the end - we resolved it by making part of the code recursive.
the GetVisibleViewController used to look like this;
UIViewController GetVisibleViewController()
{
var rootController = UIApplication.SharedApplication.KeyWindow.RootViewController;
if (rootController.PresentedViewController == null)
return rootController;
if (rootController.PresentedViewController is UINavigationController)
{
return ((UINavigationController)rootController.PresentedViewController).VisibleViewController;
}
if (rootController.PresentedViewController is UITabBarController)
{
return ((UITabBarController)rootController.PresentedViewController).SelectedViewController;
}
return rootController.PresentedViewController;
}
whereas it needed to cycle through to find the top UIViewController;
UIViewController GetVisibleViewController(UIViewController controller = null)
{
controller = controller ?? UIApplication.SharedApplication.KeyWindow.RootViewController;
if (controller.PresentedViewController == null)
return controller;
if (controller.PresentedViewController is UINavigationController)
{
return ((UINavigationController)controller.PresentedViewController).VisibleViewController;
}
if (controller.PresentedViewController is UITabBarController)
{
return ((UITabBarController)controller.PresentedViewController).SelectedViewController;
}
return GetVisibleViewController(controller.PresentedViewController);
}
I've raised the issue and submitted a pull request on the github

Why crash happens when using a FileOpenPicker in my UWP app?

Recently I am writing an app on My PC and lumia 640, everything seems good when it runs under Debug mode in VS 2015, but when I use it on my phone and tap a button to open a FileOpenPicker to choose picture from PicturesLibrary, it just crash...
When I try connecting my phone and use VS to find the problem, it never shows up any more...Also, when I run my app on my PC, whether under Debug mode or not, the problem also never happens.
The Listener of the button looks like this:
private async void OnSnap(object sender, RoutedEventArgs e)
{
try
{
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
fileOpenPicker.FileTypeFilter.Add(".jpg");
fileOpenPicker.FileTypeFilter.Add(".png");
fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
var inputFile = await fileOpenPicker.PickSingleFileAsync();
if (inputFile == null)
{
// The user cancelled the picking operation
return;
}
else
{
Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(inputFile);
Frame frame = Window.Current.Content as Frame;
frame.Navigate(typeof(PictureChoosePage), await inputFile.OpenAsync(FileAccessMode.Read));
}
}
catch (Exception exception)
{
Debug.WriteLine(exception.Message);
var msgDialog = new MessageDialog(exception.Message) { Title = "Unkown Error" };
msgDialog.Commands.Add(new Windows.UI.Popups.UICommand("OK", uiCommand => {
Frame frame = Window.Current.Content as Frame;
frame.Navigate(typeof(MainPage));
}));
msgDialog.Commands.Add(new Windows.UI.Popups.UICommand("Cancel", uiCommand => { }));
await msgDialog.ShowAsync();
return;
}
}
One more thing to mention is that when my App crash, the bottom bar of the FileOpenPicker shows up...like this:
The required permissions should have been declared, and if there is a UnathorizedAccessException thrown, it should be caught by my code...So I'm thinking if this is the bug of the OS since the windows 10 mobile on my lumia 640 is 10.0.14295.1000, just a preview version.

How to switch to Front Camera in Windows Phone 8.1 (WinRT/Jupiter)

I can't seem to find the property for the MediaCapture class that allows me to detect the front camera and switch to it if available. Here is my current setup of the device, it all works as expected on Windows (front cam) and Phone (rear cam). None of the Microsoft samples show the front camera being used in Universal or WP 8.1 (WinRT/Jupiter).
mediaCaptureManager = new MediaCapture();
await mediaCaptureManager.InitializeAsync();
if (mediaCaptureManager.MediaCaptureSettings.VideoDeviceId != "" && mediaCaptureManager.MediaCaptureSettings.AudioDeviceId != "")
{
StartStopRecordingButton.IsEnabled = true;
TakePhotoButton.IsEnabled = true;
ShowStatusMessage("device initialized successfully!");
mediaCaptureManager.VideoDeviceController.PrimaryUse = CaptureUse.Video;
mediaCaptureManager.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
mediaCaptureManager.SetRecordRotation(VideoRotation.Clockwise90Degrees);
mediaCaptureManager.RecordLimitationExceeded += RecordLimitationExceeded;
mediaCaptureManager.Failed += Failed;
}
There is a sample on the Microsoft github page that is relevant, although they target Windows 10. Still, the APIs should work on 8/8.1.
UniversalCameraSample: This one does capture photos, and supports portrait and landscape orientations. Here is the relevant part:
private static async Task<DeviceInformation> FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel desiredPanel)
{
// Get available devices for capturing pictures
var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
// Get the desired camera by panel
DeviceInformation desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredPanel);
// If there is no device mounted on the desired panel, return the first device found
return desiredDevice ?? allVideoDevices.FirstOrDefault();
}
And you can use it like so:
// Attempt to get the front camera if one is available, but use any camera device if not
var cameraDevice = await FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel.Front);
if (cameraDevice == null)
{
Debug.WriteLine("No camera device found!");
return;
}
// Create MediaCapture and its settings
_mediaCapture = new MediaCapture();
var settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameraDevice.Id };
// Initialize MediaCapture
try
{
await _mediaCapture.InitializeAsync(settings);
_isInitialized = true;
}
catch (UnauthorizedAccessException)
{
Debug.WriteLine("The app was denied access to the camera");
}
catch (Exception ex)
{
Debug.WriteLine("Exception when initializing MediaCapture with {0}: {1}", cameraDevice.Id, ex.ToString());
}
Have a closer look at the sample to see how to get all the details. Or, to have a walkthrough, you can watch the camera session from the recent //build/ conference, which includes a little bit of a walkthrough through some camera samples.
Here is how to get the device's available cameras and set the front one for the stream:
mediaCaptureManager = new MediaCapture();
var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
var deviceInfo = devices[0]; //grab first result
foreach (var device in devices)
{
if (device.Name.ToLowerInvariant().Contains("front"))
{
deviceInfo = frontCamera = device;
hasFrontCamera = true;
}
if (device.Name.ToLowerInvariant().Contains("back"))
{
rearCamera = device;
}
}
var mediaSettings = new MediaCaptureInitializationSettings
{
MediaCategory = MediaCategory.Communications,
StreamingCaptureMode = StreamingCaptureMode.AudioAndVideo,
VideoDeviceId = deviceInfo.Id
};
await mediaCaptureManager.InitializeAsync(mediaSettings);
You'll need to consider rotation because front and rear cameras on different devices have different rotations, but this will initialize your MediaCapture properly

How to use a 'Container View' in iOS? (storyboard)

i want to use a container view in story board project with mono touch and i don't know good objective c have a lot of sample but i couldn't understand.
thanks a lot
i have 4 view controller on my project and one customseque
i don't know how to call first view controller in main view controller
i try to put some codes in container view controller but couldn't success please help me from where i have to call and which code will call it - please xamarin code ..
i solved my problem like this.. thanks by the way who is viewed this question..
public override void PrepareForSegue (UIStoryboardSegue segue, NSObject sender)
{
base.PrepareForSegue (segue, sender);
if (segue.Identifier == SegueIdentifierFirst) {
var a = segue.DestinationViewController as FirstViewController;
firstViewController = a;
}
if (segue.Identifier == SegueIdentifierSecond) {
var b = segue.DestinationViewController as SecondViewController;
secondViewController = b;
}
if (segue.Identifier == SegueIdentifierFirst) {
if (this.ChildViewControllers.Length > 0) {
this.swapFromViewController (this.ChildViewControllers [0], this.firstViewController);
} else {
this.AddChildViewController(firstViewController);
UIView destView = ((UIViewController)firstViewController).View;
destView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
destView.Frame = new RectangleF(0, 0, this.View.Frame.Size.Width, this.View.Frame.Size.Height);
this.View.AddSubview(destView);
(firstViewController).DidMoveToParentViewController (this);
}
} else if (segue.Identifier == SegueIdentifierSecond) {
swapFromViewController (this.ChildViewControllers[0], this.secondViewController);
}
}

Got a SIGSEGV while setting the Text of my TextField from a ABPeoplePickerModule

In my App the User needs to type in some Address Information.
I provide an Addressbook Button for that since Version 1.0.
That worked fine in my previous tests, but now I get a SIGSEGV when I try to set my UITextField.Text property. This error occurs everytime when I try to Pick an Address from the PeoplePicker in MonoTouches Debug mode, when I try that on my iPhone the eror occurs randomly between setting the TextFields and pushing the next ViewController.
Is There anything wrong in my Code or is it a bug?
//AB Button Event
addressBook.TouchUpInside += delegate {
//Create new Picker
ABPeoplePickerNavigationController PP = new ABPeoplePickerNavigationController();
//Cancel Event
PP.Cancelled += delegate {
NavigationController.DismissViewController(true, null);
};
//Select Event
PP.SelectPerson += delegate(object sender, ABPeoplePickerSelectPersonEventArgs e) {
//Detailed Person View
ABPersonViewController pv = new ABPersonViewController();
//Action when clicked on a Property
pv.PerformDefaultAction += delegate(object person, ABPersonViewPerformDefaultActionEventArgs ev) {
//If the Property was an Address
if(ev.Property.ToString() == "Address"){
string lands = "", orts = "", plzs = "";
try{
//Read the Detailed Address Data from the clicked property
ABMultiValue<PersonAddress> addresses = ev.Person.GetAllAddresses();
PersonAddress[] values = addresses.GetValues();
lands = values[ev.Identifier.Value].Country.ToString();
orts = values[ev.Identifier.Value].City.ToString();
plzs = values[ev.Identifier.Value].Zip.ToString();
}catch{
Console.WriteLine("Fehlerhafte Addresse");
}
//Set the Textfield with the new information
//iPhone Simulator in Debugmode crashes here everytime
land.Text = lands;
ort.Text = orts;
plz.Text = plzs;
//Close the Module
NavigationController.DismissViewController(true, null);
}
};
//Set selected Person for the person View
pv.DisplayedPerson = e.Person;
//Open Person View with navigation from the PeoplePicker Controller
PP.PushViewController(pv, true);
};
//Open PeoplePicker Controller Module
NavigationController.PresentViewController(PP, true, null);
};
Thanks in advance!
The just released MonoTouch 6.0.5 has a fix for a similar issue.

Resources