TaCode Tuesday: How to Create a Zang CocoaPod for Call and SMS

Posted by Pedram Mohammadi on February 7, 2017

Here’s a nightmare scenario: The night before you deploy your build to production, your colleague notices a bunch of libraries need to be updated and decides to update them, thinking it’s for the best. And then the unspeakable happens: your build breaks. You have to revert back the compatible version – search it, copy it, and test it again. You could have saved the app if not for the 20 libraries that you have to manually restore one by one. Someone has to inform the project manager that deployment has to be postponed. Unfortunately, that someone is you.

Luckily for you, I am here to help with my love of tacos and all the code you need to save the day. What do tacos have to do with your build breaking, you ask? Well it's TaCode Tuesday of course!

Let's Taco 'Bout Your Build

You could have prevented this if you used a dependency manager – a solution that contains a set of tools enabling logical and meaningful management of libraries. It is helpful when dealing with complex projects in a team environment, allowing you to easily keep track of updates, thereby eliminating the need for manual changes. Also known as package managers, it contains a metadata-like list of dependencies, version number, vendor, and software name together with a brief description. When you install a dependency manager, all the metadata is stored in a local package database, allowing you to efficiently manage the dependencies, preventing missing prerequisites and mismatches. A good example of a dependency manager for an iOS application is CocoaPods.

How Does CocoaPods Work?

CocoaPods is a dependency manager for Swift and Objective-C that is very useful to developers who are using a bunch of external libraries for their mobile applications. Using Zang APIs in CocoaPods to build your own call and SMS apps would allow you greater flexibility as it will help to determine and solve dependencies between libraries before downloading or updating your Zang APIs and linking it to your Xcode workspace.

Before you start, make sure you meet the following requirements.

Requirements:

  • Basic knowledge of:
    • MacOSx terminal window commands
    • Xcode IDE
  • Intermediate knowledge of:
    • Objective C
    • Zang SDK login credentials
    • RESTful web services
    • HTTP connectivity and client server architecture
  • Github account

 

Step 1: Install CocoaPods on your MacOSx by following the basic steps outlined on their website. You can start with:

# Xcode 7 + 8

$ sudo gem install cocoapods

 

Step 2: Create a folder and named it “pod” on your MacOSx Desktop.

 

Step 3: Open your terminal window and key in “pod lib create [name of your pod]”. For example: “pod lib create zangpod”. See Figure 1.0 for a sample of an expected output after running “pod lib create” instruction on your terminal window.

 

Figure 1: Successful response when creating a new Pod

Step 4: Go to your folder /Users/{username}/Desktop/pod and you will notice a set of files has been created for you from the instructions on Step 3.

Figure 2: Set of files created after a new Pod

Step 5: Open the folder “Example” and you will find an Xcode project “zangpod.xcodeproj” with its supporting files.

There are three types of metadata included from the generated files:

  1. README.md serves as developer instructions
  2. LICENSE is the open source license of your Pod library
  3. zangpod.podspec contains specific information about your pod such as version number, homepage, and author names. 

 

Step 6: Using Xcode open the “zangpod.xcodeproj”. Your setup would look like this.

Figure 3: What your Xcode looks like after the Pod set-up

 

You will have two major folders for your pod development on your Xcode development window:

  1. Zangpod is your project workspace; it consists of your application data, Podspec Metadata, Tests, Frameworks, Products, and Pods.
  2. Pods is the basic shell of a CocoaPod, containing all pod related development stuff.

 

Step 7: On your Xcode IDE locate the file /Pods/Development Pods/zangpod/zangpod/Classes/Replace.m and then create an interface and implementation file named “Zang.m and Zang.h”.  

 

Step 8: Write your interface prototypes inside the Zang.h file

@interface Zang:NSObject

 

{

//properties for Zang API login credentials

NSString *AccountSID;

 

//properties for call api

NSString *callInboundXMLUrl= @"{your zang enabled inboundxml url}";

NSString *callFrom;

NSString *callTo;

 

//method for call api

-(NSString) makeCall;

 

//properties for sms api

NSString *smsAPIurl;

NSString *smsTo;

NSString *smsBody;

NSString *smsFrom;

NSString *smsStatusCallback;

NSString *smsStatusCallbackMethod;

NSString *smsAllowMultiple;

 

//method for sms api

-(NSString) sendSMS;

}

 

Step 9: Write the code for invoking the call functionality of the Zang API

@implementation Zang

-(id) init

{

self = [super init];

return self;

}

 

-(NSString) makeCall

