Friday, July 31, 2015

iOS Settings Bundle - Registering default values

By default, iOS Settings bundle does not register the default values from the preferences. In order to make sure the default values are present, application needs to use the registerDefaults method. This can be either done one by one key and value like below or using the bundle.plist reading and getting the key and registering it. 

// Set the application defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"YES"
                                                        forKey:@"enableRotation"];
[defaults registerDefaults:appDefaults];

[defaults synchronize];

references:
http://useyourloaf.com/blog/2010/05/18/adding-a-settings-bundle-to-an-iphone-app.html

Geo fencing Practicals

Below given snippet. API client connection need to be done before starting the geo fencing request. 

public int onStartCommand(Intent intent, int flags, int startId)
            {
                
                if(mGeofenceList == null)
                {
                    mGeofenceList = new ArrayList();
                }
                mGeofenceList.add(new Geofence.Builder()
                                  // Set the request ID of the geofence. This is a string to identify this
                                  // geofence.
                                  .setRequestId("HOME_GF")
                                  .setCircularRegion(12.841022,
                                                     77.6480388,
                                                     100
                                                     )
                                  .setExpirationDuration(600000 * 6)
                                  .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
                                                      Geofence.GEOFENCE_TRANSITION_EXIT)
                                  .build());
                
                buildGoogleApiClient();
                mGoogleApiClient.connect();
                return START_REDELIVER_INTENT;

            }

private PendingIntent getGeofencePendingIntent() {
    // Reuse the PendingIntent if we already have it.
    if (mGeofencePendingIntent != null) {
        return mGeofencePendingIntent;
    }
    Intent intent = new Intent(this, GeoFenceTransitionsIntentService.class);
    // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
    // calling addGeofences() and removeGeofences().
    return PendingIntent.getService(this, 0, intent, PendingIntent.
                                    FLAG_UPDATE_CURRENT);
}

/**
 * Runs when a GoogleApiClient object successfully connects.
 */
@Override
public void onConnected(Bundle connectionHint) {
    Log.i(LOG_TAG, "Connected to GoogleApiClient");
    Toast.makeText(AppUtils.getAppContext(), "Connected to GoogleApiClient", Toast.LENGTH_SHORT).show();
    LocationServices.GeofencingApi.addGeofences(
                                                mGoogleApiClient,
                                                getGeofencingRequest(),
                                                getGeofencePendingIntent()
                                                ).setResultCallback(this);
}

