Send NSData via Airdrop - ios

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.

Related

How to share PDF file with Evernote in iOS

I want to share PDF file with Evernote in iOS application.
Note: I have found the code of Evernote login from Evernote official website but didn't get any reference of sharing PDF from anywhere.
I have found solution of my above question :
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"pdf-sample" ofType:#"pdf"];
NSData *pdfFileData = [NSData dataWithContentsOfFile:filePath];
ENResource * resource = [[ENResource alloc] initWithData:pdfFileData mimeType:#"application/pdf" filename:#"pdf-sample.pdf"];
ENNote * note = [[ENNote alloc] init];
note.title = #"Costsfirst PDF file";
[note addResource:resource];
[[ENSession sharedSession] uploadNote:note notebook:nil completion:^(ENNoteRef *noteRef, NSError *uploadNoteError) {
NSString * message = nil;
if (noteRef) {
message = #"Pdf uploaded!";
} else {
message = #"Failed to upload.";
}
}];
Above code is working perfectly for me.
If I do understand your question then, to share PDF with Evernote from your iOS app, can be achieved via UIActivityViewController.
try this:
NSData *pdfFileData = [NSData dataWithContentsOfFile:pdfFilePath];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[#"Test", pdfFileData] applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:nil];
--- OR ---
NSString *str = [[NSBundle mainBundle] pathForResource:#"YourPdfFileName" ofType:#"pdf"];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[#"Test", [NSURL fileURLWithPath:str]] applicationActivities:nil];
With the code above, You could scroll over on UIActivityViewController’s share section, and use other custom share extensions like Evernote.
You didn’t have to do a thing. As a user, just click the more button to show the ones you want in the share sheet. As a developer, you don’t have to do anything to your UIActivityViewController to show custom Share and Action Extensions.
Hope this may help you.
Regarding Evernote cloud sdk for iOS:
https://github.com/evernote/evernote-cloud-sdk-ios/blob/master/Getting_Started.md
This document covers getting set up with the Evernote Cloud SDK for iOS, some quick examples, and some discussion of the primary classes.

Sharing images/videos to other apps through UIActivityViewController shows shared items twice in iOS

I'm trying to share some images and videos to other apps(like FB, WhatsApp) using UIActivityViewController. I have sub-classed UIActivityItemProvider, and on calling -(id)item methods, I'm processing the images/videos and saving in documents directory. Then I am returning the file paths as NSURLs. My problem is that I'm not able to find a way to send multiple file URLs at the same time.
Below are the approaches I took to return urls from -(id)item method;
As an NSArray of NSURL objects. DOES NOT WORK. When the target app popup comes, it is empty always.
As a NSDictionary, in which NSURL objects are the values and keys could be anything. PROBLEMATIC: The target app popup shows all items, but TWICE! I experimented with the dictionary a lot, but couldn't find a way to solve this.
Simply returning an NSURL object from -(id)item method works fine for single file. But, I have to share multiple items. Array doesn't work, Dictionary is duplicating shared items.
Can someone please tell me what I'm doing wrong here?
UPDATE 1:
This is how I show the UIActivityViewController.
CustomItemProvider *provider = [[CustomItemProvider alloc] initWithPlaceholderItem:[UIImage imageNamed:#"ios-59.png"]];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[provider] applicationActivities:nil];
activityViewController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError)
{
if(completed)
{
NSLog(#"Activity Completed");
}
else
{
NSLog(#"Activity Cancelled");
}
};
[self presentViewController:activityViewController animated:YES completion:^{}];
The UIActivityItemProvider implementation is as given below; The URLs are valid and there are images/videos at those locations.
#interface CustomItemProvider : UIActivityItemProvider
#end
#implementation CustomItemProvider
- (id)item
{
NSURL *url1 = [NSURL fileURLWithPath:#"file one url"];
NSURL *url2 = [NSURL fileURLWithPath:#"file two url"];
NSURL *url3 = [NSURL fileURLWithPath:#"file three url"];
return #{#"item1":url1, #"item2":url2, #"item3":url3}; //As NSDictionary. This causes 6 items to be shared; all files twice.
//return #[url1, url2, url3]; //As NSArray
}
#end
UPDATE 2:
The linked question is different.
I don't want to send the files directly to the UIActivityViewController as parameter to initWithActivityItems:. The reason is that there could be multiple video files, which will cause memory warning and a crash. Also, I will be manipulating the files before sending it to target app(in the -(id)item method, which I have not shown here), hence I need UIActivityItemProvider to process the files in background.
Share image with other apps:
Swift 3 code-
let image = UIImage(named: "yourimage")
let objectsToShare = [image]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
present(activityVC, animated: true, completion: nil)
UPDATE:
This approach was completely wrong and will lead to unexpected results in some scenarios. Sorry if this answer mislead anyone.
The correct approach is to create one UIActivityItemProvider object for each item to be shared. And return the item to be shared from the corresponding provider object. Sorry that I couldn't update this answer before.
Good day everyone!
Okay, finally I got it. This has been driving me crazy and I couldn't find any proper documentation/answers anywhere.
The solution was to return a dictionary back with NSItemProvider objects as values. The keys for the same could be anything that is not same as other keys.
If anyone is after the same problem, find the solution below;
#interface CustomItemProvider : UIActivityItemProvider
{
NSCondition *_condition;
NSArray *_filesToShare;
}
#end
#implementation CustomItemProvider
- (id)item
{
_fetchInProgress = YES;
//Here start fetching/processing videos/photos in ANOTHER THREAD. Once the fetching/processing is complete, set the value of _fetchInProgress to NO.
//If you want to show progress, display progress view in MAIN THREAD here.
[_condition lock];
while(_fetchInProgress)
{
[_condition wait];
}
[_condition unlock];
//Here I am assuming that the files are processed and are saved to documents/cache directory and their file-paths are in _filesToShare array.
NSMutableDictionary *itemsDict = [NSMutableDictionary dictionaryWithCapacity:[_filesToShare count]];
for (int i = 0; i < [_filesToShare count]; i++)
{
NSURL *url = [NSURL fileURLWithPath:[_filesToShare objectAtIndex:i]];
NSItemProvider *item = [[NSItemProvider alloc] initWithContentsOfURL:url];
[itemsDict setObject:item forKey:#(i)];
}
return itemsDict;
}
#end
Cheers!!!

iOS Share GIF (animated image) not Working

It's been almost 2 days that i'm looking to find a solution to my problem but i wasn't successful , i want to share GIF (animated image) on Facebook, Twitter, Email, WhatsApp , using "UIActivityViewController".
This is my code :
NSURL *imagePath = [NSURL URLWithString:#"http://sth.gif"];
NSData *animatedGif = [NSData dataWithContentsOfURL:imagePath];
NSArray *sharingItems = [NSArray arrayWithObjects: animatedGif,stringToShare, nil];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
When i share in Email its animated and its working perfect , but in Twitter , Facebook , whatsApp Gifs are not animated and its like an image ...
I already read all Stack-overflow questions about the same problem Like this or this or this but its not working for me.
So far base on days research found out that :
TWITTER : For share a GIF on twitter had to use twitter API and create a multipart request to achieve the goal and its working very well.
FACEBOOK : I did share some GIF on Facebook using FACEBOOKSHAREKIT , but i don't know why sometimes Gifs are animated, sometimes not.
INSTAGRAM : To share gif on Instagram had to convert GIFS to MP4 (or any other video formats accepted by Instagram) then save it into camera roll then share it , It is little twisted but its working very well.
WHATSAPP : It not supporting GIF at all. READ THE UPDATE
To do all of this i couldn't use "UIActivityViewController" , so decided to create a custom share page. if anybody know something to add here , to help me and others please tell me (especially about Facebook).
Thanks in advance
UPDATE
WHATSAPP : Thanks to #AmmarShahid, as he mentioned in comments, Whatsapp now supports gif.
Encountered the similar problem and Googled a lot but still not a perfect solution, the best I came up is here:
Use UIActivityItemProvider and extend - (id)item {} for different UIActivityType:
Twitter: The default UIActivityViewController Twitter share doesn't support it yet which it will "scale down" it as a still JPG. However somehow it works for GIF less than 100kb (tested in iOS 9) and I don't know why. Therefore, I have to use SLRequest to upload the GIF as taught in here. When the SLRequest is done and return, dismiss the UIActivityViewController. The downside of that is no preview share sheet and users cannot type their own message anymore.
Facebook: It's actually much easier! Just upload the GIF to Giphy, then provide the Giphy URL to UIActivityViewController instead of the file contents, Facebook will recognize it and show the animated GIF
- (id)item
{
if ([self.activityType isEqualToString:UIActivityTypePostToFacebook]) {
// Upload to Giphy
...
return [NSURL URLWithString:giphyURL];
}
if ([self.activityType isEqualToString:UIActivityTypePostToTwitter]) {
// Use SLRequest to share instead
...
// Dismiss the UIActivityViewController (I am using Unity)
[UnityGetGLViewController() dismissViewControllerAnimated:NO completion: NULL];
return nil;
}
}
full code is in my GitHub, I am actually a iOS newb so some experts please correct me and the code if possible
// Share GIF File: WhatsApp
NSURL *imageUrl =[self.ImageArray objectAtIndex:currentPhotoIndex];
NSString *path=imageUrl.absoluteString;
NSArray *strings = [path componentsSeparatedByString:#"/"];
NSString *mygif=[strings objectAtIndex:strings.count-1];
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *dataPath = [documentsPath stringByAppendingPathComponent:#"/MrHRamani"];
NSString *filePath = [dataPath stringByAppendingPathComponent:mygif];
NSURL *urll=[NSURL fileURLWithPath:filePath];
NSLog(#"imag %#",imageUrl);
self.documentationInteractionController.delegate = self;
self.documentationInteractionController.UTI = #"net.whatsapp.image";
self.documentationInteractionController = [self setupControllerWithURL:urll usingDelegate:self];
[self.documentationInteractionController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];

Why my message is shared twice in viber, I have used UIActivityViewController

I have used UIActivityViewController for sharing my message in Facebook, Twitter, Viber etc....It seems the message is send twice in Viber but for others are ok. Can u please help me?? I have used the code given below...
-(void)shareContent {
NSString * message;
NSArray * itemsArray = [NSArray new] ;
if ([shareFlag isEqualToString:#"Friend"]) {
message = #"Hi, I am using Amar Sticker, an amazing app to download & share cool Bangla Stickers. Click here and get it for FREE: http://goo.gl/qK7HRw";
NSURL *appLink = [NSURL URLWithString:#"http://goo.gl/qK7HRw"];
itemsArray = #[message, appLink];
shareFlag = #"";
}
UIActivityViewController * avc = [[UIActivityViewController alloc] initWithActivityItems:itemsArray applicationActivities:nil];
[avc setExcludedActivityTypes:#[UIActivityTypeAssignToContact, UIActivityTypeCopyToPasteboard,UIActivityTypeSaveToCameraRoll]];
[avc setCompletionHandler:^(NSString *activityType, BOOL completed) {
}];
[self presentViewController:avc animated:YES completion:nil];
}
After many searching and doing in several way I see that it only happens when I share an array, it can not handle the shared object of the array properly, maybe its a bug of viber. When I post only one string or url it can send properly. I have tested using 2,3,4 items arrry and only one single string/url etc.

Want to paste gif into mail window using UIPasteBoard

I wanted to show a gif so what i did was that i split my gif and showed it in a animation for UIImageView using this link.
http://iphonenativeapp.blogspot.com/2011/03/how-to-show-animation-in-iphoneipad-app.html
Now, i want to make the user copy that gif and paste it in the mail app.
If i used the array which contained all the split images of gif then 4-5 images get pasted in the mail app.
Please help me paste the gif. Thanks!
Gonna copy/paste my own answer from a similar question.
NSString *gifPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:#"volleyball.gif"];
NSData *gifData = [[NSData alloc] initWithContentsOfFile:gifPath];
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
[pasteboard setData:gifData forPasteboardType:#"com.compuserve.gif"];
[gifData release];
Edit just noticed you asked these 2 similar questions yourself.
Although you can use HTML based email -- for example:
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
NSString *emailBody = #"<p><b>Hello World</b></p>";
[picker setMessageBody:emailBody isHTML:YES];
You can't insert inline images as you would typically in HTML. Inline images in HTML email use separate MIME parts that are referenced via a content-id element from the body of the message. MFMailComposeViewController doesn't give you control over the MIME structure of the message and thus doesn't let you add inline referenced content parts.
Embedding image data into <img> tags as base64 will sometimes work -- it depends on the email client and browser used to render it -- but it's not broadly portable.
FWIW, animated gifs appear to work with email in the new share sheets in iOS 6, which would automatically populate the gif in an email if the user selects mail:
NSString *gifPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:#"volleyball.gif"];
NSData *gifData = [[NSData alloc] initWithContentsOfFile:gifPath];
NSArray *activityItems = [NSArray arrayWithObjects:#"Here is an awesome body for the email.",gifData,nil];
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
activityController.completionHandler = ^(NSString *activityType, BOOL completed){
// item was shared!
// you can check if it was email (or another type, like facebook or twitter) in the *activityType.
// completed is YES if they actually shared it, if they canceled, completed will be NO.
};
[navigationController presentViewController:activityController animated:YES completion:nil];
As iOS does not support the animated GIF format, I don't think it is possible to copy/paste the gif in the mail app. However, you can try attaching the gif file (not the split images) & composing a new email using MFMailComposeViewController. If you open the attachment on a non-iOS device, you should be able to see the animated GIF.
HTH,
Akshay

Resources