4

I'm using uiactivityviewcontroller for showing sharing option. Everything working except when user selects the Gmail sharing option. If user chooses email then it shows the content properly. But if i choose gmail then nothing is displayed in the body text.

Here is the code:

 NSString *str = [NSString stringWithFormat:@"%@",@"Check the application"];
 NSArray* dataToShare = @[str];  // ...or whatever pieces of data you want to share.

UIActivityViewController* activityViewController = [[UIActivityViewController alloc] initWithActivityItems:dataToShare applicationActivities:nil];
[activityViewController setValue:@"Check it out" forKey:@"subject"];

if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
    activityViewController.popoverPresentationController.sourceView = self.view;
    activityViewController.popoverPresentationController.sourceRect = CGRectMake(0,self.view.frame.size.height, self.view.frame.size.width, 400);

}

[self presentViewController:activityViewController animated:YES completion:nil];

[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed) {
    if(completed){

    }
}];
}

- (NSString *)activityViewController:(UIActivityViewController *)activityViewController subjectForActivityType:(NSString *)activityType{
    return @"Check it out";
}
Dima
  • 23,484
  • 6
  • 56
  • 83
Parul Garg
  • 355
  • 3
  • 14
  • extremely frustrating. super irrational behavior from gmail app (e.g. try just an NSURL, or an NSString and an NSURL). and creating a gmail uiactivity is not ideal. – st.derrick Mar 17 '15 at 20:51
  • 1
    without subclassing, the best you can do is send exactly one NSURL and exactly one NSString. the NSString will be *both* the email subject and beginning of the body, and the NSURL will be the end of the email body. Annoying but workable. – st.derrick Mar 17 '15 at 20:58

3 Answers3

2

You can use the URL scheme Gmail to create a subclass of UIActivity:

The code below was extracted this answer: https://stackoverflow.com/a/12766330/3726577

//ActivityViewCustomActivity.h
@interface ActivityViewCustomActivity : UIActivity

@end

//ActivityViewCustomActivity.m
@implementation ActivityViewCustomActivity

- (NSString *)activityType {
    return @"googlegmail";
}

- (NSString *)activityTitle {
    return @"Gmail";
}

- (UIImage *)activityImage {
    // Note: These images need to have a transparent background and I recommend these sizes:
    // iPadShare@2x should be 126 px, iPadShare should be 53 px, iPhoneShare@2x should be 100
    // px, and iPhoneShare should be 50 px. I found these sizes to work for what I was making.

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
    {
        return [UIImage imageNamed:@"iPadShare.png"];
    }
    else
    {
        return [UIImage imageNamed:@"iPhoneShare.png"];
    }
}

- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems {
    NSLog(@"%s", __FUNCTION__);
    return YES;
}

- (void)prepareWithActivityItems:(NSArray *)activityItems {
    NSLog(@"%s",__FUNCTION__);
}

- (UIViewController *)activityViewController {
    NSLog(@"%s",__FUNCTION__);
    return nil;
}

- (void)performActivity {
    NSString *email = @"googlegmail:///co?subject=Check it out&body=Check the application";
    email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];

    [self activityDidFinish:YES];
}

@implementation ViewController2

- (void)viewDidLoad{
    [super viewDidLoad];

    NSString *textItem = @"Check the application";

    ActivityViewCustomActivity * ca = [ActivityViewCustomActivity new];

    UIActivityViewController *activityVC =
    [[UIActivityViewController alloc] initWithActivityItems:@[textItem] applicationActivities:[NSArray arrayWithObject:ca]];

    activityVC.excludedActivityTypes = @[UIActivityTypePostToWeibo, UIActivityTypeAssignToContact, UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeSaveToCameraRoll];
    [activityVC setValue:@"Check it out" forKey:@"subject"];

    activityVC.completionHandler = ^(NSString *activityType, BOOL completed)
    {
        NSLog(@" activityType: %@", activityType);
        NSLog(@" completed: %i", completed);
    };

    [self presentViewController:activityVC animated:YES completion:nil];
}

See more: http://www.macstories.net/links/gmail-for-ios-url-scheme/

Community
  • 1
  • 1
  • Solution you provided is not working. The error printed in log is "plugin com.google.Gmail.ShareExtension invalidated" – Parul Garg Mar 13 '15 at 08:46
  • Sorry, I do not know this error. [Here](https://drive.google.com/file/d/0Bw9ojGTiAJchUFFMVWtJOEo1S28/view?usp=sharing) is the link of the sample code. **OBS**: You need the [Gmail](https://itunes.apple.com/br/app/gmail-o-e-mail-do-google/id422689480?mt=8) app installed – Rondinelli Morais Mar 13 '15 at 15:01
  • Thanks for the solution you provided works. But in my case the issue was something else I was passing the URL as NSString which working for all other activities except the Gmail. Now resolved this. Thanks for your help. – Parul Garg Mar 16 '15 at 07:00
  • @ParulGarg so how did you solve the issue? Even I'm facing the same issue with Gmail. Im passing the URL as 'string' – Ankit Jain Apr 28 '15 at 13:03
  • @AnkitJain Try using following code: NSURL *url = [NSURL URLWithString:@"pass url here"]; NSString *str = "share text"; NSArray* dataToShare = @[str,url]; – Parul Garg Apr 30 '15 at 16:49
0

Looks like there is a bug in Gmail Share extension. Please check if your URL has &, passing & character makes message subject and body empty. You can use & instead.

PS: I didn't check for other special characters.

sanjana
  • 3,034
  • 2
  • 25
  • 31
0

It's a bit tricky in Swift 3 and iOS 9+.

First, you need to add googlegmail to LSApplicationQueriesSchemes in Info.plist

Second, here's how my UIActivity subclass looks like:

It's a bit tricky in Swift 3 and iOS 9+.

First, you need to add googlegmail to LSApplicationQueriesSchemes in Info.plist

Second, here's how my UIActivity subclass looks like:

final class GmailNewEmailShareActivity: UIActivity {

    private let urlScheme = "googlegmail:"
    private var activityItems: [Any]? = nil

    override class var activityCategory: UIActivityCategory {
        return .share
    }

    override var activityType: UIActivityType? {
        return UIActivityType(rawValue: "googlemail")
    }

    override var activityTitle: String? {
        return "Gmail"
    }

    override var activityViewController: UIViewController? {
        return nil
    }

    override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
        guard let url = URL(string: urlScheme) else {
            return false
        }
        return UIApplication.shared.canOpenURL(url)
    }

    override func prepare(withActivityItems activityItems: [Any]) {
        // At this point I store incoming activity items to use them later in `perform()`
        self.activityItems = activityItems
    }

    override var activityImage: UIImage? {
        // 60x60, 120x120 and 180x180
        return nil
    }

    override func perform() {
        guard let body = activityItems?.first as? String, let encodedBody = body.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
            activityDidFinish(false)
            return
        }
        let urlString = "\(urlScheme)///co?body=\(encodedBody)"
        guard let url = URL(string: urlString) else {
            activityDidFinish(false)
            return
        }
        UIApplication.shared.openURL(url)
        activityDidFinish(true)
    }

}
derpoliuk
  • 1,756
  • 2
  • 27
  • 43