Tuesday, 12 June 2018

AWS service limits asked in "AWS Certified Solutions Architect - Associate" and "AWS Certified Developer - Associate" certifications

Background

I just cleared my "AWS Certified Developer - Associate" certification exam yesterday with 90%. I have already cleared "AWS Certified Solutions Architect - Associate" exam 6 months back with 89%. You can see my badges below-
While preparing I realized that there are some questions based on service limits in AWS. These can be straightforward questions or they can be slightly twisted. Either case knowing service limits help out a lot. So I am going to summarize most of them which I feel important from certification perspective.




NOTE: AWS service limits can change anytime. So it is best to refer the FAQ sections of corresponding services to confirm. Following limits are as of June 2018.

AWS service limits & constraints

Following are AWS services and their corresponding limits. There would be more limits and constraints to each service. I am simply trying to summarise based on my exam preparation, test quizzes, and actual exam experience. Please let me know in comments if these limits are changed and I can update accordingly. Thanks.

Consolidated billing


AWS S3

  • By default, customers can provision up to 100 buckets per AWS account. However, you can increase your Amazon S3 bucket limit by visiting AWS Service Limits.
  • The bucket name can be between 3 and 63 characters long and can contain only lower-case characters, numbers, periods, and dashes.
  • Bucket names must not be formatted as an IP address (for example, 192.168.5.4).
  • For more details refer - https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
  • AWS S3 offers unlimited storage
  • Each object on S3, however, can be 0 bytes to 5TB.
  • The largest object that can be uploaded in a single PUT is 5GB
  • For objects larger than 100 megabytes, customers should consider using the Multipart Upload capability.
  • For further details refer - https://aws.amazon.com/s3/faqs/

Glacier

  • There is no maximum limit to the total amount of data that can be stored in Amazon Glacier. 
  • Individual archives are limited to a maximum size of 40 terabytes.
  • For more details refer - https://aws.amazon.com/glacier/faqs/

Redshift


AWS EC2

VPC

Route 53



Cloud watch

Cloud formation

Lambda

Dynamo DB

  • There is an initial limit of 256 tables per region. You can raise a request to increase this limit.
  • You can define a maximum of 5 local secondary indexes and 5 global secondary indexes per table(hard limit) - total 10 secondary indexes
  • The maximum size of item collection is 10GB
  • The minimum amount of reserved capacity that can be bought - 100
  • The maximum item size in DynamoDB is 400 KB, which includes both attribute name binary length (UTF-8 length) and attribute value lengths (again binary length). The attribute name counts towards the size limit. No limit on the number of items.
  • For more details refer - https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html
  • A BatchGetItem single operation can retrieve up to 16 MB of data, which can contain as many as 100 items
  • For more details refer - https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html
  • A single Scan operation will read up to the maximum number of items set (if using the Limit parameter) or a maximum of 1 MB of data and then apply any filtering to the results using FilterExpression.
  • For more details refer - https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html

SQS

  • You can create any number of message queues.
  • Max configuration: 14 days retention and 12 hours visibility timeout
  • Default configuration: 4 days retention  and 30 seconds visibility timeout
  • A single request can have up to 1 to 10 messages up to a maximum payload of 256KB.
  • Each 64 kb chunk payload is billed as 1 request. So a single API call with 256kb payload will be billed as 4 requests.
  • To configure the maximum message size, use the console or the SetQueueAttributes method to set the MaximumMessageSize attribute. This attribute specifies the limit on bytes that an Amazon SQS message can contain. Set this limit to a value between 1,024 bytes (1 KB), and 262,144 bytes (256 KB).
  • For more details refer - https://aws.amazon.com/sqs/faqs/

SNS

  • By default, SNS offers 10 million subscriptions per topic and 100,000 topics per account.  To request a higher limit, please contact Support.
  • Topic names are limited to 256 characters.
  • SNS subscription confirmation time period is 3 days

SWF



Again as mentioned before this is obviously not an exhaustive list but merely a summary of what I thought could be best to revise before going to the associate exams. Let me know if you think something else needs to be added here for the benefit of everyone.


Since you have taken time to go through the limits here is a bonus question for you :)

Question: You receive a call from a potential client who explains that one of the many services they offer is a website running on a t2.micro EC2 instance where users can submit requests for customized e-cards to be sent to their friends and family. The e-card website administrator was on a cruise and was shocked when he returned to the office in mid-January to find hundreds of angry emails complaining that customers' loved ones had not received their Christmas cards. He also had several emails from CloudWatch alerting him that the SQS queue for the e-card application had grown to over 500 messages on December 25th. You investigate and find that the problem was caused by a crashed EC2 instance which serves as an application server. What do you advise your client to do first? Choose the correct answer from the options below

