UIActivityViewController thinks my jpg is video when share by file URL - ios

I have jpg files saved in the Documents directory that can be shared from a standard UIActivityViewController. All activity items (including Save Image) work as expected, but when Save Image is tapped, the following error shows in the console, despite the fact that the jpg does actually get saved to the camera roll.
Is this a bug in iOS, or do I have to somehow specify that my file is a jpg (and not a video) in the file URL?
2015-07-29 06:46:58.317 AppName[4658:893408] Video /var/mobile/Containers/Data/Application/A63DF08E-21D0-435D-A0D7-84D73D632FC9/Documents/ImageStore/805/23.jpg cannot be saved to the saved photos album: Error Domain=AVFoundationErrorDomain Code=-11828 "Cannot Open" UserInfo=0x1702e8b80 {NSLocalizedFailureReason=This media format is not supported., NSLocalizedDescription=Cannot Open, NSURL=file:///var/mobile/Containers/Data/Application/A63DF08E-21D0-435D-A0D7-84D73D632FC9/Documents/ImageStore/805/23.jpg, NSUnderlyingError=0x170c4f9f0 "The operation couldn’t be completed. (OSStatus error -12847.)"}
Here's the code I'm using:
NSURL *fileURL = [NSURL fileURLWithPath: [...path to my file...] isDirectory:NO];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[fileURL] applicationActivities:nil];
activityViewController.excludedActivityTypes = #[UIActivityTypeCopyToPasteboard, UIActivityTypePrint, UIActivityTypeAssignToContact, UIActivityTypeAddToReadingList, UIActivityTypePostToVimeo];
[self presentViewController:activityViewController animated:YES completion:nil];

I got the above message when trying to save a png file. Also noticed some other error messages. In tracking those down, got rid of both problems by applying the OS_ACTIVITY_MODE with disable as seen in following question/answer: "Reading from public effective user settings" in iOS 10

Related

Error while saving JPG/PNG photo to gallery in IOS 11

