Click here to Skip to main content
Click here to Skip to main content

Developing an App that sends SMS messages

By , 15 Feb 2013
 

Introduction 

This article explain 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 messages 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)  

- (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". 

- (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.

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person 
<span class="Apple-tab-span" style="white-space: pre; ">								</span>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];
    
    
<span class="Apple-tab-span" style="white-space: pre; ">	</span>return NO;
}

 

Country Flags 

A nice part I have added is a list of countries along with each country's flag. Not really necesary 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: 

#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 occours, an error code appears indicating the nature of the error. The HTTPSMS SDK documentation explains each error number. 

There can be several scenarios in which the transmission fails. 

The first one is Connectivity Error. Such error can occour 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. 

        
        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 queed 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

How to send an SMS from a Desktop Application

Points of Interest  

If you need help getting started with iOS development, please contact me to haephrati <at> gmail <dot> com or read this article

 

 Michael Haephrati CodeProject MVP 2013    

License

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

About the Author

Michael Haephrati
Israel Israel
Member
Michael Haephrati, born in 1964, an entrepreneur, inventor and a musician. Haephrati worked on many ventures starting from HarmonySoft, designing Rashumon, the first Graphical Multi-lingual word processor for Amiga computer.
 
Worked with Amdocs and managed several software projects, among them one for the Ministry of Tourism in New Zealand.  During 1995-1996 he worked as a Contractor with Apple at Cupertino. After returning to Israel, worked as a Project Manager with Top Image Systems (mostly with JCC, Nicosia), and then at a research institute made the fist steps developing the credit scoring field in Israel. He founded Target Scoring and developed a credit scoring system named ThiS, based on geographical statistical data, participating VISA CAL, Isracard, Bank Leumi and Bank Discount (Target Scoring, being the VP Business Development of a large Israeli institute).

During 2000, he founded Target Eye, and developed the first remote PC surveillance and monitoring system, named Target Eye.

Other ventures included: Data Cleansing (as part of the DataTune system which was implemented in many organizations.
 


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberSudhakar Shinde12 Apr '13 - 1:24 
GeneralRe: My vote of 5mvpMichael Haephrati12 Apr '13 - 1:27 
GeneralMy vote of 5memberliliflower35525 Jan '13 - 1:10 
GeneralMy vote of 5memberresi243125 Jan '13 - 0:10 
GeneralMy vote of 5membermidulm24 Jan '13 - 23:05 
GeneralMy vote of 5groupbalam198824 Jan '13 - 22:20 
GeneralMy vote of 5groupevan89724 Jan '13 - 21:41 
GeneralMy vote of 5memberJohn Klinner24 Jan '13 - 19:49 
GeneralMy vote of 1memberPJohnMathews23 Jan '13 - 22:18 
GeneralMy vote of 5memberRutuanie22 Jan '13 - 23:13 
GeneralMy vote of 5memberJohn Klinner19 Jan '13 - 21:51 
GeneralMy vote of 5memberHillary Higg19 Oct '12 - 20:26 
GeneralMy vote of 5memberGeorge Rogers II13 Oct '12 - 6:38 
GeneralMy vote of 5memberEmma20123217 Sep '12 - 6:45 
QuestionAPI to decode a received SMSmembergvascon115 Sep '12 - 10:41 
AnswerRe: API to decode a received SMSmemberMatan joice15 Sep '12 - 11:31 
AnswerRe: API to decode a received SMSmemberMichael Haephrati15 Sep '12 - 23:34 
GeneralMy vote of 5memberJohnBergen24 Jul '12 - 23:41 
GeneralMy vote of 5memberMatan joice10 Jun '12 - 7:25 
GeneralMy vote of 5memberMember 43208449 Jun '12 - 8:02 

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 16 Feb 2013
Article Copyright 2012 by Michael Haephrati
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid