XMPPFramework message not sent - iphone

I receive messages from a Google Talk account, they are shown in the Table View in the Ios emulator, but when i send it, it is not shown in the Google Talk client (in another computer). This is the code:
-(IBAction)sendchat:(id)sender
{
General *general = [General sharedManager];//It is a singleton class used to store some values that need to be accesible in the whole application.
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
text=[mensaje text];
NSLog(#"Texto en el body: %#", text);
[body setStringValue:text];
NSArray *dest=[general.firstfrom componentsSeparatedByString:#"/"];//in firstfrom is stored the account from wich we receive the first message. This app cannot start a conversation itself, must only answer
NSLog(#"Destination trimmed: %#", [dest objectAtIndex:0]);//Here, the destination account shows correctly (without the /xxxx stuff, just name#gmail.com)
XMPPMessage *mens=[[XMPPMessage alloc]init];
[mens addAttributeWithName:#"body" stringValue:text];
[mens addAttributeWithName:#"sender" stringValue:general.userlogin];
NSLog(#"text vale: %#", text);
NSXMLElement *messagetosend = [NSXMLElement elementWithName:#"message"];
[messagetosend addAttributeWithName:#"type" stringValue:#"chat"];
[messagetosend addAttributeWithName:#"to" stringValue:[dest objectAtIndex:0]];
[messagetosend addChild:body];
NSLog(#"We are sending to: %#", [dest objectAtIndex:0]);
[self.xmppStream sendElement:messagetosend];
[self xmppStream:xmppStream didReceiveMessage:mens];//manage the sent message as it was received, to show it in the Table View
self.mensaje.text=#"";
}
As I say, messages are received perfectly, but I cannot send. Ive seen plenty of examples of how to send, and they are like my code. If i debug sender it is shown ok (namesender#gmail.com), and the "to" attribute is ok too (namereceiver#gmail.com). The xmppStrem is set correctly (as far as i know):
xmppStream = [[XMPPStream alloc] init];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
In ViewDidLoad method.
Any help? Thank you.
---EDIT---
I forgot to say, both accounts know each others and in the Google Talk client, the presence is sent.

I found the answer. I had two classes receiving messages, because Class A must receive a message to trigger the pushing of the view of the class B (this app is unable to start a chat conversation by itself). So, i set two xmppStream, one for every class. I put an xmppStream in my General class, make both classes take that xmppStream, and it now sends messages.

Related

How to send an SMS at a specific time

i'm new to iphone application development.
i'm creating a application to send sms.
In my application i need to send sms on specified time.
I have a time picker to specify the time in UITextField.
-(void)sendInAppSMS
{
NSLog(#"SendMessage");
if([textFieldRounded.text isEqualToString:#""] || [textFieldRounded1.text isEqualToString:#""] || [textFieldRounded2.text isEqualToString:#""] || [textFieldRounded.text isEqualToString:#"(null)"] || [textFieldRounded1.text isEqualToString:#"(null)"] || [textFieldRounded1.text isEqualToString:#"(null)"] || [textFieldRounded.text isEqualToString:nil] || [textFieldRounded1.text isEqualToString:nil]|| [textFieldRounded2.text isEqualToString:nil])
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"SMS" message:#"Please Enter All Fields!" delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
}
else
{
NSLog(#"Done");
NSDateFormatter *SentTime = [[NSDateFormatter alloc] init];
[SentTime setDateFormat:#"dd/MM/YYYY hh:mm aa"];
NSDate *now1 = [NSDate date];
NSString *Time1 = [SentTime stringFromDate:now1];
NSLog(#"Time is :%#",Time1);
NSString *Sentime=[NSString stringWithFormat:#"%#",textFieldRounded2.text];
if([Sentime isEqualToString:Time1])
{
NSLog(#"Time Matching... can send msg now");
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
if([MFMessageComposeViewController canSendText])
{
NSString *Message = [NSString stringWithFormat:#"%#, %#",textFieldRounded1.text,textFieldRounded2.text];
NSLog(#"Message is %#", Message);
controller.body = Message;
controller.recipients = [NSArray arrayWithObjects:#"+919999999999" , nil];
controller.messageComposeDelegate = self;
[self presentModalViewController:controller animated:YES];
}
}
else
{
NSLog(#"Send Message when time reach at %#",textFieldRounded2.text);
//Here What code i should write
}
}
}
if the time is equal to current time then send the sms nowitself (no need to store the messsage anywhere).
Other wise i need to send that sms , when current time becomes as that specified time. Until the time reach how to keep(store) the message and send on the time.
Regards,
Rajendran.B
You can't send SMS using timer in iOS, Apple does not allow this functionality.
see this
In terms of user experience, your code is very unlikely to allow the user to send a message unless the current time matches the exact minute of the specified time. It would make more sense to check to see if the time is after or within a certain range of the specified time. Also of note, it would be easier to make these comparisons if you weren't comparing string literals. (use NSDate and associated convenience methods to make these comparisons)
In terms of sending a message at a certain time, this will likely require a server component in which you register the message to be sent and the time it should be sent, and then at specified intervals, process messages that are in the message send queue.
As has been pointed out in the other answers, it's not possible to "save" the message that the user has composed in the MFMessageComposeViewController to send at a later time (nor are there any other means to do so).
Your options are:
Collect the details for the SMS ahead of time, but then at the correct time prompt the user. You could use a UILocalNotification for this if the app might be closed. You can open a message with the right details prefilled using setTitle:, setBody:, and setRecipients: on the MFMessageComposeViewController instance, so the user will just have to hit send.
Send the message details back to a server, and send the SMS at the right time using some SMS system such as the Twilio api. This will add significant complexity, and the SMS wouldn't come from the user's phone number.

how can i send message from different accounts in xmpp

I am developing chat application using xmpp client. I can send and receive message when I login with one account. My problem is when i login with two different account i cannot send message using First login account. For sending message i tried the fallowing code:
- (void)sendMessage:(id)sender
{
xmppStream=[[self appDelegate] xmppStream];
NSString *messageStr =messageField.text;
if([messageStr length] > 0)
{
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body setStringValue:messageStr];
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:jidStr];
[message addChild:body];
NSLog(#"%#",message);
}
}
In this delegate method, i create stream object like fallowing
-(void)setUpStream
{
XMPPStream *xmppStream=[XMPPStream alloc] init]
}
when i second time login with another account then xmppStream object is associated with second account but not for First account.
so i can't send message using first account.can any one solve my problem plz and how to create two xmppStream objects for two accounts;
The easiest way to do this is to create to xmppStream objects in your AppDelegate.
Call one xmppStreamOne and xmppStreamTwo.
You could even create an NSMutableArray of xmppStreams if you intent to log into many different different servers.
When you retrieve the xmppStream from the AppDelegate make sure to grab the right one.

Blocking user in XMPP Framework iOS

I am developing a XMPP based chat application for iOS. One of the features of the app is that i need to block some of the users from my rooster.Is there any method available to this in the XMPP framework ? If not, is there some work around to do this ?
Also can some one help me in sending images from one user to other using XMPP ?
There are a number of things you might want to consider:
Likely your user is subscribed to the contact's presence and vice-versa. He will unsubscribe from the contact's presence (so he will no longer receive presence notifications from him) by sending:
<presence to='contact#example.com' type='unsubscribe'/>
He will revoke subscription to his own presence from the contact by sending:
<presence to='contact#example.com' type='unsubscribed'/>
Finally you can remove the item from your roster.
<iq from='user#example.com/home' type='set' id='roster'>
<query xmlns='jabber:iq:roster'>
<item jid='contact#example.com' subscription='remove'/>
</query>
</iq>
In fact, if you send the stanza above, i.e. if you want to cancel both subscriptions, you do not need to send the presence stanzas, they will be handled by the servers.
Finally, you can now block further interaction with the user by means of the jabber:iq:privacy API. This is explained in detail here.
The general presence/roster management is explained in the same rfc, probably best here.
Please check this code to implement user blocking:
-(void)blockUser{
XMPPIQ *iq = [[XMPPIQ alloc]init];
NSString *from = [NSString stringWithFormat:#"from#mail.com/resources"];
[iq addAttributeWithName:#"from" stringValue: from];
[iq addAttributeWithName:#"type" stringValue:#"set"];
NSXMLElement *block =[NSXMLElement elementWithName:#"block" xmlns:#"urn:xmpp:blocking"];
NSXMLElement *item = [NSXMLElement elementWithName:#"item"];
[item addAttributeWithName:#"jid" stringValue:#"to#mail.com/resources"];
[block addChild:item];
[iq addChild:block];
[xmppStream sendElement:iq];
}
- (void)setupXMPPPrivacy
{
NSLog((#"%s [Line %d] "), __PRETTY_FUNCTION__, __LINE__);
//Init XMPPPrivacy List
//xmppPrivacy = [[XMPPPrivacy alloc] init];
xmppPrivacy = [[XMPPPrivacy alloc] initWithDispatchQueue:dispatch_get_main_queue()];
//Activate xmpp modules
[xmppPrivacy activate:[[self appDelegate] xmppStream]];
//Delegate XMPPPrivacy
[xmppPrivacy addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppPrivacy retrieveListWithName :#"Block_List"];
}
-(void)privacyblock
{
[xmppPrivacy retrieveListWithName:#"Block_List"];
[xmppPrivacy setActiveListName:#"Block_List"];
NSXMLElement *privacyElement = [XMPPPrivacy privacyItemWithType:#"jid" value:xmpp_jid action:#"deny" order:1];
[XMPPPrivacy blockIQs:privacyElement];
[XMPPPrivacy blockMessages:privacyElement];
[XMPPPrivacy blockPresenceIn:privacyElement];
[XMPPPrivacy blockPresenceOut:privacyElement];
NSLog(#"-------> PRIVACY ELEMENT: %#", privacyElement);
[arrayPrivacy addObject:privacyElement];
[xmppPrivacy setListWithName:#"Block_List" items:arrayPrivacy];
}

How to send mail from iphone app without showing MFMailComposeViewController?

I want to send mail from my custom iPhone app. I have used MFMailComposeViewController to send mail from my iphone in my previous app. Now, i don't want to show the MFMailComposeViewController to the user, if they click Send Mail button the mail automatically send to the recipient mail address. How can i do this? Can you please help me on this? Thanks in advance.
I have used below code to show the MFMailComposeViewController,
MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setSubject:#"Details"];
[controller setMessageBody:#"Hi" isHTML:NO];
[controller setToRecipients:[NSArray arrayWithObjects:#"abcd.m#gmail.com", nil]];
[self presentModalViewController:controller animated:YES];
[controller release];
Sending emails programmatically, without user intervention, from an iphone application, cannot be implemented using any of the Apple frameworks. It could be possible in a jailbroken phone but then it would never see the inside of App Store.
If you want control of email sending, then a better way would be to set up a web service (at your server end) you can post to using an HTTP request. If you are posting to only one address this can work very well, although you may want to get the user to input their return mail address.
Otherwise only the standard dialog is available (this relies on using whatever account they've setup on the device).
The iOS SDK has made it really easy to send email using the built-in APIs. With a few line of codes, you can launch the same email interface as the stock Mail app that lets you compose an email. You can pop up mail composer form , write message and can send plain mail or file attached mail using MFMailComposeViewController class. For more info : Sending e-mail from your iOS App
But, in this section what i am going to explain is about sending emails without showing the mail composer sheet ie. sending emails in background. For this feature, we can not use iOS native MFMailComposer class because it does not allow us to send emails in background instead it pop ups the mail composer view from where user have to tap "send" button , so for this section i am going to use SKPSMTPMessage Library to send emails in background, however email account has to be hardcoded on this method.
Limitations :
sender/receiver email address has to be hardcoded or you have to grab it using some pop up form in your app where user inputs sender/receiver email address. In addition, sender account credentials has to be also hardcoded since there is no way we can grab it from device settings.
Method :
Import CFNetwork.framework to your project.
Include #import "SKPSMTPMessage.h"
#import "NSData+Base64Additions.h" // for Base64 encoding
Include to your ViewController
Download SKPSMTPMessage library from
https://github.com/jetseven/skpsmtpmessage
Drag and Drop "SMTPLibrary" folder you have downloaded to your project.
Before proceeding, let you know that i am using sender/receiver email address and sender password hardcoded in the code for this example.But, you may grab this credentials from user, allowing them to input in some sort of forms(using UIViews).
-(void) sendEmailInBackground {
NSLog(#"Start Sending");
SKPSMTPMessage *emailMessage = [[SKPSMTPMessage alloc] init];
emailMessage.fromEmail = #"sender#gmail.com"; //sender email address
emailMessage.toEmail = #"receiver#gmail.com"; //receiver email address
emailMessage.relayHost = #"smtp.gmail.com";
//emailMessage.ccEmail =#"your cc address";
//emailMessage.bccEmail =#"your bcc address";
emailMessage.requiresAuth = YES;
emailMessage.login = #"sender#gmail.com"; //sender email address
emailMessage.pass = #"Passwxxxx"; //sender email password
emailMessage.subject =#"#"email subject header message";
emailMessage.wantsSecure = YES;
emailMessage.delegate = self; // you must include <SKPSMTPMessageDelegate> to your class
NSString *messageBody = #"your email body message";
//for example : NSString *messageBody = [NSString stringWithFormat:#"Tour Name: %#\nName: %#\nEmail: %#\nContact No: %#\nAddress: %#\nNote: %#",selectedTour,nameField.text,emailField.text,foneField.text,addField.text,txtView.text];
// Now creating plain text email message
NSDictionary *plainMsg = [NSDictionary dictionaryWithObjectsAndKeys:#"text/plain",kSKPSMTPPartContentTypeKey, messageBody,kSKPSMTPPartMessageKey,#"8bit",kSKPSMTPPartContentTransferEncodingKey,nil];
emailMessage.parts = [NSArray arrayWithObjects:plainMsg,nil];
//in addition : Logic for attaching file with email message.
/*
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"filename" ofType:#"JPG"];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
NSDictionary *fileMsg = [NSDictionary dictionaryWithObjectsAndKeys:#"text/directory;\r\n\tx- unix-mode=0644;\r\n\tname=\"filename.JPG\"",kSKPSMTPPartContentTypeKey,#"attachment;\r\n\tfilename=\"filename.JPG\"",kSKPSMTPPartContentDispositionKey,[fileData encodeBase64ForData],kSKPSMTPPartMessageKey,#"base64",kSKPSMTPPartContentTransferEncodingKey,nil];
emailMessage.parts = [NSArray arrayWithObjects:plainMsg,fileMsg,nil]; //including plain msg and attached file msg
*/
[emailMessage send];
// sending email- will take little time to send so its better to use indicator with message showing sending...
}
Now, handling delegate methods :
// On success
-(void)messageSent:(SKPSMTPMessage *)message{
NSLog(#"delegate - message sent");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Message sent." message:nil delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
}
// On Failure
-(void)messageFailed:(SKPSMTPMessage *)message error:(NSError *)error{
// open an alert with just an OK button
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error!" message:[error localizedDescription] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
NSLog(#"delegate - error(%d): %#", [error code], [error localizedDescription]);
}
Ok, thats all from the coding side. hope this tutorial may find useful for you guyz

ASIHTTPRequest working on emulator but not iphone

Hey guys I have done lots of work with ASIHTTPRequest so far and use it several times in my ios application, however in one area of my app where I have added another asihttprequest method its not working properly.
First of all it must be said that the reason I'm trying to spread the load of downloading and parsing the data.. If I do this on the subview it takes a good 2-3 second to go through the second xml sheet and get all of the related values out.. where as If I do it on this mainview where people are not seeing anything load etc then when the go back to the subview it should look almost instant. I don't know how correct this is but I figure its a okay thing to do to make the app feel abit snappier.
So I am setting it the asihttprequest methods identically as the other ones that work minus caching.
What happens is I select a table cell from the main view that loads the second view and parses a bunch of info to the tableview. the User then selects a value which is passed back to the main view and displayed.
I then parse another lot of xml data checking the selected valueID against everything in the second xml sheet. so that when the user selects the second cell I pass all the data that was just parsed over to the second view to make it look as though its loaded alot faster.
Heres a flow chart of that will explain what I'm trying to do abit better
This is what the parser code looks like in the main view which is the one thats working in the emulator but not on the iphone.
This is my protocol that I call from the subview and pass all the values I need to over and fire off the request to the mainviews ASIHTTPRequest.
- (void) setManufactureSearchFields:(NSArray *)arrayValues withIndexPath:(NSIndexPath *)myIndexPath
{
manufactureSearchObjectString = [[arrayValues valueForKey:#"MANUFACTURER"] objectAtIndex:0];
manufactureIdString = [[arrayValues valueForKey:#"MANUID"] objectAtIndex:0]; //Restricts Models dataset
manufactureResultIndexPath = myIndexPath;
[self.tableView reloadData]; //reloads the tabels so you can see the value in the tableViewCell.
//need some sort of if statment here so that if the back button is pressed modelSearchObjectString is not changed..
if (oldManufactureSearchObjectString != manufactureSearchObjectString) {
modelResultIndexPath = NULL;
modelSearchObjectString = #"empty";
oldManufactureSearchObjectString = [[NSString alloc] initWithFormat:manufactureSearchObjectString];
}
//These two lines below are what execute ASIHTTPRequest and set up my parser etc
dataSetToParse = #"ICMod"; // This sets the if statment inside parserDidEndDocument
[self setRequestString:#"ICMod.xml"]; //Sets the urlstring for XML inside setRequestString
}
This then fires the ASIHTTPRequest delegate methods.
- (IBAction)setRequestString:(NSString *)string
{
//Set database address
//NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:#"http://127.0.0.1:8888/codeData/"]; // imac development
NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:#"http://127.0.0.1:8888/codeData/"]; // iphone development
//PHP file name is being set from the parent view
[databaseURL appendString:string];
NSLog(#"%#", databaseURL);
//call ASIHTTP delegates (Used to connect to database)
NSURL *url = [NSURL URLWithString:databaseURL];
//This sets up all other request
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
When I run this through debug with break points while testing on the iphone this is where the app falls over.. but On the emulator it has no problems.
This next method never gets called when testing on the iphone but workds sweet on the emulator.
- (void)requestFinished:(ASIHTTPRequest *)request
{
responseString = [request responseString]; //Pass requested text from server over to NSString
capturedResponseData = [responseString dataUsingEncoding:NSUTF8StringEncoding];
[self startTheParsingProcess:capturedResponseData];
}
This is the only other delegate that is fired when testing on the iphone, sends me an alret saying the connection has timed out.
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
NSLog(#"%#", error);
UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:#"Error!" message:#"A connection failure occurred." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[errorAlert show];
}
I don't think you need to see all the parser delegates as I don't think they are the issue as this is where the app falls over...
here is what gets printed to the log...
2011-11-29 14:38:08.348 code[1641:707] http://000.000.000.000:0000/codeData/second.xml
2011-11-29 14:38:18.470 code[1641:707] Error Domain=ASIHTTPRequestErrorDomain Code=2 "The request timed out" UserInfo=0x1e83a0 {NSLocalizedDescription=The request timed out}
If you need more of my code let me know.. but I'm at abit of a loss here as like I say there is no difference to how Im doing this ASIHTTPRequest to other views other than I'm initializing it from the protocol that I'm setting up from the second view.. maybe I should set the values before I reload the table or something... I'm not sure though hopefully someone can help me out with this one and spot the issue I cannot see.
Can you view 'http://127.0.0.1:8888/codeData/' with Safari on the iPhone? Chances are that server isn't available from whatever networks the iPhone is connected to.
If your iMac is using DCHP it is possible that the address has changed since you originally set the value.
Are you sure you have the case correct on the URL? The simulator is much more forgiving on case-sensitivity than the actual device.
Do not fly blind but use an HTTP Proxy like Charles for making sure your requests are actually fired and result into what you expect.