First of all, I would like to say that if you are looking for a way of sending mails without using the Apple's mail composer you are not looking in the proper site. However I had the same purpose at the beginning, but I didn't want to deal directly with the SMTP protocol and I couldn't find any supported library.
Instead of a custom mail scene, you are going to have the Apple's standard mail composer. Something like that:
Implementing this is not difficult using MFMailComposeViewController, but with Cocos2D you have to pay attention at several points.
The general idea is simple: create the composer, check if it can send mails, set the delegate, fill the mail and tell the controller to show the composer.
So, the steps to follow are;
The main problems with Cocos2D are the animation and that you don't work with view controllers, instead you have scenes, layers, ...
For the first problem, it's as easy as pausing the director before showing the composer and resuming it after the mail is sent.
For the controller issue, I found in the cocos-2d forum a solution which involved creating a view controller and setting the view to the openGL view. That worked pretty fine with iOS5, but arise a uncaught exception when testing in iOS6. More than one view controller cannot be associated with the same view.
I finally got to the solution, take the view controller, stored in the appDelegate (it implies a little modification in the appDelegate class), and use it to show the mail view.
So, the steps to follow are;
- Add the MessageUI framework to the project.
- Make your class implement MFMailComposeViewController.
- Instantiate the mail composer
- Check if the device can send the mail. This checks whether the iPhone Mail app is synchronized with an account or not. In this last case, you should break here and show an error.
- Set the delegate to self. Your class now must contain the method mailComposeController:didFinishWithResult:error:
- Fill the mail with the subject, recipients, body...
- Tell the UI view controller to show the composer
The main problems with Cocos2D are the animation and that you don't work with view controllers, instead you have scenes, layers, ...
For the first problem, it's as easy as pausing the director before showing the composer and resuming it after the mail is sent.
For the controller issue, I found in the cocos-2d forum a solution which involved creating a view controller and setting the view to the openGL view. That worked pretty fine with iOS5, but arise a uncaught exception when testing in iOS6. More than one view controller cannot be associated with the same view.
I finally got to the solution, take the view controller, stored in the appDelegate (it implies a little modification in the appDelegate class), and use it to show the mail view.
Finally, the code should be like that:
Remark. All of this is assuming that you are working with cocos2d 1.x. This is reasonable assumption since the new version in cocos2d is quite recent, it has several changes from the older version and doesn't support iOS <4 or iPhone <3GS.
With Cocos2d 2.x and this documentation, I suppose (I haven't tried it yet) that the problem is no more there, because our SharedDirector will be itself our view controller (we don't need to ask the AppDelegate nor create the rootViewController variable)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <UIKit/UIKit.h> | |
@class RootViewController; | |
@interface AppDelegate : NSObject <UIApplicationDelegate> { | |
UIWindow *window; | |
RootViewController *viewController; | |
} | |
@property (nonatomic, retain) UIWindow *window; | |
- (RootViewController *) getVController; //New method | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- (RootViewController *) getVController { | |
return viewController; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <MessageUI/MessageUI.h> | |
@interface YourLayer : CCLayer <MFMailComposeViewControllerDelegate> { | |
MFMailComposeViewController *picker; | |
UIViewController *rootViewController; | |
} | |
- (void) displayComposerSheet; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Call this method when you want to display the composer | |
- (void) displayComposerSheet { | |
// Pause the animation | |
[[CCDirector sharedDirector] pause]; | |
// Get the UI view controller | |
rootViewController = (UIViewController*)[(AppDelegate*)[[UIApplication sharedApplication] delegate] getVController]; | |
// Instantiate the mail composer and check if it can send mails | |
picker = [[MFMailComposeViewController alloc] init]; | |
if ((!picker) || ![MFMailComposeViewController canSendMail]) { | |
NSLog(@"Impossible to send mail"); | |
return; | |
} | |
picker.mailComposeDelegate = self; | |
// Fill the mail content | |
NSArray *toArray = [NSArray arrayWithObjects:@"recipient1@themail.com",@"recipient2@themail.com", nil]; | |
[picker setToRecipients:toArray]; | |
[picker setSubject:@"This test is working!"]; | |
[picker setMessageBody:@"Oh my God! This is working! Even I can add a <a href=\"http://www.google.com\">link</a>! <br/> Me" isHTML:YES]; | |
// Display the view | |
[rootViewController presentModalViewController:picker animated:YES]; | |
// We don't need it anymore | |
[picker release]; | |
} | |
// This method is triggered on mail composer actions | |
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error { | |
// Resume the animation | |
[[CCDirector sharedDirector] resume]; | |
// All the possible results | |
switch (result) { | |
case MFMailComposeResultCancelled: | |
NSLog(@"Cancelled"); | |
break; | |
case MFMailComposeResultSaved: | |
NSLog(@"Mail saved not sent"); | |
break; | |
case MFMailComposeResultFailed: | |
NSLog(@"Failed sending mail"); | |
break; | |
case MFMailComposeResultSent: | |
NSLog(@"Mail sent"); | |
default: | |
break; | |
} | |
// Hide the composer | |
[rootViewController dismissModalViewControllerAnimated:YES]; | |
} |
With Cocos2d 2.x and this documentation, I suppose (I haven't tried it yet) that the problem is no more there, because our SharedDirector will be itself our view controller (we don't need to ask the AppDelegate nor create the rootViewController variable)