I'm trying to attach a wav-file from an iOS application but the attachment is not delivered even though it's visible in the composed mail.
Heres the related code:
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setSubject:NSLocalizedString(#"mailTopic", nil)];
[controller setMessageBody:NSLocalizedString(#"mailBody", nil) isHTML:YES];
NSString *wavPath = [self exportAssetAsWaveFormat:self.myRec.soundFilePath]; // CAF->Wav export
if (wavPath != nil) {
NSLog(#"wavPath: %#", wavPath);
NSData *recData = [NSData dataWithContentsOfFile:wavPath];
NSString *mime = [self giveMimeForPath:wavPath];
[controller addAttachmentData:recData mimeType:mime fileName:#"MySound.wav"];
[self presentModalViewController:controller animated:YES];
[controller release];
}
}
-(NSString *) giveMimeForPath:(NSString *)filePath {
NSURL* fileUrl = [NSURL fileURLWithPath:filePath];
NSURLRequest* fileUrlRequest = [[NSURLRequest alloc] initWithURL:fileUrl cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:.1];
NSURLResponse* response = nil;
[NSURLConnection sendSynchronousRequest:fileUrlRequest returningResponse:&response error:nil];
NSString* mimeType = [response MIMEType];
NSLog(#"MIME: %#", mimeType);
[fileUrlRequest release];
return mimeType;
}
NSLog results:
NSLog(#"wavPath: %#", wavPath); -> "wavPath: /var/mobile/Applications/71256DCA-9007-4697-957E-AEAE827FD97F/Documents/MySound.wav"
NSLog(#"MIME: %#", mimeType); -> "MIME: audio/wav"
The file path seams to be ok (see NSLog data), and the mime type set to "audio/wav".. Cant figure this out..
The error was that the wav-file was not 100% written by the time I create NSData out of it.. duuuh
Thanks for the effort guys
Maybe the destination is stripping attachments of that type? Did you try manually sending a message with a .wav and see if it works? I had the same problem trying to send to Zendesk. Turns out they strip attachments for some mimetypes.
Related
In my chat application, I am unable to send any image or file while chat. What i tried is ---
Method 1...
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body setStringValue:#"Send Image Testing"];
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:[jid full]];
[message addAttributeWithName:#"from" stringValue:[[xmppStream myJID] full]];
[message addChild:body];
NSImage *img = [NSImage imageNamed:#"loginLogo.png"];
NSData *imageData = [img TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
NSData *data = [imageRep representationUsingType:NSJPEGFileType properties:nil];
NSString *imgStr = [NSString encodeBase64WithData:data];
NSXMLElement *ImgAttachement = [NSXMLElement elementWithName:#"attachment"];
[ImgAttachement setStringValue:imgStr];
[message addChild:ImgAttachement];
[xmppStream sendElement:message];
I added a "xmlElement" named "attachment" in "message" xmlElement. String value of "attachment" is ImageDataString encoded in "Base64" format. But this code is sending only the text to other end(not image).
Don't know the cause of failure, may be i should send NSImage or server link of the image in place of image data.
Method 2...
I also tried "XMPPOutgoingFileTransfer" classes, with following code.
[_fileTransfer sendData:decodedData
named:#"hello"
toRecipient:[XMPPJID jidWithString:#"MYUSERNAME#chat.facebook.com/RESOURCENAME"]
description:#"Baal's Soulstone, obviously."
error:&err])
But every time this is giving the same error - Error Domain=XMPPOutgoingFileTransferErrorDomain Code=-1 "Unable to send SI offer; the recipient doesn't have the required features."
Please help, if any idea
Thanks in advance
I got it working this way-
Inside setupStrem method, set up the incoming end like this -
xmppIncomingFileTransfer = [[XMPPIncomingFileTransfer alloc] init];
xmppIncomingFileTransfer.disableIBB = NO;
xmppIncomingFileTransfer.disableSOCKS5 = NO;
[xmppIncomingFileTransfer activate:xmppStream];
[xmppIncomingFileTransfer addDelegate:self delegateQueue:dispatch_get_main_queue()];
Implement the incoming end delegate methods-
- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender didFailWithError:(NSError *)error
{
DDLogVerbose(#"%#: Incoming file transfer failed with error: %#", THIS_FILE, error);
}
- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender didReceiveSIOffer:(XMPPIQ *)offer
{
DDLogVerbose(#"%#: Incoming file transfer did receive SI offer. Accepting...", THIS_FILE);
[sender acceptSIOffer:offer];
}
- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender didSucceedWithData:(NSData *)data
named:(NSString *)name
{
DDLogVerbose(#"%#: Incoming file transfer did succeed.", THIS_FILE);
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *fullPath = [[paths lastObject] stringByAppendingPathComponent:name];
[data writeToFile:fullPath options:0 error:nil];
DDLogVerbose(#"%#: Data was written to the path: %#", THIS_FILE, fullPath);
}
Incoming files will be written to the documents directory, you can update UI when it is done.
On the sending side-
if (!_fileTransfer) {
_fileTransfer = [[XMPPOutgoingFileTransfer alloc] initWithDispatchQueue:dispatch_get_main_queue()];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[_fileTransfer activate:appDelegate.xmppStream];
_fileTransfer.disableIBB = NO;
_fileTransfer.disableSOCKS5 = NO;
[_fileTransfer addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *fullPath = [[paths lastObject] stringByAppendingPathComponent:filename];
NSData *data = [NSData dataWithContentsOfFile:fullPath];
NSError *err;
if (![_fileTransfer sendData:data named:filename toRecipient:[XMPPJID jidWithString:self.contact.primaryResource.jidStr] description:#"Baal's Soulstone, obviously." error:&err]) {
DDLogInfo(#"You messed something up: %#", err);
}
Implement the outgoing delegate methods -
- (void)xmppOutgoingFileTransfer:(XMPPOutgoingFileTransfer *)sender didFailWithError:(NSError *)error
{
DDLogInfo(#"Outgoing file transfer failed with error: %#", error);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"There was an error sending your file. See the logs." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
- (void)xmppOutgoingFileTransferDidSucceed:(XMPPOutgoingFileTransfer *) sender
{
DDLogVerbose(#"File transfer successful.");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Success!" message:#"Your file was sent successfully." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
Note that the disableIBB and disableSOCKS5 should match at both ends.
If the problem still exists, go to XMPPOutgoingFileTransfer.m and then to the method-
- (void)handleRecipientDiscoInfoQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info
Then put a NSLOG/Breakpoint at this line -
hasSOCKS5 = hasSI && hasFT && hasSOCKS5;
hasIBB = hasSI && hasFT && hasIBB;
Both values should become TRUE when sending a file. Check which one is FALSE (causing the error), you will get an idea why the incoming end is sending FALSE instantly. Try to fix that.
I have to send Video through message. I attached 30KB size of video. But it alerts "Video is too long". Below i mentioned the code to send video through message.
NSString *message = [NSString stringWithFormat:#"Download this Video!"];
MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init];
messageController.messageComposeDelegate = self;
[messageController setBody:message];
if ([MFMessageComposeViewController canSendAttachments]) {
NSLog(#"Attachments Can Be Sent.");
NSString *filePath=[mURL absoluteString];
NSData *videoData = [NSData dataWithContentsOfURL:[NSURL URLWithString:filePath]];
BOOL didAttachVideo = [messageController addAttachmentData:videoData typeIdentifier:#"public.movie" filename:filePath];
if (didAttachVideo) {
NSLog(#"Video Attached.");
} else {
NSLog(#"Video Could Not Be Attached.");
}
}
[self presentViewController:messageController animated:YES completion:nil];
I am trying to fetch gmail & yahoo contacts in my iPhone application.
For Gmail I have used GTMOauth2.0. I can see all contacts but when I want only contacts from MyContacts group. I have used following code to get contacts:
-(void)signInToGoogle:(id)sender
{
[self signOutFromGoogle];
NSString *keychainItemName = nil;
NSString *scope = #"https://www.google.com/m8/feeds/contacts/default/full";
NSString *clientID = #"CLIENTID";
NSString *clientSecret = #"CLIENTSECRETID";
SEL finishedSel = #selector(viewController:finishedWithAuth:error:);
GTMOAuth2ViewControllerTouch *viewController;
viewController = [GTMOAuth2ViewControllerTouch controllerWithScope:scope
clientID:clientID
clientSecret:clientSecret
keychainItemName:keychainItemName
delegate:self
finishedSelector:finishedSel];
NSDictionary *params = [NSDictionary dictionaryWithObject:#"en" forKey:#"hl"];
viewController.signIn.additionalAuthorizationParameters = params;
NSString *html = #"<html><body bgcolor=silver><div align=center>Loading sign-in page...</div></body></html>";
viewController.initialHTMLString = html;
[[self navigationController] pushViewController:viewController animated:YES];
}
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
finishedWithAuth:(GTMOAuth2Authentication *)auth
error:(NSError *)error {
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (error != nil) {
[processObj removeFromSuperview];
self.view.userInteractionEnabled = YES;
NSLog(#"Authentication error: %#", error);
NSData *responseData = [[error userInfo] objectForKey:#"data"]; // kGTMHTTPFetcherStatusDataKey
if ([responseData length] > 0) {
// show the body of the server's authentication failure response
NSString *str = [[NSString alloc] initWithData:responseData
encoding:NSUTF8StringEncoding];
NSLog(#"%#", str);
}
self.auth = nil;
} else {
self.auth = auth;
[self doAnAuthenticatedAPIFetch];
}
}
- (void)doAnAuthenticatedAPIFetch {
NSString *urlStr = #"https://www.google.com/m8/feeds/groups/default/full/Contacts";
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.auth authorizeRequest:request
completionHandler:^(NSError *error) {
NSString *output = nil;
if (error) {
output = [error description];
} else {
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (data) {
// API fetch succeeded :Here I am getti
output = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
} else {
// fetch failed
output = [error description];
}
}
}];
}
In the API I am passing "Contacts" as a group id but it is returning error "Group Id Not Found". I have the google document from
https://developers.google.com/google-apps/contacts/v3/?csw=1
but still can't solve the problem. Help me on these.
You'll need to fetch the groups feed to get the ID for a group. See the groups feed documentation, or try the ContactsSample app provided with the Google Data APIs Objective-C Client Library.
Im simply trying to upload this image to iCloud. It keeps giving me the error "The operation couldn’t be completed. Operation not permitted". I took this code right out of the Document Based App Programming Guide and I believe I've set all my certificates, identifiers, profiles, and entitlements correctly. Any help would be much appreciated. This is insanely frustrating.
#import "docx.h"
#implementation docx
-(IBAction)test:(id)sender{
NSURL *src = [NSURL URLWithString:#"/Users/rjm226/Desktop/jh.jpg"];
NSLog(#"%#", src);
NSURL *dest = NULL;
NSURL *ubiquityContainerURL = [[[NSFileManager defaultManager]
URLForUbiquityContainerIdentifier:nil]
URLByAppendingPathComponent:#"Documents"];
if (ubiquityContainerURL == nil) {
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: NSLocalizedString(#"iCloud does not appear to be configured.", #""),
NSLocalizedFailureReasonErrorKey, nil];
NSError *error = [NSError errorWithDomain:#"Application" code:404
userInfo:dict];
[self presentError:error modalForWindow:[self windowForSheet] delegate:nil didPresentSelector:NULL contextInfo:NULL];
return;
}
dest = [ubiquityContainerURL URLByAppendingPathComponent:
[src lastPathComponent]];
//Move file to iCloud
dispatch_queue_t globalQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globalQueue, ^(void) {
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSError *error = nil;
// Move the file.
BOOL success = [fileManager setUbiquitous:YES itemAtURL:src
destinationURL:dest error:&error];
dispatch_async(dispatch_get_main_queue(), ^(void) {
if (! success) {
[self presentError:error modalForWindow:[self windowForSheet]
delegate:nil didPresentSelector:NULL contextInfo:NULL];
}
});
});
}
#end
This is insanely frustrating.
Welcome to iCloud. You'll get used to that feeling after a while. In the meantime though, you have other problems.
NSURL *src = [NSURL URLWithString:#"/Users/rjm226/Desktop/jh.jpg"];
This is not going to give you a valid URL, which is going to be a problem. What you need is:
NSURL *src = [NSURL fileURLWithPath:#"/Users/rjm226/Desktop/jh.jpg"];
That will give you a valid file:// URL.
This is my first time on this site and I am very new to coding so I was wondering if somebody could help me out.
I want to set a get request from my iphone app to my website and get the information echoed back from the website to my phone.
I have gotten this far but do not know where to go from here. Any help would be much appreciated, thanks!
- (void)myData:(id)sender
{
NSString *DataToBeSent;
sender = [sender stringByReplacingOccurrencesOfString:#"," withString:#"%20"];
[receivedData release];
receivedData = [[NSMutableData alloc] init];
DataToBeSent = [[NSString alloc] initWithFormat:#"http://194.128.xx.xxx/doCalc/getInfo.php?Data=%#",sender];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:dataToBeSent] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];
[request setHTTPMethod: #"GET"];
NSError *requestError;
NSURLResponse *urlResponse = nil;
NSData *response1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
[dataToBeSent release];
}
OLD WAY
- (void)myData:(id)sender
{
NSString *dataToBeSent;
sender = [sender stringByReplacingOccurrencesOfString:#"," withString:#"%20"];
[receivedData release];
receivedData= [[NSMutableData alloc] init];
dataToBeSent= [[NSString alloc] initWithFormat:#"http://194.128.xx.xxx/doCalc/getInfo.php?Data=%#",sender];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:dataToBeSent]];
Theconn= [[NSURLConnection alloc]initWithRequest:theRequest delegate:self];
NSLog (#"test1 %#", theRequest);
NSLog (#"test2 %#", Theconn);
[dataToBeSent release];
}
Then the following methods are called and I get my data BUT if I sent another request after my first one but different data on the same connection, it would always give me the same result which shouldn't happen
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
/* appends the new data to the received data */
[receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
NSString *stringData= [[NSString alloc]
initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(#"Got data? %#", stringData);
[self displayAlertCode:stringData];
[stringData release];
// Do unbelievably cool stuff here //
}
Assuming your data loaded properly you can convert the data into a string and do whatever you want with it.
NSData *response1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
//Make sure to set the correct encoding
NSString* responseString = [[NSString alloc] initWithData:response1 encoding:NSASCIIStringEncoding];
If your server returns JSON there are 3rd party libraries that can parse the string into collections like NSArray and NSDictionary. If your server returns XML then NSXMLParser could be something you can use.
EDIT
I've changed your code to manage the memory a little differently.
.h
#property (nonatomic,retain) NSMutableData * receivedData;
#property (nonatomic,retain) NSURLConnection * Theconn;
.m
#synthesize receivedData;
#synthesize Theconn;
//A bunch of cool stuff
- (void)myData:(id)sender
{
//If you already have a connection running stop the existing one
if(self.Theconn != nil){
[self.Theconn cancel];
}
sender = [sender stringByReplacingOccurrencesOfString:#"," withString:#"%20"];
//This will release your old receivedData and give you a new one
self.receivedData = [[[NSMutableData alloc] init] autorelease];
NSString *dataToBeSent = [NSString stringWithFormat:#"http://194.128.xx.xxx/doCalc/getInfo.php? Data=%#",sender];
NSURLRequest *theRequest= [NSURLRequest requestWithURL:[NSURL URLWithString:dataToBeSent]];
//This will release your old NSURLConnection and give you a new one
self.Theconn = [NSURLConnection connectionWithRequest:theRequest delegate:self];
NSLog (#"test1 %#", theRequest);
NSLog (#"test2 %#", Theconn);
}
//...
//Your delegate methods
//...
- (void) dealloc{
[receivedData release];
[Theconn release];
[super dealloc];
}