@Override
public void onConnectionFailed(ConnectionResult result) {
    // Refer to the javadoc for ConnectionResult to see what error codes might be returned in
    // onConnectionFailed.
    Log.i(LOG_TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
    String info = "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode();
    Toast.makeText(AppUtils.getAppContext(), info , Toast.LENGTH_SHORT).show();
}

@Override
public void onConnectionSuspended(int cause) {
    // The connection to Google Play services was lost for some reason.
    Log.i(LOG_TAG, "Connection suspended");
    Toast.makeText(AppUtils.getAppContext(), "Connection suspended" , Toast.LENGTH_SHORT).show();
    
    // onConnected() will be called again automatically when the service reconnects
}
References:



Android Sending SMS in background.

Sending an SMS in background is quite simple. below is the code that will let one do that

public void sendSMS(String message,String destination)
{
    SmsManager smsManager = SmsManager.getDefault();
    if( smsManager != null )
    {
        PendingIntent sentPI = PendingIntent.getBroadcast(AppUtils.getAppContext(), 0,
                                                          new Intent(AppUtils.getAppContext(), SMSSentStatusReceiver.class), 0);
        PendingIntent deliveredPI = PendingIntent.getBroadcast(AppUtils.getAppContext(), 0,
                                                               new Intent(AppUtils.getAppContext(), SMSDeliveryStatusReceiver.class), 0);
        smsManager.sendTextMessage(destination,null,message,sentPI,deliveredPI);
    }
}

Note that there are two receivers one is SMSSentStatusReceiver and SMSDeliveryStatusReceiver which will receive the callbacks to update the status of sent and delivery respectively.

References:

iOS View Controller Containment

A best example of Container view controllers are Tab View Controllers. In essence, this is about containing other controllers inside one controller. Before iOS 5.0 view controller containers were existing only in the framework classes. 

When designing a container, we are establishing a parent child relation ship between container and its child controllers. A container can add the content views of other view controllers in its own view hierarchy Whenever child view is displayed in containers view, the Controller also establishes a connection to the child view controller and ensure that all appropriate view controller events are sent to the child. 

Below is the code to add a child view controller to a Customer Container view controller 

-(void) addChildViewController:(UIViewController*) content 
{
[self addChildViewController:content];
content.view.frame = self.view.frame;
[self.view addSubView:content.view];
[content didMoveToParentViewController:self];
}

When a child view Controller is added to a controller, its willMoveToParentViewController will be called automatically. 

To remove a child controller from a Container view controller, below can be used

-(void) removeChildViewController:(UIViewController*) content
{
[content willMoveToParentViewController:nil];
[self.view removeFromSuperView:content.view];
[content removeFromParentViewController:nil];
}

For a container with essentially static contents, adding and removing view controllers is simple like above. Sometimes we would want to animate a view into the scene while simultaneously removing another child. 

-(void) tranitionToNewViewController:(UIViewController*)newVC oldVC:(UIViewController*)oldVC
{
[oldVC willMoveToParentViewController:nil];
[self addChildViewController:newVC];
self transitionFromViewController:oldVC toNewViewController:newVC
duration:0.25 options:0
animations:^{
newVC.view.frame = oldVC.view.frame;
oldVC.view.frame = endFrame;
}
completion:^{
[oldVC removeFromParentViewController];
[newVC didMoveToParentViewController:self];
}
}


References:


iOS Coredova Plugin - An Overview

The call exec(, , , ,[args]); from javascript code effectively marshals the request from UIWebView to the native iOS side calling the method on the service class passing the arguments to the action method. 

The plugin needs to be defined as a Feature tag in the XML file. The plugin xml file needs to specify the tags and these tags gets injected into the config.xml file. 

Plugins can utilize the pluginInitialize method to start up the services. Plugins should also implement the onReset method to stop the services if there are long running tasks. This method get called whenever the WebView changes the focus of the page. 

The general format of the cordova plugin method is like below 

-(void) pluginMethodSample:(CDVInvokeUrlCommand*)command
{
CDVPluginResult *pluginResult = nil;
NSString argument1 = [command.arguments objectAtIndex:0];
if(argument1 == nil)
{
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@“command was nil”];
}
else 
{
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}

For the return type, we can have String, Int, Double, Bool, Array, Dictionary, ArrayBuffer and multipart types. 

The complex return types include, 

messageAsArrayBuffer expects as NSData and converts as ArrayBuffer in the javascript callback. Likewise, ArrayBuffer sent from javascript is converted into NSData in iOS argument 
messageAsMultiPart expects and NSArray containing any of the other supported types, and sends the entire array as the arguments to the Javascript callback. This way, all the arguments are 
serialized and deserialized as necessary. It is safe to result back NSData as as mutlipart but not as Array/Dictionary. 

References:

Wednesday, July 29, 2015

Android Geo Fencing Basics

Geo fencing work by marking a lat and long as the center and a radius as the proximity. Or in other words, the latitude, longitude and radius define a geofence. 
There can be multiple geo fences active with a limit of 100 per device user. For each geofence, we can ask location services to send the entrance and exit events or can specify the duration within the geo fence area to wait or dwell before triggering an event. We can limit the duration of any geo fence by specifying an expiration duration in milliseconds. Afer the geofence expires, Location services automatically removes it. 

Set up for Geo fence Monitoring 
Ignored for this to work, application needs to have ACCESS_FINE_LOCATION permission in the application manifest file. 

Ignored to listen to the geo fence transitions, need to have a geo fence intent service in the manifest file as well. 
Below is what taken from the application manifest for e.g. 

To Create the Geo fence, Application needs to use the Builder class available in the location APIs.To handle the intents sent from Location services when geofence transitions occur, application can specify a PendingIntent  

Below are the main steps involved 

1. Define Geofence
2. Monitory State changes 

Defining the Geofence is in following 3 three steps 
1. Create Geofence objects by specifying lat, long, radius, Id, expiration duration, transition types. Use GeoFence.Builder for this
2. Make a geofencing request - Use GeoFencingRequest.Builder for this purpose. need to add the geo fences created in step #1 to this and set the Initial triggers 
3. Define an intent for the geo fencing transitions - This is a normal PendingIntent 
4. Now add the geo fences with the configurations to the GeoFencingApi 

LocationServices.GeoFencingApi.addGeoFences(mGoogleApiClient, GeoFencingRequestObject, GeoFencingPendingIntent).setResultCallback(this);

References:

Monday, July 27, 2015

WiFi Connectivity State Monitoring

In order to get the WiFi State changes, need to register a broadcast receiver. I registered a broadcast receiver in the Service like below and it all worked very well.

public int onStartCommand(Intent intent, int flags, int startId)
{
    Log.v(LOG_TAG,"Network connection sensor is starting");
    //start the wifi sensor right now
    mWifiReceiver = new WifiReceiver();
    IntentFilter mIntentFilter = new IntentFilter();
    mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
    mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
    mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
    registerReceiver(mWifiReceiver, mIntentFilter);
    return START_REDELIVER_INTENT;

}

private class WifiReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
        if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
            notifyScanResult();
        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
            mWifiNetworkInfo =
            (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
            Log.v(LOG_TAG, "mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
            if (mWifiNetworkInfo.getState() == NetworkInfo.State.CONNECTED) {
                mBssid = intent.getStringExtra(WifiManager.EXTRA_BSSID);
                Log.v(LOG_TAG,"Connected SSID is :"+mBssid);
                WifiManager wifiManager = (WifiManager) getSystemService (Context.WIFI_SERVICE);
                WifiInfo info = wifiManager.getConnectionInfo ();
                String bssid2 = info.getBSSID();
                Log.v(LOG_TAG,"connected SSID "+info.getSSID());
                Log.v(LOG_TAG,"Connected SSID bssid2 :"+bssid2);
                AppUtils.infoLog("Connected SSID:"+info.getSSID()+":BSSID :"+bssid2+":bSSID :"+mBssid);
                notifyWifiState();
            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                                                WifiManager.WIFI_STATE_UNKNOWN);
                notifyWifiState();
            }
            else {
                return;
            }
        }

    }

References:
http://alvinalexander.com/java/jwarehouse/android/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java.shtml

Cordova Plugin - Overview

A plugin is a package of injected code that allows the cordova web view within which the app renders to communicate with the native platform on which it runs. Plugins provide access to the device and platform functionality that is ordinarily unavailable to the web based applications. 

Plugin comprises of a single javascript interface along with corresponding native code libraries for each platform. In essence this hides various native code implementations behind a common Javascript interface. 

To make a simple plugin such as echo client, the steps are as below 

1. To Build Plugin 
Application can use CLI’s plugin add command to apply a plugin to a project. the argument to that is the URL to the git repository that contains the plugin code. 

e.g. 

cordova plugin add https://plugin.git 

The plugin repository features a plugin.xml file at the top-level. This is the manifest file for the plugin. The id attribute is the reverse dns name format of the package as the apps to they are added. the js-module tag specifies the common javascript interface. The platform tag specifies the corresponding platform code say for e.g. iOS platform. The platform tag has config-file and that encapsulates the feature tag that is injected into the platform-specific config.xml to make the platform aware of the additional code library. the header file and the source file for the library is specified in the header-file, source-file tags. 

The Javascript interface of the plugin

this is the most important part and is the front facing code interface to the plugin. It will have a cordova.exec function that communicates with the native platform. The syntax is below 

cordova.exec(function(winParam){},function(error){},”service”,”action”,[“firstArgument”,”secondArgument”,42,false]);

winParam){} => Is the success callback 
error){} => is the failure callback
“service” is the name of the service to call on the native side. 
“action” => is the name of the action to be called on the native side. 
arguments is the array of arguments to pass to the native side. 

window.echo = function (str,callback)
{
cordova.exec(callback,function(err) {callback (‘nothing to echo’);},”Echo”,”echo”,[str]);
};

this basically attaches the echo as a window function. The function accepts a string to be echoed and the callback function for the echo. 

The function can be called like the below 

window.echo(“echo me ”,function(echovalue){alert(echovalue==“echo me”)} );

references:

Friday, July 24, 2015

iOS NSURLSession - Uploading Content

Apple has described NSURLSession as both a new class and a suite of classes. There’s new tools to upload, download, handle authorization, and handle just about anything in the HTTP protocol. 

NSURLSession is made using NSURLConfiguration and an optional delegate. After creating the session, the networking needs are satisfied by creating NSURLSessionTasks. 

There are 3 NSURLSessionConfigurations

1. defultSessionConfiguration : This is most like NSURLConnection. This configuration object uses a global cache, cookie and credential storage objects. 
2. ephemeralSessionConfiguration : this configuration is for private sessions and has no persistent storage for cache, cookie or credential storage objects. 
3. backgroundSessionConfiguration : this is the configuration to use if we are going to create the session from background such as remote notification received. i.e. basically when app is suspended. 

NSURLConnection does their most of the jobs by their minions NSURLSessionTasks. 

For eg. To Upload a zip File content, below to be done. Very Important that to specify the Content-Type. Else, the session seems to be sending the data as Query parameters as seen from the Java Servlet end. 

-(void) uploadImageData
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *logFilePath = [NSString stringWithFormat:@"%@/%@",documentsDirectory,@“file.zip”];

    NSData *logData = [[NSFileManager defaultManager] contentsAtPath:logFilePath];
    
    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    sessionConfiguration.HTTPAdditionalHeaders = @{@"_username": @"testuser"};
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
    NSURL *url = [NSURL URLWithString:@"https://myserverurl.com/upload”];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request addValue:@"application/octet-stream" forHTTPHeaderField:@"Content-Type"];
    request.HTTPBody = logData;
    request.HTTPMethod = @"POST";
    NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        NSLog(@"Error :%@",error);
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
        
        NSDictionary *dict = httpResponse.allHeaderFields;
        NSLog(@"All Headers :%@",dict);

    }];
    [postDataTask resume];
}

References:

Tuesday, July 21, 2015

iOS NSURLSession refreshing bit of basics

Apple introduced NSURLSession to replace the NSURLConnection as a preferred way for networking. 

Below are the main reasons behind we using the NSURLSession. 

1. Background uploads and downloads: When creating the NSURLSession object, we get the benefits of background networking. This helps with the battery life, supports UIKit multitasking and uses the same delegate model as in-process transfers. 

2. Ability to pause and resume networking operations: It looks like with NSURLCOnnection API, any networking operation can be paused, stopped and restarted. No NSOperation sub classing is required. 

3. Configurable Container. Each URLSession is a configurable container for putting request into. For e.g. if we need to set and HTTP header option, we just need to do this once and each request in the session will have the same configuration. 

4. Subclassable and Private storage. NSURLSession is subclassable and we can configure a session to use private storage on a per session basis. This allows developer to have private storage per session basis. This allows developer to have private storage objects outage of the global stage. 

5. Improved authentication handling - Authentication is done per connection basis. When using NSURLConnection if an authentication challenge was issued, the challenge would come back for an arbitrary request, the problem with this is that we won’t know for which request this was returned.  

6. Rich Delegate model: NSURLConnection had some asynchronous block based methods. However delegate cannot be used with them. When a request is made it either works or fails even if authentication was needed. With NSURLSession, we can have a hybrid approach, use the asynchronous block based methods and also setup a delegate to handle authentication. 

7. Uploads and downloads through the file system: This encourages the separation of the data (file contents) from the metadata (the URL and settings) 

Simple requests seemed very simple as this below 

NSURLSession *session = [NSURLSession sharedSession];
    [[session dataTaskWithURL:[NSURL URLWithString:@"http://api.openweathermap.org/data/2.5/weather?q=London,uk"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (data !=NULL)
        {
            NSString *strData = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"data is :%@",strData);
        }
        //
    }] resume];


References:

Monday, July 20, 2015

iOS Development Cool command line utilities

Packaging application if having .app file, mobile provision and Signing identity is present

 /usr/bin/xcrun -sdk iphoneos PackageApplication -v "AppRTCDemo.app" -o "/Users/muser.r/Desktop/RR/per/iOS/WebRTC/src/out_ios64/Release-iphoneos/AppRTCDemo.ipa" --sign "iPhone Distribution: mycompany, Inc." --embed "/Users/muser.r/Desktop/RR/Projects/certs/CCADist.mobileprovision"

To find all Signing identities currently active on the Machine 
security find-identity


To get the detail of the provisioning profile used for signing
security cms -D -i src/out_ios/Release-iphoneos/AppRTCDemo.app/embedded.mobileprovision

To remove the code signature from the compiled app 
 rm -rf src/out_ios/Release-iphoneos/AppRTCDemo.app/_CodeSignature/

To Copy the mobile provisioning profile into the .app file
cp ~/Downloads/my_personal.mobileprovision src/out_ios/Release-iphoneos/AppRTCDemo.app/embedded.mobileprovision


