Click here to Skip to main content
15,867,453 members
Articles / Mobile Apps / iPhone

Developing an App that Sends SMS Messages

Rate me:
Please Sign up or sign in to vote.
4.97/5 (52 votes)
15 Feb 2013CPOL2 min read 89.8K   3.3K   71   25
How great could it be to be able to send SMS messages from your IPhone using the Internet connection
This article explains how to write an iOS App that will use HTTP to send an SMS.

Background

In my article, How to send an SMS from a Desktop Application, I mentioned CardBoardFish, a simple and easy to use API for sending SMS messages world wide.

The SendSMS App

The app is very basic and simple. It has one screen which looks like this:

The SendSMS App Screen

Basically, you enter the sender's name or number (which could be anything), the country code and phone number of the recipient and a message, and then press "Send".

The message is then sent, and a confirmation number pops up.

OK Confirmation

The most important building block of the App is the Send routine (in ViewController.m):

C++
- (void) send {    
     @autoreleasepool {
        
        NSString *url = [NSString stringWithFormat:
        @"http://sms1.cardboardfish.com:9001/HTTPSMS?S=H&UN=%@&P=%@&DA=%@%@&SA=%@&M=%@&DC=4",
        @"<PLACE YOUR USER NAME HERE>", @"<PLACE YOUR PASSWORD HERE", txtCountryCode.text, 
        txtDestinationNo.text, txtName.text,[self stringToHex:txtMessage.text]];
        
        url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSLog(@"url %@", url);
        
        NSError* connError = 0;
        NSURLResponse* response;
        
        NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:url] 
                   cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20];
        
        NSData* data = [ NSURLConnection sendSynchronousRequest:
                         request returningResponse:&response error:&connError ];
        NSString* resp = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"response: %@", resp);

Interfacing with the Device's Address Book

In order to easily select existing contacts from your IPhone, the openContacts routine is used, which uses a Class named ABPeoplePickerNavigationController which according to Apple, "implements a view controller that manages a set of views that allow the user to select a contact or one of its contact-information items from an address book".

C++
- (IBAction)openContacts:(id)sender {
    
    ABPeoplePickerNavigationController *picker = 
                    [[ABPeoplePickerNavigationController alloc] init];
    picker.peoplePickerDelegate = self;
    NSArray *displayedItems = [NSArray arrayWithObjects:
                              [NSNumber numberWithInt:kABPersonPhoneProperty], 
                              [NSNumber numberWithInt:kABPersonEmailProperty],
                              [NSNumber numberWithInt:kABPersonBirthdayProperty], nil];
    
    picker.displayedProperties = displayedItems;
    [self presentModalViewController:picker animated:YES];
    [picker release];
} 

After an entry from the Address Book is selected, we perform some basic cleansing on it, such as removing leading zeros and spaces, dashes and brackets. So the number "(04) 888-3333" becomes "48883333" which is the required format for the SDK.

C++
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)
   peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person 
   property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
    NSString* phone = nil;
    ABMultiValueRef phoneNumbers = ABRecordCopyValue(person,
                                                     property);
    if (ABMultiValueGetCount(phoneNumbers) > 0) {
        phone = (__bridge_transfer NSString*)
        ABMultiValueCopyValueAtIndex(phoneNumbers, identifier);
    } else {
        phone = @"[None]";
    }
    phone = [phone stringByReplacingOccurrencesOfString:@"(" withString:@""];
    phone = [phone stringByReplacingOccurrencesOfString:@")" withString:@""];
    phone = [phone stringByReplacingOccurrencesOfString:@"-" withString:@""];
    phone = [phone stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    if ([[phone substringWithRange:NSMakeRange(0, 1)] isEqual:@"0"] ) {
        phone = [phone substringFromIndex:1];
    }
    
    txtDestinationNo.text = phone;
    [self dismissModalViewControllerAnimated:YES];
    
    return NO;
}

Country Flags

A nice part I have added is a list of countries along with each country's flag. Not really necessary through... I used 226 flag .PNG images named as the country code of each flag, so 49.png holds the German flag, and so on...

The Country Code Selector

Then CountryCodesViewController.m source file looks like this:

C++
#import "CountryCodesViewController.h"
@interface CountryCodesViewController ()
@end
@implementation CountryCodesViewController
@synthesize mainViewController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] 
                           stringByAppendingPathComponent:@"Flags"];
    countryCodes = [[NSFileManager defaultManager] 
                   contentsOfDirectoryAtPath:sourcePath error:NULL];
    [countryCodes retain];
}
- (void)viewDidUnload
{
    [tblCountryCodes release];
    tblCountryCodes = nil;
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)dealloc {
    [tblCountryCodes release];
    [super dealloc];
}
#pragma mark UITableView methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [countryCodes count];    
}
- (UITableViewCell *)tableView:(UITableView *)tableView 
              cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    UITableViewCell *cell = [[[UITableViewCell alloc] 
       initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
    
    NSString *strFlagName = [countryCodes objectAtIndex:indexPath.row];
    
    
    cell.textLabel.text = [strFlagName substringToIndex:[strFlagName length] - 4];
    
    cell.imageView.image = 
            [UIImage imageNamed:[NSString stringWithFormat:@"Flags/%@",strFlagName]]; 
    
    return cell;
    
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *strFlagName = [countryCodes objectAtIndex:indexPath.row]; 
    
    [mainViewController selectCountryCode:
            [strFlagName substringToIndex:[strFlagName length] - 4]];
    
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
    
    [self dismissModalViewControllerAnimated:YES];
    
}
- (IBAction)okPressed:(id)sender {
    [self dismissModalViewControllerAnimated:YES];
}
@end 

Error Handling

When an error occurs, an error code appears indicating the nature of the error. The HTTPSMS SDK documentation explains each error number.

Image 4

There can be several scenarios in which the transmission fails.

The first one is Connectivity Error. Such error can occur if the IPhone is not connected to the Internet. In such case, we would like to alert the user, and yet, place the SMS in a queue to be sent when the IPhone connects to the Internet. We also would like that in case several SMS messages were composed during the time the device was offline, they will all be placed in the queue and transmitted whenever possible.

This example does not perform any logical error checks (such as validating the format of the phone number, country code, etc. and in any case, only after a message is sent to the Web Service, there might be additional error codes that will raise.

C++
        if ( connError ) {
            NSLog(@"%@",[connError description]);
            
            NSMutableDictionary *message = [[NSMutableDictionary alloc] init];
         
            [message setValue:txtCountryCode.text forKey:@"countryCode"];
            [message setValue:txtDestinationNo.text forKey:@"destinationNo"];
            [message setValue:txtName.text forKey:@"name"];
            [message setValue:txtMessage.text forKey:@"message"];
            
            [self performSelectorOnMainThread:@selector(addToQueue:) 
                                  withObject:message waitUntilDone:NO];
            [message release];
            UIAlertView* alert = [[UIAlertView alloc] init];
            alert.title = @"Send SMS";
            alert.message = @"Can't access Internet. 
                            The message will be queued to be sent later";
            [alert addButtonWithTitle:@"Ok"];
            [alert show];
            [alert release];            
            
        } else {
            UIAlertView* alert = [[UIAlertView alloc] init];
            alert.title = @"Send SMS";
            alert.message = resp;
            [alert addButtonWithTitle:@"Ok"];
            [alert show];
            [alert release];
            
            if ([resp rangeOfString:@"OK"].location != NSNotFound) {
                [self performSelectorOnMainThread:@selector(sendComplete) 
                                        withObject:nil waitUntilDone:YES];
            }            
        }
        
        [resp release];
    }    
    
    loadingView.hidden = YES;
}   

Further Reading

Points of Interest

If you need help getting started with iOS development, please read this article.

Michael Haephrati , CodeProject MVP 2013

History

  • 16th February, 2013: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO Secured Globe, Inc.
United States United States
Michael Haephrati is a music composer, an inventor and an expert specializes in software development and information security, who has built a unique perspective which combines technology and the end user experience. He is the author of a the book Learning C++ , which teaches C++ 20, and was published in August 2022.

He is the CEO of Secured Globe, Inc., and also active at Stack Overflow.

Read our Corporate blog or read my Personal blog.





Comments and Discussions

 
GeneralMy vote of 5 Pin
Amol_B24-Jul-13 23:58
professionalAmol_B24-Jul-13 23:58 
GeneralMy vote of 5 Pin
alonbarak14-Jun-13 11:03
alonbarak14-Jun-13 11:03 
GeneralRe: My vote of 5 Pin
Michael Haephrati4-Jul-13 2:12
professionalMichael Haephrati4-Jul-13 2:12 
GeneralMy vote of 5 Pin
Sudhakar Shinde12-Apr-13 1:24
Sudhakar Shinde12-Apr-13 1:24 
GeneralRe: My vote of 5 Pin
Michael Haephrati12-Apr-13 1:27
professionalMichael Haephrati12-Apr-13 1:27 
GeneralMy vote of 5 Pin
liliflower35525-Jan-13 1:10
liliflower35525-Jan-13 1:10 
GeneralMy vote of 5 Pin
resi243125-Jan-13 0:10
resi243125-Jan-13 0:10 
GeneralMy vote of 5 Pin
midulm24-Jan-13 23:05
midulm24-Jan-13 23:05 
GeneralMy vote of 5 Pin
balam198824-Jan-13 22:20
balam198824-Jan-13 22:20 
GeneralMy vote of 5 Pin
evan89724-Jan-13 21:41
evan89724-Jan-13 21:41 
GeneralMy vote of 5 Pin
John Klinner24-Jan-13 19:49
John Klinner24-Jan-13 19:49 
GeneralMy vote of 5 Pin
Ruth Aanie22-Jan-13 23:13
Ruth Aanie22-Jan-13 23:13 
GeneralMy vote of 5 Pin
John Klinner19-Jan-13 21:51
John Klinner19-Jan-13 21:51 
GeneralMy vote of 5 Pin
Hillary Higg19-Oct-12 20:26
Hillary Higg19-Oct-12 20:26 
GeneralMy vote of 5 Pin
George Rogers II13-Oct-12 6:38
George Rogers II13-Oct-12 6:38 
GeneralMy vote of 5 Pin
Emma20123217-Sep-12 6:45
Emma20123217-Sep-12 6:45 
AnswerRe: My vote of 5 Pin
Michael Haephrati21-Sep-17 9:24
professionalMichael Haephrati21-Sep-17 9:24 
QuestionAPI to decode a received SMS Pin
gvascon115-Sep-12 10:41
gvascon115-Sep-12 10:41 
AnswerRe: API to decode a received SMS Pin
Matan joice15-Sep-12 11:31
Matan joice15-Sep-12 11:31 
AnswerRe: API to decode a received SMS Pin
Michael Haephrati15-Sep-12 23:34
professionalMichael Haephrati15-Sep-12 23:34 
AnswerRe: API to decode a received SMS Pin
Michael Haephrati21-Sep-17 8:55
professionalMichael Haephrati21-Sep-17 8:55 
GeneralMy vote of 5 Pin
JohnBergen24-Jul-12 23:41
JohnBergen24-Jul-12 23:41 
GeneralMy vote of 5 Pin
Matan joice10-Jun-12 7:25
Matan joice10-Jun-12 7:25 
GeneralMy vote of 5 Pin
Member 43208449-Jun-12 8:02
Member 43208449-Jun-12 8:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.