I need to have Facebook and WhatsApp as sharing options for my image. I've already implemented UIActivityViewController, where i can share via Facebook and UIDocumentInteractionController where i can share via WhatsApp. I don't know how to merge these things.
UIActivityViewController:
UIActivityViewController *activityViewContoller = [[UIActivityViewController alloc]
initWithActivityItems:#[#"Test", image] applicationActivities:nil];
[self presentViewController:activityViewContoller animated:YES completion:nil];
UIDocumentInteractionController:
NSString *savePath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/whatsAppTmp.wai"];
[UIImageJPEGRepresentation(image, 1.0) writeToFile:savePath atomically:YES];
_documentInteractionController = [UIDocumentInteractionController
interactionControllerWithURL:[NSURL fileURLWithPath:savePath]];
_documentInteractionController.UTI = #"net.whatsapp.image";
_documentInteractionController.delegate = self;
[_documentInteractionController presentOpenInMenuFromRect:CGRectZero
inView:self.view animated:YES];
I want to have both of them in one popover, however I have no idea how to achieve it. Any tip please?
I've checked out StackOverFlow question 1, but it doesn't help me at all. My file is .wai (for WhatsApp) so when i try to send it via FB file is unable to open. Also it shows all options, while i want only 2(FB+WhatsApp) to be visible. Following the StackOverFlow question 2 I can show only FB (working one, because i set normal image) but can't add WhatsApp (no .wai file, i don't know what to do with UTI). Is there any way to solve this issue?
To change type of file:
- (void)share {
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/tmptmpimg.jpg"];
[UIImageJPEGRepresentation(_img, 1.0) writeToFile:path atomically:YES];
_documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:path]];
_documentInteractionController.delegate = self;
[_documentInteractionController presentOptionsMenuFromRect:CGRectZero inView:self.view animated:YES];
}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application {
if ([self isWhatsApplication:application]) {
NSString *savePath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/tmptmpimg.wai"];
[UIImageJPEGRepresentation(_img, 1.0) writeToFile:savePath atomically:YES];
controller.URL = [NSURL fileURLWithPath:savePath];
controller.UTI = #"net.whatsapp.image";
}
}
- (BOOL)isWhatsApplication:(NSString *)application {
if ([application rangeOfString:#"whats"].location == NSNotFound) { // unfortunately, no other way...
return NO;
} else {
return YES;
}
}
This way we can use all options- Facebook, Twitter and custom WhatsApp.
The problem with showing only selected options is still not solved, but it's the minor one.
To exclude non-desired sharing options (the second part of your question), assuming your UIActivityViewController object is called activityController, set the excludedActivityTypes property, like so:
activityController.excludedActivityTypes = #[UIActivityTypeAssignToContact,
UIActivityTypePrint,
UIActivityTypeAddToReadingList,
UIActivityTypeAirDrop];
Related
It successfully redirects to the Whatsapp app.There is no preview frame and when tapped Send, an error messages pops up "This video could not be sent. Please choose a different video.
Here is my code.
- (void)shareVideo {
NSLog(#"[WhatsAppShare] sharing video");
//NSString *nativePath = [[NSString alloc] initWithCString:path encoding:NSASCIIStringEncoding];
NSString *nativePath=[[NSBundle mainBundle] pathForResource:#"video" ofType:#"mp4"];
// Save video to path in documents directory
NSString *savePath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/whatsAppTmp.wam"];
if([[NSFileManager defaultManager] fileExistsAtPath:savePath]){
if([[NSFileManager defaultManager] removeItemAtPath:savePath error:nil]){
[self shareVideoAtNativePath:nativePath SavePath:savePath];
}
} else {
[self shareVideoAtNativePath:nativePath SavePath:savePath];
}}
- (void)shareVideoAtNativePath:(NSString*)nativePath SavePath:(NSString*)savePath{
NSError*error;
BOOL isSuccess=[[NSFileManager defaultManager] copyItemAtPath:nativePath toPath:savePath error:&error];
if(isSuccess){
// Create interaction controller
self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:savePath]];
self.documentInteractionController.UTI = #"net.whatsapp.movie";
self.documentInteractionController.delegate = self;
[self.documentInteractionController presentOpenInMenuFromRect:CGRectMake(0, 0, 1, 1)
inView:[self view]
animated:YES];
} else{
NSLog(#"error %#", error);
}
}
We have observed the exact same problem. Everything was working until a recent update of WhatsApp. This is probably a bug on WhatsApp side.
Here is a workaround for this problem:
Do not use a wam file, use the mp4 file directly. So in your case, just call
[self shareVideoAtNativePath:nativePath SavePath:nativePath];
Change the UTI to public Mpeg4:
self.documentInteractionController.UTI = #"public.mpeg-4";
This seems to have solved our issue. However, there is a drawback that, the share dialog now contains many other apps/services that can open mp4 files.
We've faced the exact same issue.
The official .wam format brings up only WhatsApp in the share dialog, but fails to forward the video.
Using .m4v format is working for us. A few more options are displayed along with WhatsApp (Open in WhatsApp is the option we want). We are displaying an alert saying "Please select Whatsapp on the next screen" before sending user to the share dialog.
File format: m4v
UTI: net.whatsapp.movie
Please refer to the working code below:
UIDocumentInteractionController *documentInteractionController;
-----
-----
- (void)shareVideoViaWhatsApp:(NSURL*)url{
// Creating temp video to share specifically on whatsapp.
NSString *cachesFolder = [NSTemporaryDirectory() stringByAppendingPathComponent: [NSString stringWithFormat:#"video.m4v"]];
NSURL *file = [NSURL fileURLWithPath:cachesFolder];
[[NSData dataWithContentsOfURL:url] writeToURL:file options:NSDataWritingAtomic error:nil];
documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL: file ];
documentInteractionController.UTI = #"net.whatsapp.movie";
documentInteractionController.delegate = self;
[documentInteractionController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
}
// In code Use share GIF and Video for WhatsApp....
NSString *savePath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/whatsAppTmp.wam"];
savePath = [[NSBundle mainBundle] pathForResource:#"Movie" ofType:#"m4v"];
_documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:_videourl];
_documentInteractionController.UTI = #"net.whatsapp.movie";
_documentInteractionController.delegate = (id)self;
[_documentInteractionController presentOpenInMenuFromRect:CGRectMake(0, 0, 0, 0) inView:self.view animated: YES];
I am trying to implement share multiple file to Facebook , mail ,google driver and whatsapp.
I can share one file via UIDocumentInteractionController like the following code:
NSString *filePath = [NSString stringWithFormat:#"%#/%#", directory, [fileList objectAtIndex:selectedIndexPath.row]] ;
url = [NSURL fileURLWithPath: filePath] ;
documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:url];
[documentInteractionController setDelegate:self];
documentInteractionController.UTI = #"net.whatsapp.image";
[documentInteractionController presentOptionsMenuFromRect:CGRectZero inView:self.view animated:YES];
How to share multiple file via UIDocumentInteractionController without using UIActivityViewController ?
If use NSMutableArray , and add multiple object of url. How to set NSMutableArray to UIDocumentInteractionController ?
Thanks in advance.
To share multiple files you can use UIActivityViewController.
UIImage *image = [UIImage imageWithCGImage:self.imgView.image.CGImage];
NSArray* dataToShare = #[image, image2, image3]; // Any data you want to share.
UIActivityViewController* activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:dataToShare
applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:nil];
This might help you.
I want to share an image via whatsapp.
I'm using UIDocumentInteractionController with the following code.
Can I skip the menu that is opened (and the user selects whatsapp) and just act as if he selected the first option?
if ([[UIApplication sharedApplication] canOpenURL: [NSURL URLWithString:#"whatsapp://app"]])
{
NSString *savePath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/whatsAppTmp.wai"];
[UIImageJPEGRepresentation(image, 1.0) writeToFile:savePath atomically:YES];
_documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:savePath]];
_documentInteractionController.UTI = #"net.whatsapp.image";
_documentInteractionController.delegate = self;
[_documentInteractionController presentOpenInMenuFromRect:CGRectZero inView:self.view animated: YES];
}
WhatsApp was updated with iOS 8 SDK with ShareKit extension.
So now sharing to WhatsApp is 'default' in UIActivityController and there is no need to implement UIDocumentInteractionController to share the image.
Thanks to a couple other posts here , I've successfully be able to use the Instagram iPhone hooks to open Instagram and present it with a photo successfully from my application.
(I've made my ViewController class a delegate of UIDocumentInteractionController, and alloc/init'ed a nonatomic/retain property of UIDocumentInteractionController...
However, the key that I put into my NSDictionary that I place in the document controller annotation property will not seem to carry over to Instagram - the caption area is just empty.
How do I deal with this?
Here is my method:
- (void) uploadImageToInstagram:(UIImage *)imageToUpload {
NSLog(#"postToInstagramInBackground");
NSURL *instagramURL = [NSURL URLWithString:#"instagram://app"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
// Upscale to 612x612
imageToUpload = [self upscaleImage:imageToUpload];
// Get JPG + IGO Format
NSString *savePath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/generate.igo"];
[UIImageJPEGRepresentation(imageToUpload, 1.0) writeToFile:savePath atomically:YES];
// Paths
NSURL *imageURL = [NSURL fileURLWithPath:savePath];
NSURL *igImageHookFile = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:#"file://%#",savePath]];
// Setup DocController
self.docController.UTI = #"com.instagram.photo";
self.docController = [self setupControllerWithURL:igImageHookFile usingDelegate:self];
self.docController.annotation = [NSDictionary dictionaryWithObject:#"MyApp" forKey:self.caption.text];
[self.docController setURL:imageURL];
[self.docController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES ];
}
else {
NSLog(#"Instagram not installed in this device!\nTo share image please install Instagram.");
}
}
There are a few methods that are called here that I haven't included, one that upscales the image to make sure its 612x612, and one setups the file url for the document controller.
Proper syntax should be
self.docController.annotation = [NSDictionary dictionaryWithObject:self.caption.text forKey:#"InstagramCaption"];
I am new to UIActivityViewController and perhaps I am missing a basic understanding. What I am trying to do is attached a csv, xml and vcard file to activity controller and show dropbox, google drive etc options. I have downloaded and installed dropbox, google drive etc apps on my iPhone.
Now when I launch UIActivityViewController all I see are default message and email app in my acitivity controller. How can I have other apps show up on their too? Do I need to install each and every apps individual SDKs and somehow incorporate them in my app?
This is what I wold like to see
but this is what I see instead.
Here's the code that I have tried so far
-(IBAction) dropBoxAction
{
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask ,YES);
NSString* documentsPath = [paths objectAtIndex:0];
//CSV
NSMutableString *fileNameStr = [NSMutableString stringWithFormat:#"test_CSV_Backup.csv"];
NSString* csvDataFileStr = [documentsPath stringByAppendingPathComponent:fileNameStr];
NSData *csvData = [NSData dataWithContentsOfFile:csvDataFileStr];
//EXCEL
NSMutableString *fileNameStr2 = [NSMutableString stringWithFormat:#"test_EXCEL_Backup.xml"];
NSString* excelDataFileStr = [documentsPath stringByAppendingPathComponent:fileNameStr2];
NSData *excelData = [NSData dataWithContentsOfFile:excelDataFileStr];
//VCARD
NSMutableString *fileNameStr3 = [NSMutableString stringWithFormat:#"test_VCARD_Backup.vcf"];
NSString* vcardDataFileStr = [documentsPath stringByAppendingPathComponent:fileNameStr3];
NSData *vcardData = [NSData dataWithContentsOfFile:vcardDataFileStr];
//adding them all together
NSMutableArray *sharingItems = [NSMutableArray new];
[sharingItems addObject:csvData];
[sharingItems addObject:excelData];
[sharingItems addObject:vcardData];
UIActivity *activity = [[UIActivity alloc] init];
NSArray *applicationActivities = #[activity];
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:applicationActivities];
[self presentViewController:activityController animated:YES completion:nil];
}
As #rmaddy said, you should use UIDocumentInteractionController to replace UIActivityViewController, just like this:
UIDocumentInteractionController *dc = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:fileNameStr]];
[dc presentOptionsMenuFromRect:self.view.bounds inView:self.view animated:YES];
For anyone interested in future, here's the code all in one place. Do rate it up if this helps.
In your *.h file add this
#interface v1BackupComplete : UIViewController <UIDocumentInteractionControllerDelegate>
{
UIDocumentInteractionController *docController;
}
In your *.m file add this
/************************
* Dropbox ACTION
************************/
-(IBAction) dropBoxAction2
{
NSLog(#"dropBoxAction2 ...");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask ,YES);
NSString* documentsPath = [paths objectAtIndex:0];
NSMutableString *fileNameStr3 = [NSMutableString stringWithFormat:#"test_VCARD_Backup.vcf"];
NSString* vcardDataFileStr = [documentsPath stringByAppendingPathComponent:fileNameStr3];
NSURL *fileURL = [NSURL fileURLWithPath:vcardDataFileStr];
docController = [self setupControllerWithURL:fileURL
usingDelegate:self];
bool didShow = [docController presentOpenInMenuFromRect:self.view.bounds inView:self.view animated:YES];
NSLog(#"didShow %d ...", didShow);
if (!didShow)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"ERROR"
message:#"Sorry. The appropriate apps are not found on this device."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[alert show];
}
}
#pragma mark - UIDocumentInteractionControllerDelegate
- (UIDocumentInteractionController *) setupControllerWithURL:(NSURL *)fileURL
usingDelegate:(id <UIDocumentInteractionControllerDelegate>) interactionDelegate {
UIDocumentInteractionController *interactionController =
[UIDocumentInteractionController interactionControllerWithURL:fileURL];
interactionController.delegate = interactionDelegate;
return interactionController;
}
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
return self;
}
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller
{
return self.view;
}
- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller
{
return self.view.frame;
}
UIActivityViewController only shows standard built-in activities plus any custom activities you pass as applicationActivities.
For what you are doing, you don't want UIActivityViewController. You want a UIDocumentInteractionController. If you just want to display existing apps that can open the file, use one of the presentOpenInMenuFrom... methods.
But note that is to be used for just a single file, not three.
Passing three files makes no sense in this context.
I have used your code here to open with dropbox and only after I have used presentPreview method (bellow) It was worked for me.
The pdf was shown as preview and then on the preview share button click (top right) the dropbox option ("open in dropbox") did the job. As it works in the mail app in the attachment preview.
[interactionController presentPreviewAnimated:YES];
When i tried to open with presentOpenInMenuFromRect it was crashed on selecting "open in dropbox".