Coding after the profile is copied to the .app file
codesign -f -s "iPhone Developer: Jason Adams (SZ2V5SDF5DF)" --resource-rules src/out_ios/Release-iphoneos/AppRTCDemo.app/ResourceRules.plist src/out_ios/Release-iphoneos/AppRTCDemo.app


Reference:

Sunday, July 19, 2015

iOS Asset Catalogs - just an overview

Asset catalogs are to simply the management of images that are used by the app as part of its user interface. 

Typically, an asset catalog can include 

Image sets: Used for most type of images, an image set contains all versions or representations of an image that are necessary to support various devices and scale factors. 

App Icons : App icon contains all representations of an icon that iOS must provide to be displayed on device’s homescreen and in the app store. 

Launch Images: Launch image sets contain all the representations of the static launch image that iOS apps must provide to temporarily.

There are 3 areas of Asset catalog in Xcode, set list, set viewer, set attributes inspector. 

To access the image, the platform specific methods such as imageNamed: can be used. 

In Xcode 6, if the deployment target minimum is 7.0, then below two features are extra 

1. Individual image can be loaded using set names
2. For deployment targets of at least 7.0 or OX 10.9, Xcode compiles the asset catalog to a runtime binary file format that reduces the download time of the app. 

Each asset catalog in Xcode has a corresponding folder with an .xcassets extension, and there are sub folders for each set. Each folder in turn contains the image representations, along with the Contents.json file describing each image. This file is automatically created by Xcode. 

We can share the asset catalog between different projects in the same workspace. 

It is very easy to create an image set. Just drag and drop the image to be added to the set and by default it takes it as the 1x resource. 

To customize image set for size classes, In the attribute inspector, select the Height and width and select Any & Regular. This adds many combinations such as one for e.g. 2x[-*] is a 2x image for horizontal compact size class and any vertical size class. 


Note also that In the device, we can specific if separate image is needed depending on the device models. To do this, on the Devices drop down, select the option Device Specific. 


references:

iOS Storyboard Part II - Notes From Apple Tutorial

The first part of the storyboard tutorial from Apple did include unwind segue, but most important thing to me was when Save was pressed, it was doing the same action as Exit / cancel on the screen. So, the main thing to learn is how to Save the data from the current controller itself before unwinding back. 

On thing to remind is that Assistant editor is powerful. Once a view controller is selected, its custom controller is shown side by side and just by control dragging the component, can add the properties to the class. 


Now, since on Save button press, opted to exit out, one can uncomment the method in the current view controller and assign the variables. 

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.

    self.favItemName = self.myfavName.text;
}

Now on the target controller to which unwinding is happening, the code can be added like below 

- (IBAction)unwindToList:(UIStoryboardSegue *)segue
{
    NewFavoriteViewController *favVC = [segue sourceViewController];
    NSString *favItemName = favVC.favItemName;
}


References:

Saturday, July 18, 2015

iOS Storyboard - A Few Notes From Apple Tutorial

Displaying Static content in table view. 

This is mainly used if we want to quickly produce an application with some predefined cells, rather than doing something in the code. Below simple steps can select the Static cells option instead of the Dynamic prototype option which the one selected by default. 

. Select the table view, 
2. on the right attribute inspector panel, select “Content” As static cells  
3. This adds three cells to the table view. Now we can select first cell and In the attribute inspector, change the Style to Basic or any of the 4 options available. And change the values of the different sections accordingly 
4. We can copy paste the cell and make enough cell to make a prototype. 


This actually establishes a root view controller relationship. This means that the view for the content displayed below the navigation bar will be the tableview. The storyboard entry point is now at the navigation controller because the navigation controller holds all of the content that displayed in the app.  

Now the task is to configure the navigation bar. We need navigational elements such as Back, an additional button such as Add. 

The essential point is that the navigation controllers doesnt have any of the navigation items defined. It picks the navigation bar elements from the ViewController that it is current displaying. With this in mind, we need to configure the Current View Controller i.e. the TAbleViewController to have the navigation elements. 

First of all the title of the navigation bar. This is set by the following steps. 

- On the scene that contains the view controller, there will be a Navigation bar item. Select and just set the title to the one desired. Thats All! 



To add a bar button, just drag and drop a Bar button from the object library and place on to the navigation bar of the selected View Controller. 

