I need to share a .zip file via email / iTunes / other ways (such as message, AirDrop). I can already send a zipped file via email and iTunes, but when I try to send the zip file using UIActivityViewController, it doesn't show any file.
This is the code:
-(void) sendAllToApp {
NSString *dpath=NSTemporaryDirectory();
NSString *zipfile=[dpath stringByAppendingPathComponent:[NSString stringWithFormat:#"All_Reports_of_Project_%#.zip",project.displayName]];
[SSZipArchive createZipFileAtPath:zipfile withFilesAtPaths:zippedURL];//zipfile is the path that I store zip file data,zippedURL is the paths of files t.
NSData *zipData=[[NSFileManager defaultManager]contentsAtPath:zipFile];
NSURL *url =[NSURL fileURLWithPath:zipfile];
[zipData writeToURL:url atomically:NO];
if(zipData != nil) {
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[url] applicationActivities:nil];
activityViewController.excludedActivityTypes = #[UIActivityTypePrint];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
activityViewController.popoverPresentationController.sourceView = self.navigationController.view;
activityViewController.popoverPresentationController.sourceRect = CGRectMake(self.navigationController.view.bounds.size.width/2, self.navigationController.view.bounds.size.height/4, 0, 0);
}
[self.navigationController presentViewController:activityViewController animated:true completion:nil];
activityViewController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
// When completed flag is YES, user performed specific activity
};
[self clearTmpDirectory];
}
else {
[self showError];
[self clearTmpDirectory];
}
}
I set items to #[url] and #[zipData] both.
When using URL, I can't use AirDrop.
When using zip data, I get a .data file in my MacBook. If I change the .data file to .zip, it will become the correct file that I want to share.
So how can I share the .zip file correctly?
We had the same issue. The only fix that did work for us was to convert the .zip to a .tar file, which can be shared using a NSURL containing its path.
Related
I am using UIActivityViewController to share my generated image, it worked fine for certain apps like Whatsapp or sharing via Email, but i also wanted to share it using Messages app. I've tried several ways to do it but i can't display Messages app on it.
Here's my code :
UIImage *receiptStage3 = [CreateReceiptImage putLogo:nil putLabel:TRANSACTION_RECEIPT inImage:receiptStage2];
NSData *imageData = UIImageJPEGRepresentation(receiptStage3,0.5);
// create url
NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyyMMddHHmmss"];
NSString *fileName = [NSString stringWithFormat:#"%#%#%#", #"FormatHere-", [dateFormatter stringFromDate:[NSDate date]],#".jpg"];
NSURL *url = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingString:fileName]];
NSData *data = imageData;
// write data
[data writeToURL:url atomically:NO];
NSArray *activityItems = #[url];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
activityVC.excludedActivityTypes = #[UIActivityTypePostToTencentWeibo, UIActivityTypePostToVimeo, UIActivityTypePostToWeibo, UIActivityTypePostToFlickr, UIActivityTypePostToTwitter, UIActivityTypePostToFacebook, UIActivityTypePrint, UIActivityTypeAssignToContact, UIActivityTypeOpenInIBooks, UIActivityTypeAirDrop,UIActivityTypeSaveToCameraRoll,UIActivityTypeAddToReadingList];
[activityVC setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
//Delete file
NSError *errorBlock;
if([[NSFileManager defaultManager] removeItemAtURL:url error:&errorBlock] == NO) {
NSLog(#"error deleting file %#",#"error");
return;
}
}];
[self presentViewController:activityVC animated:YES completion:nil];
As i said before i've tried several ways like putting NSUrl #[url] and UIImage *receiptStage3 directly to initWithActivityItems. I've also tried to remove excludedActivityTypes but the Message option wont show. Am i missing something ? or are there another ways to do this ? Thanks before
Your code is completely fine, works to me.
First of all you Messages app may be missing if you have iMessage disabled in your settings. Go to Settings->Messages and make sure it's on:
Also you may not see it in the default items, check out hidden ones:
In my app, I want to implement the ability to export the multiple pdf files.
For now, I can export an only pdf file using the code below:
// get local path url
NSURL *url = [self getFileURLWithIndexPath:indexPath];
if(url) {
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[url path]];
if(!fileExists) {
NSLog(#"%#", [url path]);
}
self.docController = [UIDocumentInteractionController interactionControllerWithURL:url];
[self.docController setDelegate:self];
BOOL canOpenFile = [self.docController presentOpenInMenuFromRect:self.view.frame inView:self.view animated:YES];
if(!canOpenFile) {
// No reader PDF
}
}
The url is the local URL path.
This method will popup where I can choose iBooks to export.
But I have no idea how to export multiple files, can anyone help me...?
Thank!
You can use UIActivityViewController to export multiple files and can open in UIDocumentationInteractionController, it provides in-app support for managing user interactions with files in the local system.
NSArray *dataItems = #[pdf1, pdf2, pdf3];
UIActivityViewController *activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:dataItems
applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:^{
}];
I've got a (for me) big problem.
I want to send a vcf-file with airdrop from my own app to another iOS device. I've got a NSData object, which i should convert to a vcf file, and this I should send with airdrop to another IOS device.
The NSData object works fine, i can send a vcc file with email, but with airdrop I left my limit.
I tried everything i found here in the forum and on developer.apple.com. But nothing works, I think the reason is, that i have no idea how too start the fix the problem.
Has anybody any idea how i can realize it?
THANKS
I believe this is roughly what you are looking for:
NSString *contactName = nil; // name of person in vcard
NSData *vcfData = nil; // vcard data
NSURL *fileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.vcf", contactName]]];
NSError *writeError;
if ([vcfData writeToURL:fileURL options:NSDataWritingAtomic error:&writeError]) {
NSArray *activityItems = #[fileURL];
UIActivityViewController *avc = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
[self presentViewController:avc animated:YES completion:nil];
} else {
// failed, handle errors
}
If you still want to support providing NSData to some of the activities you will have to create some objects that conforms to UIActivityItemSource protocol and have some of them return nil where appropriate (see this SO for more details on that). You might find the AirDrop sample code project from Apple helpful too.
I am having some trouble in sharing videos with airdrop. So, i am using the AssetLibrary like this :
else if (conformsToVideo) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Asset Loaded" message:#"Video One Loaded"
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
self.mediaAsset = [AVAsset assetWithURL:[info objectForKey:UIImagePickerControllerMediaURL]];
UIActivityViewController * controller = [[UIActivityViewController alloc] initWithActivityItems:#[self.mediaAsset] applicationActivities:nil];
[self presentViewController:controller animated:YES completion:nil];
}
Maybe this is just not the way to do it, I don't know and I didn't find any tutorial about it so if you have one, I will gladly take it.
Now my problem is that when i select a video everything works fine until the UIActivityViewController pops out , i don't have any error but I can't use airdrop (nor any other service BTW) the only thing I can do is press the Cancel button of the UIAVController.
I am using iOS 8.3.
Thanks for your help
Ok, eventually I found an answer, maybe not the best but I put it there in case it helps someone cause I didn't find much on sharing video with airdrop :
NSURL * path = [info objectForKey:UIImagePickerControllerReferenceURL];
BOOL conformsToVideo = (UTTypeConformsTo((__bridge_retained CFStringRef) mediaType, kUTTypeAudiovisualContent));
if (conformsToVideo) {
[self.library assetForURL:path
resultBlock:^(ALAsset *asset) {
ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
NSString* outputDirectory = [NSString stringWithFormat:#"%#", NSTemporaryDirectory()];
NSString* pathToCopy = [outputDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#", assetRepresentation.filename]];
NSUInteger size = (NSUInteger)assetRepresentation.size;
NSMutableData* data = [NSMutableData dataWithLength:size];
NSUInteger bytesRead = [assetRepresentation getBytes:data.mutableBytes fromOffset:0 length:size error:nil];
NSURL * url = nil;
if ([data writeToFile:pathToCopy atomically:YES])
{
NSLog(#"Ok");
url = [NSURL fileURLWithPath:pathToCopy];
UIActivityViewController * controller = [[UIActivityViewController alloc] initWithActivityItems:#[url] applicationActivities:nil];
[self presentViewController:controller animated:YES completion:nil];
}
} failureBlock:^(NSError *error) {
NSLog(#"Failure to use the ALAsset");
}
];
}
I found the solution using this question : Share a video from asset library with AirDrop fails
I am merely adding the previous steps to the code given there, hope it can be useful.
I am sharing an audio recording via the UIActivityViewController. When the audio file shares via email or iMessage, it shows the underlying name of the audio file without any apparent way of changing it.
NSArray *activityItems = [NSArray arrayWithObjects:self.audioPlayer.url, nil];
UIActivityViewController *avc = [[UIActivityViewController alloc]
initWithActivityItems:activityItems
applicationActivities:nil];
[self presentViewController:avc
animated:YES completion:nil];
If I don't use the UIActivityViewController and just use MFMessageComposeViewController directly, than I can use
[composer addAttachmentURL:self.audioPlayer.url withAlternateFilename:#"Piano Song.m4a"];
Is it possible to have an alternate file name with the UIActivityViewController?
You can create a hard link to the file (so that you don't have to copy the actual file) with any name you want in the temporary directory and pass it to the UIActivityViewController instead of the file.
- (NSURL *)createLinkToFileAtURL:(NSURL *)fileURL withName:(NSString *)fileName {
NSFileManager *fileManager = [NSFileManager defaultManager];
// create a path in the temp directory with the fileName
NSURL *tempDirectoryURL = [[NSFileManager defaultManager] temporaryDirectory];
NSURL *linkURL = [tempDirectoryURL URLByAppendingPathComponent:fileName];
// if the link already exists, delete it
if ([fileManager fileExistsAtPath:linkURL.path]) {
NSError *error;
[fileManager removeItemAtURL:linkURL error:&error];
if (error) {
// handle the error
}
}
// create a link to the file
NSError *error;
BOOL flag = [fileManager linkItemAtURL:fileURL toURL:linkURL error:&error];
if (!flag || error) {
// handle the error
}
return linkURL;
}
Use it like this:
NSURL *fileURL = ...;
NSString *desiredName = ...;
NSURL *linkURL = [self createLinkToFileAtURL:fileURL withName:desiredName];
UIActivityViewController *viewController = [[UIActivityViewController alloc] initWithActivityItems:#[linkURL] applicationActivities:nil];
[self presentViewController:viewController animated:YES completion:nil];
Hope this helps! Good luck!
Very nice, timaktimak. Thank you.
Here is the same in Swift:
private func createLinkToFile(atURL fileURL: URL, withName fileName: String) -> URL? {
let fileManager = FileManager.default // the default file maneger
let tempDirectoryURL = fileManager.temporaryDirectory // get the temp directory
let linkURL = tempDirectoryURL.appendingPathComponent(fileName) // and append the new file name
do { // try the operations
if fileManager.fileExists(atPath: linkURL.path) { // there is already a hard link with that name
try fileManager.removeItem(at: linkURL) // get rid of it
}
try fileManager.linkItem(at: fileURL, to: linkURL) // create the hard link
return linkURL // and return it
} catch let error as NSError { // something wrong
print("\(error)") // debug print out
return nil // and signal to caller
}
}
No, not possible. Could you not just rename the file before sharing it?