{

NSString *data_dictionary = @{ @"From": callFrom,

                       @"To": callTo,

                       @"Url": callInboundXMLUrl};

   NSData *postData = [data_dictionary dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

NSData *jsonData = [NSJSONSerialization JSONObjectWithData:postData options:0 error:&error];

 

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];

//fill up the AccountSID during object instantiation via dot notation

[request setURL:[NSURL URLWithString:@"http://api.zang.io/v2/Accounts/{AccountSID}/Calls.json];

[request setHTTPMethod:@"POST"];

[request setHTTPBody:jsonData];

 

NSURLResponse *requestResponse;

NSData *requestHandler = [NSURLConnection sendSynchronousRequest:request returningResponse:&requestResponse error:nil];

 

NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:requestHandler options:0 error:&error];

NSLog(@"resposne dicionary is %@",responseDictionary);

 

NSString *requestReply = [[NSString alloc] initWithBytes:[requestHandler bytes] length:[requestHandler length] encoding:NSASCIIStringEncoding];

NSLog(@"requestReply: %@", requestReply);

return requestReply;

}

 

Step 10: Write the code for invoking the send SMS functionality of the Zang API.

 

-(NSString) sendSMS

{

NSString *data_dictionary = @{ @"To": smsTo,

                       @"Body": smsBody,

                       @"From": smsFrom,

                       @"StatusCallBack",smsStatusCallBack,

                       @"StatusCallbackMethod",smsStatusCallBackMethod,

                       @"AllowMultiple",smsAllowMultiple};

   NSData *postData = [data_dictionary dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

NSData *jsonData = [NSJSONSerialization JSONObjectWithData:postData options:0 error:&error];

 

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];

[request setURL:[NSURL URLWithString:@"https://api.zang.io/v2/Accounts/{AccountSid}/SMS/Messages.json];

[request setHTTPMethod:@"POST"];

[request setHTTPBody:jsonData];

 

NSURLResponse *requestResponse;

NSData *requestHandler = [NSURLConnection sendSynchronousRequest:request returningResponse:&requestResponse error:nil];

 

NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:requestHandler options:0 error:&error];

NSLog(@"resposne dicionary is %@",responseDictionary);

 

NSString *requestReply = [[NSString alloc] initWithBytes:[requestHandler bytes] length:[requestHandler length] encoding:NSASCIIStringEncoding];

NSLog(@"requestReply: %@", requestReply);

return requestReply;

}

@end

 

Step 11: Use your zangpod class through this sample code.

 

int main( )

{

  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    

  Zang *make_call = [[Zang alloc]init];    // Create make_call object of type Zang

 

  //setup necessary values to make a call

  //required authentication id

  make_call.AccountSID = @"{your zang developer account id}";

  

  /*

For e.g, to dial a number in the US, the To should be, +17325551212. SIP endpoints must be prefixed with sip: e.g sip:12345@sip.zang.io.

  */

  make_call.callFrom = @"+17325551212";

  

  /*

  The number to display as calling (i.e. Caller ID). The value does not have to be a real phone number or even in a valid format.

  */

make_call.callTo = @"";

  

  /*The URL requested once the call connects. This URL must be valid and should return InboundXML containing instructions on how to process your call. A badly formatted URL will NOT fallback to the FallbackUrl, but will return an error without placing the call. URL length is limited to 200 characters. */

 

  make_call.callInboundXMLUrl = "{your inboundxml url}"

 

  //After setting up your call configuration values from above, invoke the call method

  

  call_result = [make_call makeCall];

  NSLog(@"JSON call status response : %f", call_result);

  

  Zang *send_sms = [[Zang alloc]init];    // Create  send_sms of type Zang

  send_sms.smsTo = @"{+17325551212}";  // Must be an SMS capable number. The value does not have to be in any specific format.

  send_sms.smsBody = @"{I would like to say hello}"; // Text of the SMS to be sent

  sms_result = [send_sms sendSMS];

  NSLog(@"JSON sms status response: %f", sms_result);



  [pool drain];

  return 0;

}



Example JSON response after making a call:

 

{

 "date_updated": "Wed, 13 Jul 2016 15:25:01 -0000",

 "parent_call_sid": "",

 "duration": 0,

 "from": "+15555555555",

 "to": "+19999999999",

 "caller_id_blocked": "false",

 "answered_by": "nobody",

 "sid": "{CallSid}",

 "recordings_count": "",

 "price": "0.00",

 "api_version": "v2",

 "status": "queued",

 "direction": "outbound-api",

 "start_time": null,

 "date_created": "Wed, 13 Jul 2016 15:25:01 -0000",

 "subresource_uris": {

   "notifications": "/v2/Accounts/{AccountSid}/Calls/{CallSid}/Notifications",

   "recordings": "/v2/Accounts/{AccountSid}/Calls/{CallSid}/Recordings"

 },

 "forwarded_from": "",

 "uri": "/v2/Accounts/{AccountSid}/Calls/{CallSid}",

 "account_sid": "{AccountSid}",

 "duration_billed": 0,

 "end_time": null,

 "phone_number_sid": ""

}

 

Example JSON response after sending SMS:

{

   "api_version": "v2",

   "sid": "{SmsSid}",

   "account_sid": "{AccountSid}",

   "date_created": "Tue, 24 Jul 2012 14:08:23 +0000",

   "date_updated": "Tue, 24 Jul 2012 14:08:24 +0000",

   "date_sent": "Tue, 24 Jul 2012 14:08:24 +0000",

   "to": "+17325551234",

   "from": "+14245551234",

   "body": "Test message sent from TelAPI!",

   "status": "sent",

   "direction": "outbound-api",

   "price": "0.070000",

   "uri": "/v2/Accounts/AC5521767e53d04deeb0a06f660cee50f9/SMS/Messages/{SmsSid}.json"

}

That’s all folks! Follow the CocoaPods deployment guide if you want to release your new pods as an open source library.

Using CocoaPods for Zang is a great idea because it will help you manage dependencies to other external libraries that your app may be using. This allows you to freely make local changes without having to worry about updating to a newer version later on. CocoaPods will also allow you to keep track of current versions of all your libraries, find new ones, and make sure that any dependencies between them are resolved.



 

Topics: Ideas, TaCode Tuesday, cPaaS