Options:
  1. Use an autoscaling group to create as many application servers as needed to access all of the Christmas card SQS messages.
  2. Reboot the application server immediately so that it begins processing the Christmas cards SQS messages.
  3. Redeploy the application server as larger instance type so that it processed the  Christmas cards SQS faster.
  4. Send an apology to the customer notifying them that their cards will not be delivered.

Answer:
4. Send an apology to the customer notifying them that their cards will not be delivered.

Explanation:
Since 500 message count was as of December 25th and e-card website administrator returned mid-Jan the difference is more than 14 days which is the maximum retention period for SQS messages.

To be honest I had select option 1 in my 1st attempt :)


Friday, 25 May 2018

Understanding difference between Cognito User Pool vs Identity Pool

Background

In one of the previous post, we saw how to setup Cognito Identity Pool for unauthenticated or authenticated access to AWS resources like S3. Cognito identity pool is used to federate users into AWS so that they can call AWS services. In this post, we are going to see what is the difference between Cognito user wool and identity pool.


Amazon Cognito User Pools

As per AWS documentation,

A user pool is a user directory in Amazon Cognito. With a user pool, your users can sign in to your web or mobile app through Amazon Cognito. Your users can also sign in through social identity providers like Facebook or Amazon, and through SAML identity providers. Whether your users sign-in directly or through a third party, all members of the user pool have a directory profile that you can access through an SDK.

User pools provide:


  • Sign-up and sign-in services.
  • A built-in, customizable web UI to sign in users.
  • Social sign-in with Facebook, Google, and Login with Amazon, as well as sign-in with SAML identity providers from your user pool.
  • User directory management and user profiles.
  • Security features such as multi-factor authentication (MFA), checks for compromised credentials, account takeover protection, and phone and email verification.
  • Customized workflows and user migration through AWS Lambda triggers.


Sourcehttps://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html

After successfully authenticating a user, Amazon Cognito issues JSON web tokens (JWT) that you can use to secure and authorize access to your own APIs, or exchange for AWS credentials.

Amazon Cognito Identity Pools (Federated Identities)


As per AWS documentation,

Amazon Cognito identity pools (federated identities) enable you to create unique identities for your users and federate them with identity providers. With an identity pool, you can obtain temporary, limited-privilege AWS credentials to access other AWS services.

Sourcehttps://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html

Understanding difference between Cognito User Pool vs Identity Pool

Above definitions can be very confusing, so let me simplify them for you.

Cognito user pool is nothing but your user management system backed by its own user directory. If you are building a new app or a website and you want to add authentication mechanism to sign in or sign up for your users you should use Cognito user pool. You can choose to have users sign in with an email address, phone number, username or preferred username plus their password. You can also use social identity providers for authentication and signing in or up for your app or website. Everything is under Cognito user pool umbrella. You can use their SDK provided to do this. Cognito user pool helps you maintain your user base details and their authentication. On successful authentication, it provides a JWT token that can be used to authenticate your custom server APIs as well.



Cognito identity pool is used when you need access to AWS services. It basically authenticates the user and if authentication is successful it will give you a temporary token that you can use to talk to AWS. For eg. let's say you want to upload a file to S3 then you can use this. I had written a post earlier to do just the same -
Now how do you authenticate users to get these temporary credentials is something you decide. You could authenticate against the Cognito user group you have already created or you can again use 3rd party authentication providers like -
  • Amazon
  • Google
  • Facebook etc
Authentication flow is as -



So to summarize if you want to build a user directory with sign-in / sign-up functionality Cognito user pool is the way to go and if you just want access to AWS services without worrying about maintaining user database of your own you can use Cognito identity pool.




Related Links

Thursday, 24 May 2018

How to check an active internet connection on iPhone/iOS

Background

There are various network calls that we may have to make from your device to server. Internet network connection may not always be available for review. So it is better if we can check if the network is reachable before making the API calls. In this post, we will see the same in Objective C.


How to check an active internet connection on iPhone/iOS

  • First, add SystemConfiguration framework to your project.
  • To do this double click on your project. This should open your project settings. Select your app target.



  • Now go to "Build Phases" Tab on the top
  • Now Expand "Link Binary With Libraries"
  • Now click on '+' icon and search for "SystemConfiguration"
  • You should see "SystemConfiguration.framework"
  • Select it and click Add
  • You should see it would be added under "Link Binary With Libraries"


  • You should also start seeing "Framework" group under project navigator -

  • Now add Tony Million's version of Reachability.h and Reachability.m to the project. You can find it here - https://github.com/tonymillion/Reachability
  • I have just created a new group called Reachability and added these file in it.


  • In the file where you want to make this change import Reachability 
    • #import "Reachability.h"
  • Now you can check if the internet is available with following code snippet -


    if ([[Reachability reachabilityForInternetConnection]currentReachabilityStatus]==NotReachable)
    {
        //connection unavailable
        NSLog(@"Connection is not available");
    }
    else
    {
        //connection available
         NSLog(@"Connection is available");
    }