Now to show a different view Controller when user press on + Button, we can do that by control dragging the + button and dragging on to the new VC. When adding segue, the Show option is to push the view controller. In case if we want to present modally, that also is an option. When presenting the controller modally, the navigation bar is not getting associated with the controller. The navigation bar get associated in the same way as done initially, i.e. Editor > Embed In > Navigation Controller 

All things are almost done. One item remaining is to navigate back.  Different types of Segues are show and modal segues, one additional segue type is unwind segue. The unwind segue allows user to go back from one scene to another and it also provides a place for a developer to add code that get executed when users navigate to the previous scene. 

To do that, first on the destination view controller, add a method that accepts the UIStoryBoardSegue and returns an IBAction. Now, just add a Bar button to the navigation bar and cotnroll drag that to the Exit icon on the scene. This brings up the method that is added in the destinationView controller like the below. 







References:


iOS Creating a Slide out navigation Panel - Exploring One of the concepts

Thought to take a look into how the slide out navigation panel concept is implemented in other applications. Just to see how different this is from one of the concept already implemented one of the project done. 

Below were the initial steps followed 

- As per the tutorial, downloaded the starter project 
- Opened the project and it had three folders Assets, Views, Classes

There are main 4 classes in the project

- MainViewController 
- CenterViewController 
- LeftPanelViewController 
- RightPanelViewController 

The project seems to be using the View Controller Containment concept introduced in the iOS 5.0.

The main Idea behind the implementation is: 

- The center view controller is the applications main view controller. To the main view controller, the view of the center view controller is added. 
- Whenever the left menu view to be shown, the LeftPanelViewController instance is created and its view is added on to the MainViewController and added as a child view controller to the main view controller. 
- The center view controller is now given a shadow to give a cool effect. 
- When the animation to be performed. The left panel view is sent to back and the Central view controller is animated to the right direction. 


Thats all! 

The concept is pretty much same as implemented in one of my app. But the header bar was common to entire project as the project had many number of view controllers. 

the project with a screenshot is like below. 



References:

Cordova and WebRTC - an attempt to use the PhoneRTC plugin from OnSIP.

To create a hybrid native iOS WebRTC app, below are the items required

- Mac OSX 
- Cordova 
- ios-deploy (optional) 


cordova was installed in the machine already, so did not have to do that again. 

The cordova plugin includes WebRTC libraries for iOS, and SIP.js is a custom media handler to use the iOS WebRTC libraries, and a cordova build script to build and run the project on devices. 

Below are the steps to be followed: 

1. create a cordova project using cordova create Cordova-WebRTC 
2. now add the iOS platform by running the below command inside  the project directory 
cd Cordova-WebRTC 
cordova platform add iOS 

Add the OnSIP cordova plugin 
Below command adds the PhoneRTC WebRTC library to the Cordova project 

cordova plugin add http://github.com/onsip/onsip-cordova.git 

To run the project just need to follow the regular procedure 

cordova run ios

Since there is an inherent problem in running from the command line, used to run from the 
Xcode project. Based on the instructions, Set the architecture only to armv7. However, 
running the project seems to be giving the error saying the architecture not found for certain 
object files during link time. Below are the error spitted out by the Xcode. 


  "_OBJC_CLASS_$_RTCICECandidate", referenced from:
      objc-class-ref in PhoneRTCDelegate.o

  "_OBJC_CLASS_$_RTCSessionDescription", referenced from:
      objc-class-ref in PhoneRTCDelegate.o


  "_OBJC_CLASS_$_RTCPeerConnectionFactory", referenced from:
      objc-class-ref in PhoneRTCDelegate.o


  "_OBJC_CLASS_$_RTCVideoCapturer", referenced from:
      objc-class-ref in PhoneRTCDelegate.o


  "_OBJC_CLASS_$_RTCPair", referenced from:
      objc-class-ref in PhoneRTCDelegate.o


  "_OBJC_CLASS_$_RTCMediaConstraints", referenced from:
      objc-class-ref in PhoneRTCDelegate.o


  "_OBJC_CLASS_$_RTCEAGLVideoView", referenced from:
      objc-class-ref in PhoneRTCPlugin.o


  "_OBJC_CLASS_$_RTCICEServer", referenced from:
      objc-class-ref in PhoneRTCPlugin.o


ld: symbol(s) not found for architecture armv7


clang: error: linker command failed with exit code 1 (use -v to see invocation)

To continue investigating on this.


references:

Friday, July 17, 2015