I was testing our application on new device with beta iOS 11 and found an intresting error.
We are creating an image which can be saved to user gallery, using UIActivityViewController (some system share view controller):
NSMutableArray *sharingItems = [NSMutableArray new];
UIImage *screenShot = [self shareViewScreenShot];
NSString *filename = #"notImportant";
NSString *path = [NSString stringWithFormat:#"%#%#.jpg", NSTemporaryDirectory(), filename];
[UIImageJPEGRepresentation(screenShot, 1.0) writeToFile:path atomically:YES];
NSURL *pathUrl = [NSURL fileURLWithPath:path];
[sharingItems addObject:pathUrl];
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
[self presentViewController:activityController animated:YES completion:nil];
This works fine, presenting share dialog, until user press "save image". Then I got error about not suporting this image format
2017-07-19 10:51:54.292881+0200 appName[6632:766119] Video
/private/var/mobile/Containers/Data/Application/29B8C33B-9247-45FE-B51F-A35A035019A9/tmp/notImportant.jpg
cannot be saved to the saved photos album: Error
Domain=AVFoundationErrorDomain Code=-11828 "Nie można otworzyć"
UserInfo={NSUnderlyingError=0x1c08558d0 {Error
Domain=NSOSStatusErrorDomain Code=-12847 "(null)"},
NSLocalizedFailureReason=Ten format multimediów nie jest obsługiwany.,
NSURL=file:///private/var/mobile/Containers/Data/Application/29B8C33B-9247-45FE-B51F-A35A035019A9/tmp/notImportant.jpg,
NSLocalizedDescription=Nie można otworzyć}
The same happens when I use png/UIImagePNGRepresentation.
So the questions are:
Are png/jpg supported in iOS 11?
Should I use/and how HEIF (new apple image format) for devices with os version >= 11?
NSOSStatusErrorDomain code means the property data size was not correct.
OSStatus is a type commonly used for error codes in OS X and iOS. If the magnitude of the code is less than 1 million, then the code is probably listed in MacErrors.h in the CarbonCore framework. Otherwise, it is probably a four-character code listed in the same header as the function which returned it. You can find the header of a function by command-clicking it in Xcode. The codes will most likely be listed near the top, grouped together. To convert the number to a code, use the Calculator app in Developer view to convert it to hexadecimal and convert each byte to a character.
iOS treates image as video? Is this a bug on iOS or some permission is missing.
Solution:
Add permissions that was missing in Info.plist file:
<key>NSPhotoLibraryUsageDescription</key>
<string>Application needs to access photos</string>
for iOS 11+
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Application needs to access photos</string>
Now Save Image action is working ok.

UIImage imageWithContentsOfFile: not working on real device

I'm creating a tableView which contains the images from gallery picked by the user, then I take the selected imagePath to place it on an UIImageView.
To set an iOS gallery image in a UIImageView,
I'm using:
NSString *imgPath = #"/var/mobile/Media/DCIM/105APPLE/IMG_5903.JPG";//Hardcoded path just for test, image actually exists on iOS device
self.imgViewContainer.image = [UIImage imageWithContentsOfFile: imgPath];
This code which works on Simulator.
I tested on a real device and I noticed that the UIImageView is empty after execute the above code.
Is there a way to achieve this using a real device?
Due to app sandboxing, your app does not have permission to view the contents of /var/mobile/Media (or really any subdirectory of /var/). Consider the code below:
do {
let fileList = try FileManager.default.contentsOfDirectory(atPath: "/var/mobile/Media/DCIM/")
} catch {
print(error)
}
contentsOfDirectory(atPath:) with throw an error with these details:
Error Domain=NSCocoaErrorDomain Code=257 "The file “DCIM” couldn’t be opened because you don’t have permission to view it." UserInfo={NSFilePath=/var/mobile/Media/DCIM/, NSUserStringVariant=(
Folder
), NSUnderlyingError=0x170045700 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
This example is in Swift, but the equivalent Objective-C code would have the same error.
There is no way around this (unless your are using a jailbroken device running your application as the root user). Use UIImagePickerController to ask the user for an image.

UIActivityViewController not showing PDF option

I know there are many posts on this type of thing. And I believe I have tried all of the suggestions. I have a very simple problem. I have a url to a PDF and I want to be able to "share" this to the adobe pdf reader app. To remove one of the possible issues I took the PDF I was downloading and put it into my bundle so it was local. I am on iOS 8.4. Here is the code I tried:
NSURL * url2 = [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource: # "data" ofType: # "pdf"]];
//Tried with the data in the file
NSData *data2 = [NSData dataWithContentsOfURL:url2];
UIActivityViewController *act=[[UIActivityViewController alloc]initWithActivityItems:#[data2] applicationActivities:nil];
//Tried with just the URL
UIActivityViewController *act=[[UIActivityViewController alloc]initWithActivityItems:#[url2] applicationActivities:nil];
act.popoverPresentationController.barButtonItem = button;
act.popoverPresentationController.sourceView = self.view;
[self presentViewController:act animated:YES completion:nil];
return;
Neither of these show the PDF option. I of course have it installed and have run it once to make sure its registered properly. Both of these I can share to Mail and the actual file is sent fine but the only share options I get are Mail, Copy and Print. I would like to see the other options like Open in iBooks and Open in Adobe Acrobat like I get from safari.
Ideas?

Airdrop error message: "cannot receive all of these items at the same time"

I use the following code to share an image, some text, and a url using UIActivityViewController. Everything works fine except that when the use selects AirDrop, it gets a "cannot receive all of these items at the same time". If I only share the image, then AirDrop works. I need the text and the url for email, Facebook, twitter sharing methods.
Is there a way to keep the text and the URL and make AirDrop only share the image while Facebook, email, twitter methods of sharing continue to use the text and url together with the image that I'm trying to share?
NSString *text = [NSString stringWithFormat:#"I made this image using %# iOS app. Here is the link to download it:", [CloudHelper appName]];
NSURL *url = [NSURL URLWithString:APP_URL];
UIActivityViewController *activityController =
[[UIActivityViewController alloc]
initWithActivityItems:#[text, url, myImage]
applicationActivities:nil];
[self presentViewController:activityController animated:YES completion:nil];
You'd want to create and share three objects that conform to the UIActivityItemSource, where one returns a string, one an image and one a URL. Then when the delegate callback requesting the item is called you check which activity type was selected (Facebook, Twitter, airdrop, etc) and have some return nil if that item doesn't apply.
So in the case of airdrop, only the item source for the image will return a non-nil value. You can take a look at the airdrop sample code to get some examples of how to implement UIActivityItemSource

Can I send UIDocuments by email, as an attachment?

I'm working with Xcode.
In my app I save some UIdocuments at that location
[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
I'm searching for a way to share documents, my first option is by email.
Can I send those documents by email, as an attachment? Can I open then with another device with the same app?
You could do like the following.
Create a MFMailComposeViewController and use - (void)addAttachmentData:(NSData*)attachment mimeType:(NSString*)mimeType fileName:(NSString*)filename method to add your attachment.
For example.
MFMailComposeViewController *mailVC = [[MFMailComposeViewController alloc] init];
[mailVC setSubject:#"Shared documents"];
[mailVC setToRecipients:#[#"sample#example.com"]];
[mailVC setMessageBody:#"Here the docs I want to share" isHTML:NO];
[mailComposer addAttachmentData:pdfData mimeType:#"application/pdf" fileName:#"file.pdf"];
[mailVC setMailComposeDelegate:self];
[self presentViewController:mailVC animated:YES completion:nil];
where pdfData is of type NSData. So, you need to transform your document into a NSData.
From Apple doc.
addAttachmentData:mimeType:fileName:
This method attaches the specified data after the message body but
before the user’s signature. You may attach multiple files (using
different file names) but must do so prior to displaying the mail
composition interface. Do not call this method after presenting the
interface to the user.
About the second part of your question. Could you explain what type of document do you need to display?
In the meantime, take a look at Adding "Open In..." option to iOS app.
To send any attachment you need to get the contents into an NSData object. If the document is on disk then this is simple. You just need the path or file URL to the document. Then you can create the NSData object using the path or URL.
If the receiver of the email has the same app and the app is setup to appear in the "Open In" menu for documents of this type, then the user can open the app from the attachment. Your app then just needs to know what to do when it is asked to open a file of this type. There are plenty of existing documentation and questions here on SO that describe how to register an app to open certain file types.

Resources