NOTE#import <SystemConfiguration/SystemConfiguration.h> is inside Reachability.h. You do not have to explicitly import it anywhere. Just add it to the framework.




Related Links


Tuesday, 22 May 2018

How to upload files to S3 from iOS app written in Objective C using AWS Cognito identity pool

Background

This post assumes you have setup Cognito identity pool as explained in the previous post -
If not, then please refer the previous post and set that up. Before starting with using this you should have -
  1. Identity pool ID
  2. AWS region where pool and S3 bucket reside
  3. S3 bucket name
We will use above in configuration and implementation that follows.

How to upload files to S3 from iOS app written in Objective C using AWS Cognito identity pool

  • First, go to your pod file and update following dependencies -

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'


target 'TestApp' do
  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!
  # Pods for TestApp


pod 'AWSMobileClient', '~> 2.6.18'  # For AWSMobileClient
pod 'AWSS3', '~> 2.6.18'            # For file transfers
pod 'AWSCognito', '~> 2.6.18'       # For data sync

end

  • Next run "Run pod install --repo-update" from the command line
  • Once you have the dependencies installed we can now write Objective C code to upload a file to S3.


//
//  FileUploader.m
//  TestApp
//
//  Created by Aniket on 22/05/18.
//


#import <Foundation/Foundation.h>


#import "FileUploader.h"
#import <AWSS3/AWSS3.h>
#import <AWSCore/AWSCore.h>




@implementation FileUploader


static AWSS3TransferManager *transferManager;


+ (void) initialize {
    
    if (self == [FileUploader class]) {
        AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:@"us-east-1:f847843f-0162-43c2-b73f-efdc7c69cce2"];
        AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
        [AWSS3TransferManager registerS3TransferManagerWithConfiguration:[[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider] forKey:s3TransferManagerKey];


        AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
                                        
        transferManager = [AWSS3TransferManager S3TransferManagerForKey:s3TransferManagerKey];
    }
    
}


+ (void)uploadFile
{
    
    
    NSURL *uploadingFileURL = [NSURL fileURLWithPath: @"PATH_TO_FILE";
    AWSS3TransferManagerUploadRequest *uploadRequest = [AWSS3TransferManagerUploadRequest new];
    
    
    uploadRequest.bucket = s3Bucket;
    int timestamp = [[NSDate date] timeIntervalSince1970];
    uploadRequest.key = [NSString stringWithFormat:@"%@-%d%@",@"testfile",timestamp,@".txt"];
    uploadRequest.body = uploadingFileURL;
    
    [[transferManager upload:uploadRequest] continueWithExecutor:[AWSExecutor mainThreadExecutor]
                                                       withBlock:^id(AWSTask *task) {
                                                           if (task.error) {
                                                               if ([task.error.domain isEqualToString:AWSS3TransferManagerErrorDomain]) {
                                                                   switch (task.error.code) {
                                                                       case AWSS3TransferManagerErrorCancelled:
                                                                       case AWSS3TransferManagerErrorPaused:
                                                                           break;
                                                                           
                                                                       default:
                                                                           NSLog(@"Error uploading file to S3: %@", task.error);
                                                                           break;
                                                                   }
                                                               } else {
                                                                   // Unknown error.
                                                                   NSLog(@"Error uploading file to S3: %@", task.error);
                                                               }
                                                           }
                                                           
                                                           if (task.result) {
                                                               AWSS3TransferManagerUploadOutput *uploadOutput = task.result;
                                                               // The file uploaded successfully.
                                                               NSLog(@"uploading file to S3 was successful: %@", uploadOutput);
                                                           }
                                                           return nil;
                                                       }];
    
}
@end


In above code replace the identity pool id and region as per your configuration settings. This is Objective C code, if you want to see Swift or Android - Java please refer https://docs.aws.amazon.com/aws-mobile/latest/developerguide/how-to-integrate-an-existing-bucket.html


Related Links

How to setup Cognito Identity Pool for unauthenticated or authenticated access to AWS resources like S3

Background

Many time when you are creating application be it mobile or web you have to provide an authentication mechanism for users to sign in before they can use your apps or websites features. AWS Cognito service does the same thing. 
  • Amazon Cognito makes it easy for you to have users sign up and sign in to your apps, federate identities from social identity providers, secure access to AWS resources and synchronize data across multiple devices, platforms, and applications.
You can do 3 things using this service -
  1. With Cognito Your User Pools, you can easily and securely add sign-up and sign-in functionality to your mobile and web apps with a fully-managed service that scales to support hundreds of millions of users.
  2. With Cognito Federated Identities, your users can sign-in through social identity providers such as Facebook and Twitter, or through your own identity solution, and you can control access to AWS resources from your app.        
  3. With Cognito Sync, your app can save user data, such as preferences and game state, and sync that data to make your users' experiences consistent across their devices and when they are disconnected.             
NOTE: AWS Cognito is a region-specific service so you have to select a region and make sure this service is available in that region. For this post, I am going to use us-east-1(N.Virginia).

Also in this post, I am going to show how we can create a federated identity pool which can be used to authenticate and access AWS resources. Though I am going to limit this post to setting-up the identity pool and corresponding AWS changes we will see how we can use this to upload sample files to Amazon S3 bucket.


How to setup Cognito Identity Pool for unauthenticated or authenticated access to AWS resources

  • Sign into AWS console and go to Cognito service.


  • Now click on "Manage Federated Identities"
  • Provide a name for your identity pool. Eg. athakur_test
  • If you want unauthenticated users to use this pool for authenticating and accessing AWS resources select "". I am going to select this since finally, I want to use this pool to upload files to S3. 

NOTE: Amazon Cognito can support unauthenticated identities by providing a unique identifier and AWS credentials for users who do not authenticate with an identity provider. If your application allows customers to use the application without logging in, you can enable access to unauthenticated identities.

  • If you want to provide access to authenticated users only then use one of the Authentication providers like Facebook, Amazon, Google etc
  • Click on "create pool".

  • Next screen you should see the roles that AWS will create for you. You can select "View details" to see the role details. 
  • Finally, click "Allow"
NOTE1: Assigning a role to your application end users helps you restrict access to your AWS resources. Amazon Cognito integrates with Identity and Access Management (IAM) and lets you select specific roles for both your authenticated and unauthenticated identities. 

NOTE2: By default, Amazon Cognito creates a new role with limited permissions - end users only have access to Cognito Sync and Mobile Analytics. You can modify the roles if your application needs access to other AWS resources, such as S3 or DynamoDB.

You can see click on video details to see this default policy document -

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "mobileanalytics:PutEvents",
        "cognito-sync:*"
      ],
      "Resource": [
        "*"
      ]
    }
  ]

}


We will see how to attach additional permissions to this role later.



As you can see 2 roles are created - one for the authenticated user and other for the unauthenticated user -
  1. Cognito_athakur_testAuth_Role
  2. Cognito_athakur_testUnauth_Role
On the next page, you should see some sample code - one for getting credentials and other for Cognito sync -


Get AWS credentials :

// Initialize the Amazon Cognito credentials provider
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
    getApplicationContext(),
    "us-east-1:f847843f-0162-43c2-b73f-efdc7c69cce2", // Identity pool ID
    Regions.US_EAST_1 // Region
);


Store User Data:

// Initialize the Cognito Sync client
CognitoSyncManager syncClient = new CognitoSyncManager(
   getApplicationContext(),
   Regions.US_EAST_1, // Region
   credentialsProvider);

// Create a record in a dataset and synchronize with the server
Dataset dataset = syncClient.openOrCreateDataset("myDataset");
dataset.put("myKey", "myValue");
dataset.synchronize(new DefaultSyncCallback() {
    @Override
    public void onSuccess(Dataset dataset, List newRecords) {
  //Your handler code here
    }
});


  • Note down the Identity pool id and region . In my case identity pool id is "us-east-1:f847843f-0162-43c2-b73f-efdc7c69cce2" and region is us-east-1. We will need it in subsequent setup.
The last part that is remaining now is to add additional permissions to our new role so that Cognito pool users can access other required AWS services - in this case since we need to upload files to S3 we just need S3 put access.

NOTE: Make sure Cognito identity pool should be created in same region as S3 bucket.

So go to IAM and go to roles and select it. Now click add inline policy and add following JSON policy -

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1526901559336",
            "Action": [
                "s3:PutObject"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::<BUCKET_NAME>/*"
        }
    ]
}


You have to replace <BUCKET_NAME> with your actual S3 bucket name. Always make IAM policies as stricter as possible. In this case, we are just giving put object permission on the desired S3 bucket only.

NOTE: This was for upload to S3 bucket but you can provide access to other services that you desire. If you need to create the policy you can use policy generator AWS provides - https://awspolicygen.s3.amazonaws.com/policygen.html


At this point, your Cognito service is all set up for implementation. In the next post, we will see how we can use this to implement it in our mobile or web application.

Related Links

Saturday, 19 May 2018

How to get the current time in milliseconds

Background

In many scenarios, we need the current time in milliseconds. In this post, we will see various methods to get the time in milliseconds since the UNIX epoch (January 1, 1970 00:00:00 UTC) in various programming languages.

How to get the current time in milliseconds

Following are ways you can get  current time in milliseconds for various programming languages -

  • ActionScript    
    • (new Date()).time
  • C++ 
    • std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()
  • C#.NET  
    • DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
  • Clojure 
    • (System/currentTimeMillis)
  • Excel / Google Sheets*  
    • = (NOW() - CELL_WITH_TIMEZONE_OFFSET_IN_HOURS/24 - DATE(1970,1,1)) * 86400000
  • Go / Golang 
    • time.Now().UnixNano() / 1000000
  • Hive*   
    • unix_timestamp() * 1000
  • Java / Groovy / Kotlin  
    • System.currentTimeMillis()
  • Javascript  
    • new Date().getTime()
  • MySQL*  
    • UNIX_TIMESTAMP() * 1000
  • Objective-C 
    • (long long)([[NSDate date] timeIntervalSince1970] * 1000.0)
  • OCaml   
    • (1000.0 *. Unix.gettimeofday ())
  • Oracle PL/SQL* 
    •  SELECT (SYSDATE - TO_DATE('01-01-1970 00:00:00', 'DD-MM-YYYY HH24:MI:SS')) * 24 * 60 * 60 * 1000 FROM DUAL
  • Perl    
    • use Time::HiRes qw(gettimeofday); print gettimeofday;
  • PHP 
    • round(microtime(true) * 1000)
  • PostgreSQL  
    • extract(epoch FROM now()) * 1000Python  int(round(time.time() * 1000))
  • Qt  
    • QDateTime::currentMSecsSinceEpoch()
  • R*  
    • as.numeric(Sys.time()) * 1000
  • Ruby    
    • (Time.now.to_f * 1000).floor
  • Scala   
    • val timestamp: Long = System.currentTimeMillis
  • SQL Server  
    • DATEDIFF(ms, '1970-01-01 00:00:00', GETUTCDATE())
  • SQLite* 
    • STRFTIME('%s', 'now') * 1000
  • Swift*  
    • let currentTime = NSDate().timeIntervalSince1970 * 1000
  • VBScript / ASP  
    • offsetInMillis = 60000 * GetTimeZoneOffset()
  • WScript.Echo 
    • DateDiff("s", "01/01/1970 00:00:00", Now()) * 1000 - offsetInMillis + Timer * 1000 mod 1000



I recently investigated this as I wanted MicrosoftDateFormat in objective C. We can do this as follows -

  • NSString *date = [NSString stringWithFormat:@"/Date(%lld)/",(long long)([currentTag.firstSeenTime timeIntervalSince1970] * 1000.0)];


NOTE: timeIntervalSince1970 gives you the number of seconds whereas Newtonsoft.Json library (C#) gives it in milliseconds so you need multiple by 1000.0 to get milliseconds.


Related Links



Friday, 11 May 2018

How to enable touch to click on your Mac

Background

If you are a Mac user then you must be familiar with the peculiar trackpad gestures and usage Mac offers. Personally, I feel touch to click is a much better option then physically pressing the trackpad. In this post, I will show you how to do the same. I am using MacBook Pro running Sierra (10.13.4).

How to enable touch to click on your Mac

  • Go to "Preferences" and select "Trackpad"
  • Under "Point and Click" select "Tap to Click"




  • Notice how "Click with two fingers" is also changed to "Click or tab with two finders" for secondary click.
  • You can use this checkbox to enable or disable "Tap to click"

How to enable touch to click on your Mac with command line

You can do the same above setting with the command line. Execute following commands in your Terminal.

  • sudo defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true
  • sudo defaults -currentHost write NSGlobalDomain com.apple.mouse.tapBehavior -int 1
  • sudo defaults write NSGlobalDomain com.apple.mouse.tapBehavior -int 1

NOTE: You will need to reboot your system for changes to take effect.

Similarly, to disable you can do

  • sudo defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool false
  • sudo defaults -currentHost write NSGlobalDomain com.apple.mouse.tapBehavior -int 0
  • sudo defaults write NSGlobalDomain com.apple.mouse.tapBehavior -int 0
Again reboot your machine to take effect.



Related Links




Sunday, 29 April 2018

Objective C programming in Windows with GNUStep

Background

Objective C is the programming language that is used for iOS development. To learn iOS development you need a Mac since you need Xcode to develop it. However, there is no such limitation for learning Objective C. So in this post I am going to show you how to compile and run Objective C programs on windows.


Installing GNUstep on Windows

GNUstep is a free development environment that is based on MinGW and MSYS. It has set of tools and compilers (including GCC) that lets you compile objective c programs on windows. To completely install GNUstep you need to install 3 setup files -

  1. GNUstep MSYS System
  2. GNUstep Core
  3. GNUstep Devel
 You can download and install the same from http://www.gnustep.org/windows/installer.html.

Installation : For the full environment for compiling and running GNUstep. Install the following packages in order. First install the gnustep-msys-system package, which contains all the packages required to run GNUstep (shell, graphics libraries, etc). Then install gnustep-core, which contains the core GNUstep libraries. If you want to compile and develop your own GNUstep applications, also install the gnustep-devel package.

The default installation of GNUstep would go to
  • C:\GNUstep

You can also use ProjectCenter which is a GUI extension of GNUStep.

Hello World - Objective C

Now create a new file called helloworld.m and add following content to it -

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   NSLog (@"Hello World!");

   [pool drain];
   return 0;
}

I have saved it at location -
  • C:\GNUstep\home\<username>\Development\helloworld.m

Once you have saved it open the GNUstep shell. For me, it is at the following location -
  • C:\Users\<username>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\GNUstep
Once you have opened it navigate to the directory you have helloworld.m file. Then run following command -

 gcc -o helloworld helloworld.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -fconstant-string-class=NSConstantString


This should create a helloworld.exe file in the same directory. Now run ./helloworld.exe and it should print "Hello World!". This is captured in the screenshot below -







Related Links

Friday, 13 April 2018

Understanding Delegates in C#

Background

Delegates are a very important part of C# programming language. A delegate in C# holds a reference to a method. Think of it as a pointer to the method. This reference or pointer can change at runtime. A delegate can also reference multiple methods and can invoke them all together. Think about event listeners for a Button in UI. You can add as many event listeners as you want and when the button is clicked all methods get the callback - much like the Observer Design Pattern. In this post well see how delegates work with an example.

Understanding Delegates in C#

Syntac of a delegate declaration is -
  • delegate <return type> <delegate-name> <parameter list>
For eg. consider -
  • public delegate void PriceChangeDelegate(int oldPrice, int newPrice); 

Now this delegate can point to any method that has return type void and parameters list (int, int). We will see a demo in a while. But the declaration syntax should be clear now.

So for this demo idea is to define an Item Object and with an attribute call price and we want to provide our own callback to receive updates whenever price of the item changes. We will do this using a delegate.

So let's first define our Item class -

namespace HelloWorld
{
    class Item
    {
        private int price;
        public PriceChangeDelegate PriceChanged;
        public int Price {
            get { return price; }
            set {
                if(value != 0)
                {
                    if(value != price)
                    {
                        PriceChanged(price, value);
                    }
                    price = value;
                }
            }
        }
    }
}



Notice how have created a private variable price (lower case by convention) and then a public property called Price (uppercase by convention) to encapsulate the price. Set method of this property is where our logic is. We are calling the delegate  PriceChanged when the old value price is different than current value. Also, notice how we have declared a public delegate member in class -
  • public PriceChangeDelegate PriceChanged;
 However, we have not yet declared our delegate type PriceChangeDelegate anywhere. Let's do that now -

namespace HelloWorld
{
    public delegate void PriceChangeDelegate(int oldPrice, int newPrice);
}


And there we go. Now our delegate instance can point to any methods of return type void and parameters (int, int) like we saw before. Now let's see all of this in action.


namespace HelloWorld
{
    class Program
    {
        public static void Main(string[] args)
        {
            Item item = new Item();
            item.PriceChanged = new PriceChangeDelegate(ItemPriceChangeCallback);
            item.Price = 100;
            Console.ReadLine();
        }
        public static void ItemPriceChangeCallback(int oldPrice, int newPrice) {
            Console.WriteLine("Item price changed from " + oldPrice + " to " + newPrice);
        }
    }
}


Here we are creating an instance of Item and setting a value for price to 100. Note the default value of primitive int is 0. So now when we set it to 100 we are essentially changing the price of the item. Also before that, we are assigning the delegate to the method we have locally called ItemPriceChangeCallback. So when items price will be changed ItemPriceChangeCallback will be called and our statement should get printed. Let's give it a try.




So that worked! Now like I said before a delegate can reference multiple methods as long as return type and paramters are same. Let's see how we can do that. Let's change our previous code a bit.


namespace HelloWorld
{
    class Program
    {
        public static void Main(string[] args)
        {
            Item item = new Item();
            item.PriceChanged += new PriceChangeDelegate(ItemPriceChangeCallback1);
            item.PriceChanged += new PriceChangeDelegate(ItemPriceChangeCallback2);
            item.Price = 100;
            Console.ReadLine();
        }
        public static void ItemPriceChangeCallback1(int oldPrice, int newPrice) {
            Console.WriteLine("ItemPriceChangeCallback1 :: Item price changed from " + oldPrice + " to " + newPrice);
        }
        public static void ItemPriceChangeCallback2(int oldPrice, int newPrice)
        {
            Console.WriteLine("ItemPriceChangeCallback2 : Item price changed from " + oldPrice + " to " + newPrice);
        }
    }
}


and the output is -


Notice our syntax for assigning delegate has changed. Instead of assigning we are adding it now -

  • item.PriceChanged += new PriceChangeDelegate(ItemPriceChangeCallback1);
  • item.PriceChanged += new PriceChangeDelegate(ItemPriceChangeCallback2);
instead of

  • item.PriceChanged = new PriceChangeDelegate(ItemPriceChangeCallback);

 We have defined two methods ItemPriceChangeCallback1 and ItemPriceChangeCallback2 to show this behavior. You can have as many as you wish as long as delegate contract in honoured - same return type and parameters type and number.

Also note you need not use new keyword again and again. C# compiler is intellegent enough to do this itself. You can simply do.

  • item.PriceChanged += ItemPriceChangeCallback1;
  • item.PriceChanged += ItemPriceChangeCallback2;
 It would give the same result.

Lastly you can remove all references by setting delegate as null -
  • item.PriceChanged = null;
 You would get a Null reference exception since are using delegate without instantiating our delegate and it is null by default. But this is not a desired behavior. To avoid this we can define our delegate as event. For this go back to our Item class and change -
  • public PriceChangeDelegate PriceChanged;
to
  • public event PriceChangeDelegate PriceChanged;
 and you can see that assigning null to PriceChanged is no longer possible.



 And that's all for delegates. Post your questions in comments below. Thanks.



Thursday, 5 April 2018

How to use a file to store all your logs in Xamrin Android App

Background

You can see the debug logs in the Device Log tab in Visual studio but you need to connect a USB to your android phone (not needed if you are using an emulator). However this is for realtime debugging and will not be useful to check logs that were present couple of hours back. In this post I will show you how you can log into a file in the android sd card so that you can refer it at any point in time to see what has happened.


How to use a file to store all your logs in Xamrin Android App

You can log to a file using following code snippet -

using System;
namespace Com.Osfg
{
    public class LogUtils
    {
        String logFilePath = null;

        public LogUtils()
        {
            String path = Android.OS.Environment.ExternalStorageDirectory.Path;
            logFilePath = System.IO.Path.Combine(path, "log.txt");
            if(!System.IO.File.Exists(logFilePath))
            {
                using (System.IO.StreamWriter writer = new System.IO.StreamWriter(logFilePath, true))
                {
                    writer.WriteLine("Starting logging at " + DateTime.Now.ToString());
                }
            }
        }

        public void Log(String message)
        {
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(logFilePath, true))
            {
                writer.WriteLine(DateTime.Now.ToString() + " : " + message);
            }
        }
    }
}

Let's uderstand whats happening here -

In the constructor we are getting the external storage directory and creating a file called "log.txt" there. We are checking if the file already exists and if it does not we create it. Now anyone who want to log to this file can simple create an instance of LogUtils and call Log method on it.

You can do this on OnCreate of your main activity. For me external storage file is - /storage/emulated/0 so my complete log file path is /storage/emulated/0/log.txt

Make sure you have provided appropriate permissions in the manifest file -

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


Related Links



Friday, 30 March 2018

Hello World Xamrin Android project tutorial

Background

Xamrin are set of tools built on .NET framework . It allows you to develop applications for Android, iOS and Windows using C# language and the .NET framework.In this post I am going to show you how to develop a native android application using xamrin.

Setup

For this tutorial you need to have Visual Studio with Xamrin components installed on your Windows operating system. You can get it from Visual Studio installer. Or from Visual Studio you can go to Tools -> Get Tools and Features.


 Hello World Xamrin Android project tutorial

Click on File -> New Project  and choose Blank App(Android)

 One you have created the project you should see following code structure -


 Let's go over some of the important files here -
  1. MainActivity.cs : This is your main launcher activity.
  2. Resources/layout/Main.axml : This is your launcher ctivity layout file
  3. Resources/values/String.xml : This is your string resource file.
Go to  Resources/layout/Main.axml and add a EditText and a Button to the Linear Layout that you have. You can do that from  Designer mode with just drag and drop.



Change the id of EditText and Button to "helloWorldeditText" and "ckickMeButton" respectively. So your source would look like -

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/helloWorldeditText"
        android:text="Hello World!" />
    <Button
        android:text="Click Me!"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/ckickMeButton" />
</LinearLayout>
Now go to MainActivity.cs and make following changes. We are basically going to implement a button and  change the text of EditText on the click of the button.
using Android.App;
using Android.Widget;
using Android.OS;

namespace AndroidDemo
{
    [Activity(Label = "AndroidDemo", MainLauncher = true)]
    public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);
            EditText helloWorldEditText = FindViewById<EditText>(Resource.Id.helloWorldeditText);
            Button clickButton = FindViewById<Button>(Resource.Id.ckickMeButton);
            helloWorldEditText.Text = "Hello World!";
            clickButton.Click += delegate { helloWorldEditText.Text = "Button Clicked!"; };
        }
    }
}



Notice the resource IDs we changed and use to reference it in the code. And that's it. Just deploy the code to an android device or an emulator and test our changes.





Related Links




Sunday, 18 March 2018

How To Set Up an HTTPS Service in IIS

Background

Windows provides Internet information service (IIS) to host your local applications on your windows machine. You need to enable IIS from "Turn Windows features on or off".



Once you have done that you can add an application to it and get started. I have created a youtube video to demo the same -



This video shows how to set up a simple website on IIS and also add https support. I am also going to show how to add https support part in this post.

How To Set Up an HTTPS Service in IIS

First, make sure you have self-signed certificate generated in your IIS manager. To do that go to "Server certificates" in your machine home node inside your IIS manager -


Next, double-click the "Server Certificates" section and make sure a self-signed certificate exists. 




If no certs exist for localhost go ahead and create one using "Create self-signed Certificate". 

Once you have the certificate go to Sites in the navigation panel on the left and click on Default website under sites.


Next, click on "Bindings" in the section on the right and add https binding. Make sure you select correct SSL certificate in the process that we create in previous steps.


Once you are done just click ok and you should have https binding set for your website.


Now you can open your website with https protocol.




Related Links

Sunday, 11 March 2018

AngularJS Routing Using UI-Router

Background

In the last post, we saw AngularJS Hello World example. In this post, we will see how we can create an angular JS app with routing using UI-Router module. If you have not read the previous post I would highly recommend you read that first.


 Setup

There is a small change in the file structure than our previous example. Create files as shown in the following screenshot -



Following are file details -
  • helloWorld.html : Our main HTML file. Starting page similar to the last example.
  • helloworld.module.js : Declares angular module and it's dependencies
  • helloWorld.controller.js : Controller for the module
  • helloworld.config.js : Config for the module.  
  • login.html : login page to route to
  • setting.html : setting page to route to
 Also make sure you install http-server module to host your angular app and test it -
  • npm install -g http-server


Then you can simply run in your project directory as -
  • http-server -o 
NOTE : -o option is to open browser.

AngularJS Routing Using UI-Router


Now let's see one by one content of each file. Let's start with  helloWorld.html -

<html>
    <head>
        <title>Hello World!</title>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
            <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
            <script type="text/javascript" src="helloworld.module.js"></script>
        <script type="text/javascript" src="helloWorld.controller.js"></script>
        <script type="text/javascript" src="helloworld.config.js"></script>
    </head>
    <body ng-app="helloWorldApp">
        <div ng-controller="helloWorldAppController" ng-init="init()">
                  <p>Enter Message here : <input type="text" ng-model="message"></p>
                   <p>Entered Message :  {{ message }}!</p>

                   <a href="/login">Login</a> <br/>
                   <a href="/setting">Setting</a>

                <div class="content-wrapper">
                    <ui-view></ui-view>
                </div>    
        </div>
    </body>
</html>


In this base HTML file we have just referenced other angular JS files that we need. An interesting thing to note here is the ui-view tag. This is where the injected code goes. But we will see that in a moment.


Let's see out module and controller files next -


helloworld.module.js

(function() {
    'use strict';
    console.log("In hello world module");
    angular.module('helloWorldApp', ['ui.router']);
})();


This code just declares your module as we did in last example. Only change is that it has an additional dependency on ui.router module. Note we have included a new script in helloWorld.html to get code for this module.


helloWorld.controller.js

(function(){
    'use strict';
    console.log("In hello world controller");
    angular.module("helloWorldApp").controller("helloWorldAppController", function($scope) {
        $scope.init = function() {
            console.log("Init method called");
            $scope.message = "Hello World!";
        }
    });

})();


This is a controller of the module we defined. This is again same as we did in last post. No new changes here.


Now let's see our new logic - helloworld.config.js


(function() {
    'use strict';
    console.log("In hello world config");
    angular.module('helloWorldApp').config([
        '$stateProvider',
        '$urlRouterProvider',
        function($stateProvider, $urlRouterProvider) {
            $stateProvider.state('login',{
                     url: "/login",
                     templateUrl: "login.html"
                })
            .state('settings',{
                    url: "/setting",
                    templateUrl: "setting.html"
            });
        }
    ]);
})();






 

This is actually the routing logic. For eg. if it encounters URL "/login" it will render page "login.html" that we have in same folder. Same for setting.html.


Finally, let's see out login.html and setting.html files -


login.html -


<h1>This is a login page!</h1>
<a href="/helloWorld.html">Back</a>



setting.html -


<h1>This is a login page!</h1>
<a href="/helloWorld.html">Back</a>


 Once you have all files in place just run http-server as follows -




And you should see following behavior - 


 






But wait what happened? I thought the code was supposed to be injected at tag ui-view.

This is because we do not actually use angular routing per say to change the state. Let's do some changes to see how we can do that. Change your login href as follows - 

<a href="" ng-click="replaceLoginPage()">Login</a>


and now add this method to the controller -


(function(){
    'use strict';
    console.log("In hello world controller");
    angular.module("helloWorldApp").controller("helloWorldAppController", function($scope, $state) {
        $scope.init = function() {
            console.log("Init method called");
            $scope.message = "Hello World!";
        }

        $scope.replaceLoginPage = function() {
            console.log("In replaceLoginPage");
            $state.go("login");
        }
    });

})();



And now it should replace ui-view tag.









Related Links



t> UA-39527780-1 back to top