Cordova Application configuration File - an overview

The global configuration file has the name config.xml. This is a file arranged according to the W3C widget specification. 

The main element is widget. The widget element has id parameter which can be reverse DNS name. The version number here tells the display version name. Application can also have android-versioncode, iOS-CFBundleVersion attributes to specify the platform specific secondary version codes. 

The description element of the xml specifies the meta data about the app which appears in the app store list. The optional content element tells the starting page of the application. 

access element define the set of external domains app is allowed to communicate with. 

The preference tag sets various options as pairs of key value attributes. Many preferences are platform specific and the key case is case sensitive. 

The other few Preferences to note are:

FullScreen, 
DisallowOverScroll
BackgroundColor
HideKeyboardFromAccessoryBar
Orientation

Feature Element : IF CLI is used to build applications, the plugin command to be used for enabling device APIs. This does not modify the top level config.xml. Due to this reason, the fearture element does not apply to the work flow. IF an application work directly in an SDK and using platform specific config.xml, developer need to use feature tag to enable device level APIs and external plugins. 

When CLI is used to build applications, it sometimes becomes necessary to specify preferences or other elements specific to a particular platform. 


References:

Wednesday, July 15, 2015

Downloading and Playing around with Coredova

Based on the instructions given at the web site, it is better to install the coredova CLI from the npm rather than downloading this .zip version.  
Coredova CLI is used for creating and deploying Applications. 

Before Installing CLI tools, the native Platforms SDK needs to be installed. The cordova CLI is distributed in npm form readily available to install it. It is not necessary to compile it from source. 

The below are the main steps involved in installing the CLI

1. node.js installation. since the CLI installation is using the npm command, the node.js needs to be installed. This can be installed from the link given in the reference section. node.js is a pkg ed MAC application and once after installing below message was shown 

Node was installed at
   /usr/local/bin/node
npm was installed at
   /usr/local/bin/npm
Make sure that /usr/local/bin is in your $PATH.

After it was installed, the Terminal was able to successfully find it because npm was showing the options listed. 

The installation command for corrodva is simple and it is  sudo npm install -g cordova

it gave below few details upon running the above command. 
npm WARN engine cordova-js@4.0.0: wanted: {"node":"~0.10.x"} (current: {"node":"0.12.7","npm":"2.11.3"})
npm WARN engine npm@1.3.4: wanted: {"node":">=0.6","npm":"1"} (current: {"node":"0.12.7","npm":"2.11.3"})
npm WARN engine xmlbuilder@2.2.1: wanted: {"node":"0.8.x || 0.10.x"} (current: {"node":"0.12.7","npm":"2.11.3"})
npm WARN installMany normalize-package-data was bundled with npm@1.3.4, but bundled package wasn't found in unpacked tree
/usr/local/bin/cordova -> /usr/local/lib/node_modules/cordova/bin/cordova
cordova@5.1.1 /usr/local/lib/node_modules/cordova
├── underscore@1.7.0
├── q@1.0.1
├── nopt@3.0.1 (abbrev@1.0.7)
└── cordova-lib@5.1.1 (valid-identifier@0.0.1, osenv@0.1.0, properties-parser@0.2.3, bplist-parser@0.0.6, mime@1.2.11, unorm@1.3.3, semver@2.1.0, shelljs@0.3.0, dep-graph@1.1.0, rc@0.5.2, xcode@0.6.7, through2@0.6.3, npmconf@0.1.16, elementtree@0.1.6, cordova-app-hello-world@3.9.0, glob@4.0.6, d8@0.4.4, request@2.47.0, plist@1.1.0, cordova-registry-mapper@1.1.8, npm@1.3.4, init-package-json@1.7.0, tar@1.0.2, cordova-js@4.0.0)


after the npm is installed, in order to access the coredova using the sudo command as it get installed in to the restricted directory. 

Below is the command that can be executed to create a sample hello world project 

sudo  cordova create hello com.example.hello HelloWorld

the first argument hello specifies the directory to be generated for the project. the www subdirectory hosts the applications home page along with various resources under css, js and img folders. the config.xml contains the important meta data needed to generate and distribute the application. 

To add Platforms to the project, below command needs to run (this needs to be run under the project folder that is created) 

$ sudo cordova platform add ios 
npm http GET https://registry.npmjs.org/cordova-ios
npm http 200 https://registry.npmjs.org/cordova-ios
npm http GET https://registry.npmjs.org/cordova-ios
npm http 200 https://registry.npmjs.org/cordova-ios
npm http GET https://registry.npmjs.org/cordova-ios/-/cordova-ios-3.8.0.tgz
npm http 200 https://registry.npmjs.org/cordova-ios/-/cordova-ios-3.8.0.tgz
Adding ios project...
iOS project created with cordova-ios@3.8.0
Discovered plugin "cordova-plugin-whitelist" in config.xml. Installing to the project
Fetching plugin "cordova-plugin-whitelist@1" via npm
npm http GET https://registry.npmjs.org/cordova-plugin-whitelist
npm http 200 https://registry.npmjs.org/cordova-plugin-whitelist
npm http GET https://registry.npmjs.org/cordova-plugin-whitelist/-/cordova-plugin-whitelist-1.0.0.tgz
npm http 200 https://registry.npmjs.org/cordova-plugin-whitelist/-/cordova-plugin-whitelist-1.0.0.tgz
Installing "cordova-plugin-whitelist" for ios

to build the application, just need to do run this  sudo cordova build 

This creates the app file. 

References:

What is Apache Coredova - The Basics



Apache Coredova is a platform to build native mobile applications using HTML, CSS, and Javascript. This was formerly called as Phone Gap platform. Apache Cordova is basically a set of device APIst that allow a mobile developer to access native device function such as the camera or accelerometer from javascript. Combined with UI framework such as JQuery Mobile or Dojo mobile or Sensa Touch, this allows a smartphone app to be developed with just HTML, CSS and Javascript. 

Because of the Javascript APIs are consistent across multiple device platforms and built on web standards, the app should be portable to other device platforms with minimal to no changes. 

The cordova platform currently is available to iOS, Android, Blackberry, Windows Phone, Palm WebOS, Bada and Symbian. A developer can also write own plugins with Coredova There is also a registry of third party plugins available. 

references:

Tuesday, July 14, 2015

Building WebRTC framework for iOS


The prerequisite software included below two 

- Depot tools 
- Git SCM 

Downloaded the Depot tools from git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

Now set the path to the Depot tools like this export PATH=`pwd`/depot_tools:"$PATH" 

Thats all is required for WebRTC dependencies tool installation 

Now as a second step in the main installation step after the pre-requisite software installation, need to set the required OS to iOS. This can be done by export GYP_DEFINES="OS=ios" 

Now the source code can be fetched using the command fetch webrtc_ios

This will fetch a regular WebRTC checkout with the iOS-specific parts added. The same checkout can be used for both Mac and iOS development, depending on the OS we set in the GYP_DEFINES 

To compile the code below are to be done 

GYP is used to generate the build instructions for ninja from the relevant .gyp files. Ninja is used to compile the source using the previously generated instructions. In order to configure GYP to generate the build files for iOS devices, certain environment variables to be set. 

export GYP_CROSSCOMPILE=1
export GYP_DEFINES=“OS=ios target_arch=arm”
export GYP_GENERATOR_FLAGS=“output_dir=out_ios”
export GYP_GENERATOR=ninja

This actually generated the configuration files for ninja. also can see that out_ios directory is created that contains various complile output folders debug release etc.  

Now it can be seen that the bundle id of the .app file is by default com.google.WebRTCDemo. 
To change this, we need to edit it manually and that can be done via changing the above to whatever required in /src/chromium/src/third_party/libjingle/source/talk/examples/objc/AppRTCDemo/ios/Info.plist 

Since the bundle id is changed, we need to also change the code signing identity. This can be changed in 

No to compile the code, we need to execute the command  ninja -C out_ios/Debug-iphoneos AppRTCDemo  

depending on which output directory is given in the GYP_GENERATOR_FLAGS, one need to give the path accordingly in the compile command. 

The build command generates the .app file. inorder to load that on to the device, just drag and drop on to the iTunes application. If the installation fails, it mostly due to the fact that the code signing is not correct. Below command can be used to repackage it 


 /usr/bin/xcrun -sdk iphoneos PackageApplication -v "AppRTCDemo.app" -o "/Users/muser.r/Desktop/per/KB/iOS/WebRTC/src/out_ios64/Release-iphoneos/AppRTCDemo.ipa" --sign "iPhone Distribution: company, Inc." --embed "/Users/muser.r/RR/Projects/certs/CCADist.mobileprovision"


References: