Kotlin Multiplatform for sharing code between native Android and iOS app

Often we mobile developers get asked a question, “Can we share code between Android and iOS app?”. After all much of the business logic remains the same regardless of platform we build for. Mobile developers ends up implementing much of exact same logic on each platform. Not only logic but, tests around that code is also duplicated. It is also challenging to ensure both apps implemented exact same logic. After all, if different developers worked on the platform, chances are logic is different causing each app to behave differently.

In this post, I will go over Kotlin Multiplatform as a solution for this problem. I will explain how Kotlin Multiplatform could help us having “common” code in one place shared between the two native apps. One of the main objective is that common code should be native to each platform and should have first class citizen support.

Problem Statement:

As an example for this use case, let’s assume that we are trying to implement an Analytics Event Logging framework. To keep things simple, let’s say the event name and property should be same on both platforms. An Event is a “common” thing for each platform. (Note: the issue could have been that each platform may have named their Event and property different, “button_click” vs “ButtonClick” etc)

In this example we will build a Kotlin Multiplatform solution that contains the common code shared between in Android and iOS app.

Settings up Android Project:

Let’s being by setting up a new Android project. Go through the new project wizard in the Android Studio and create a new Android project called “KotlinMPLogging”. Once complete, you should be able to start the app and see the “Hello World!” screen.

1. Hello World

Switching to Kotlin 1.3:

At this point, let’s configure our project to use Kotlin 1.3, Let’s configure our IDE to use the Kotlin 1.3 plugin. To do so, go to the Settings, Cmd + , > Languages & Frameworks > Kotlin Updates and pick “Early Access Preview 1.3”

Screen Shot 2018-10-14 at 12.57.31 PM

Next up, let’s update the build.gradle, of the main Project and update the kotlin version (rc-80 is the latest RC version as of this writing)

ext.kotlin_version = '1.3.0-rc-80'

Your, IDE will error out as it will not able to obtain the pre-release version of kotlin. To fix this, we would need to add maven url in the build script.

maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }

We will add this for both buildscript as well as allprojects so our app module is able to get the right version of std lib.

After these changes are made, your build.gradle should look like this:

buildscript {
ext.kotlin_version = '1.3.0-rc-80'
repositories {
google()
jcenter()
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
}
}
view raw build.gradle hosted with ❤ by GitHub

We should also update the gradle wrapper to 4.10+ as Kotlin Native plugin requires the newer version. To do so update distrubtionUrl in gradle-wrapper.properties file

distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

 

 

At this point, you should be able to successfully build and run the Android project. Nothing has changed so far expect for using Kotlin 1.3.

Setting up the “Common” Kotlin Multiplatform module:

Now the interesting part. It’s time to build the Kotlin Multiplatform portion. This will be shared between different platforms (iOS and Android). To keep things simple, let’s create a folder named common in current project folder.

The folder will be structured in following way:

common/src/commonMain: All the common code will be here

common/src/androidMain: Android specific code would live here, for this example we won’t have anything here.

common/src/iosMain: iOS specific code would live here, for this example we won’t have anything here.

Time to create build.gradle for this module (it will be inside “common” folder we created above).

apply plugin: 'kotlin-multiplatform'
kotlin {
targets {
final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos") \
? presets.iosArm64 : presets.iosX64
fromPreset(iOSTarget, 'iOS') {
compilations.main.outputKinds('FRAMEWORK')
}
fromPreset(presets.jvm, 'android')
}
sourceSets {
commonMain.dependencies {
api 'org.jetbrains.kotlin:kotlin-stdlib-common'
}
androidMain.dependencies {
api 'org.jetbrains.kotlin:kotlin-stdlib'
}
}
}
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
compileClasspath
}
view raw build.gradle hosted with ❤ by GitHub

Here, we apply the ‘kotlin-multiplatform‘ plugin. Source set dependencies are defined here. e.g. we use kotlin-std-common in our common source set.

In the commonMain, start by creating the Event interface (commonMain/kotlin/com/manijshrestha/kotlinmplogging/analytics).

package com.manijshrestha.kotlinmplogging.analytics
interface Event {
fun eventName(): String
fun eventProperties(): Map<String, String>?
}
view raw Event.kt hosted with ❤ by GitHub

To limit the complexity in this example, let’s create a AnalyticsManager interface. Idea is that Event gets reported by AnalyticsManager. Each platform will implement its own Manager and use the Event from the common code.

package com.manijshrestha.kotlinmplogging.analytics
interface AnalyticsManager {
fun report(event: Event)
}

With this plumbing in place, we can now add real Event implementations. We will add 2 events.

ButtonClickEvent and ViewEvent 

package com.manijshrestha.kotlinmplogging.analytics
data class ButtonClickEvent(private val buttonName: String) : Event {
override fun eventName() = "Button_Clicked"
override fun eventProperties() = mapOf(
"button_name" to buttonName
)
}
package com.manijshrestha.kotlinmplogging.analytics
data class ViewEvent(private val pageName: String) : Event {
override fun eventName() = "Page_Viewed"
override fun eventProperties() = mapOf(
"page_name" to pageName
)
}
view raw ViewEvent.kt hosted with ❤ by GitHub

As you can see above, each of the class have event name defined, regardless of the platform (iOS or Android) these events will have same name. Also required parameters are defined in the class so each platform will need to provide those arguments.

We could do lot more here but to keep the scope of this post limited to common code, We will leave this here and move on to platform specific implementation.

Using Common in Android Project:

Now it’s time to utilize the common code in our Android project. To do so lets include the “common” module in settings.gradle file

include ':common'

Now, add “common” project as a dependency in our app’s build.gradle dependencies section.

implementation project(':common')

With above changes, we can now provide the implementation of the AnalyticsManager. We could implement it to send Fabric Answers event or Google Analytics or perhaps to any services that you may want to call. For now, we are going to log the event in logcat using android logger.

package com.manijshrestha.kotlinmplogging
import android.util.Log
import com.manijshrestha.kotlinmplogging.analytics.AnalyticsManager
import com.manijshrestha.kotlinmplogging.analytics.Event
class AndroidAnalyticsManager : AnalyticsManager {
override fun report(event: Event) {
Log.d("AAM", "Interaction ${event.eventName()} happened with property ${event.eventProperties()}")
}
}

To see it in action, we are going to update the activity layout to have three buttons. We will send separate event on each button click.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button android:id="@+id/red_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/red_button"
android:layout_margin="16dp"
android:textColor="#FF0000"
android:onClick="onButtonClick"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button android:id="@+id/green_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/green_button"
android:layout_margin="16dp"
android:textColor="#00FF00"
android:onClick="onButtonClick"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/red_button"/>
<Button android:id="@+id/blue_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/blue_button"
android:layout_margin="16dp"
android:textColor="#0000FF"
android:onClick="onButtonClick"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/green_button"/>
</android.support.constraint.ConstraintLayout>

Here is the Activity where we will implement the reporting of the event.

package com.manijshrestha.kotlinmplogging
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import com.manijshrestha.kotlinmplogging.analytics.ButtonClickEvent
import com.manijshrestha.kotlinmplogging.analytics.ViewEvent
class MainActivity : AppCompatActivity() {
private val analyticsManager = AndroidAnalyticsManager()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onResume() {
super.onResume()
analyticsManager.report(ViewEvent("Main Page"))
}
fun onButtonClick(view: View) {
when (view.id) {
R.id.red_button -> analyticsManager.report(ButtonClickEvent("Red"))
R.id.green_button -> analyticsManager.report(ButtonClickEvent("Green"))
R.id.blue_button -> analyticsManager.report(ButtonClickEvent("Blue"))
}
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

With these changes we can run the app and see it in action.

Screen Shot 2018-10-14 at 3.21.38 PM

Screen Shot 2018-10-14 at 3.22.04 PM

When the page is loaded, we are now reporting Page_Viewed event with the page name and as we tap on each button, we get Button_Clicked events reported (above, we can see Red and Green button click events).

With android side fully implemented, it is time to implement it in the iOS app.

Building common framework for iOS:

If you take a peek at the “common/build” folder, you can see that it generated the java class files for our Android app to consume. For iOS app we need to compile it as “framework“. Let’s get this by adding the following script in our build.gradle file of common module.

task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String mode = System.getenv('CONFIGURATION')?.toUpperCase() ?: 'DEBUG'
inputs.property "mode", mode
dependsOn kotlin.targets.iOS.compilations.main.linkTaskName("FRAMEWORK", mode)
from { kotlin.targets.iOS.compilations.main.getBinary("FRAMEWORK", mode).parentFile }
into frameworkDir
doLast {
new File(frameworkDir, 'gradlew').with {
text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n"
setExecutable(true)
}
}
}
tasks.build.dependsOn packForXCode
view raw build.gradle hosted with ❤ by GitHub

With following changes in place, run the ​’​build’ task.

Screen Shot 2018-10-14 at 3.30.34 PM

We should see the frameworks being generated for both release and debug.

Screen Shot 2018-10-14 at 3.31.29 PM

Setting up iOS project:

Go through the new project setup wizard on Xcode and create a single view application.

Now, add the framework that was build from above step in our project. To do this, go to General > Embedded Binaries +

Screen Shot 2018-10-14 at 4.31.59 PM

Also, add the Framework path by going into “Build Settings” Framework Search Paths:

Screen Shot 2018-10-14 at 4.36.50 PM.png

With these changes, you should be able to compile and run the app without any issues.

At this stage, we are going to create the IosAnalyticsManger. Create IosAnalytiscManager.swift class in the project with implementation of your choice. For this demo we are going to print the Event detail in the console.

import Foundation
import common
class IosAnalyticsManager : AnalyticsManager {
func report(event: Event) {
print("Interaction \(event.eventName()) happened with property \(event.eventProperties().debugDescription)")
}
}

Similar to android app we are going to add 3 buttons in the storyboard and link the click action to our view controller.

Screen Shot 2018-10-14 at 4.41.11 PM.png

We will link these buttons to our view controller.

import UIKit
import common
class ViewController: UIViewController {
let anatlyicsManager = IosAnalyticsManager()
override func viewDidLoad() {
super.viewDidLoad()
// Report page is viewed
anatlyicsManager.report(event: ViewEvent.init(pageName: "Main Page"))
}
@IBAction func redButtonClicked(_ sender: Any) {
anatlyicsManager.report(event: ButtonClickEvent.init(buttonName: "Red"))
}
@IBAction func greenButtonClicked(_ sender: Any) {
anatlyicsManager.report(event: ButtonClickEvent.init(buttonName: "Green"))
}
@IBAction func blueButtonClicked(_ sender: Any) {
anatlyicsManager.report(event: ButtonClickEvent.init(buttonName: "Blue"))
}
}

Now, run the app and we should be able to see the app in action:

Screen Shot 2018-10-14 at 4.44.57 PM

As the page is loaded, Page View Event is reported, similarly as we tap on each button the Button Clicked Event is reported. In our case, we can see the output in the console log.

Screen Shot 2018-10-14 at 4.46.12 PM

Summary:

To wrap it all up, we built “common” component using Kotlin Multiplatform plugin. We defined Event and AnalyticsManager there. We built Android app that used implemented the interface defined in the common. We then used it to repot the event. Similarly, we built iOS app, we implemented the protocol defined in common. We then used the exact same Event class defined in common to report the event.

This is just scratching the surface of whats possible with Kotlin Multiplatform. I hope this shows the potential of whats possible. I hope you found this post helpful. Until next time, adios amigos.

Sample code for this project is found in github: https://github.com/manijshrestha/kotlin-multi-platform-logging

 

References:

Kotlin Multiplatform Project: iOS and Android

 

 

 

 

Chromecast Hello World – Part 2, Receiver App

This is the second part of the Hello World app we started earlier.

In this part we are going to create a receiver app for Chromecast.

Overview

Receiver application is notting but a web application that gets loaded on the Chrome browser that is in the Cast device. Only one caveat, In order to load the web application we need to whitelist the application. We do not give it a absolute URL but a App_ID that google provides when you whitelist your domain (it will make more sense later in the post below).
This web application is launched on the cast device when a sender app, sends the message to do so. At this time there is a websocket connection between the sender and receiver which is managed by the Cast API. This API exposes ability to transmit commands between sender and receiver. We can do the standard play, pause etc. In addition we can send any free form of message as we choose. This is how authentication is done on the receiver app as well. (Passing Auth token from sender app to receiver app, that is how it would play content on netflix app).

Lets gets started.

Receiver App

Receiver app will be much simpler and we would want to keep it that way because cast has limited resources. You would not want to perform heavy computation on receiver app.
To create a receiver app, you begin with importing the following script on your receiver html page.

<script src="https://www.gstatic.com/cast/js/receiver/1.0/cast_receiver.js"></script>

With that we now can initialize our receiver application.
To do this, we start by creating Receiver object. This receiver object lets us perform media actions on the media content in the page.
Receives notification when media play is complete and sends it to the sender application. (There are some guidelines provided by Google on how we should manage this, but for this demo we are going to simply play an mp3)
Lets add the script below:

      <script type="text/javascript">

	var receiver = new cast.receiver.Receiver(
	    'YOUR_APP_ID', [cast.receiver.RemoteMedia.NAMESPACE], "", 5);
	var remoteMedia = new cast.receiver.RemoteMedia();
	remoteMedia.addChannelFactory(
	    receiver.createChannelFactory(cast.receiver.RemoteMedia.NAMESPACE));

	receiver.start();

	window.addEventListener('load', function() {
	  var elem = document.getElementById('music-player');
	  remoteMedia.setMediaElement(elem);
	});

	</script>

Here, we create a Receiver object with the App_ID provided google, this would be the App_ID that sender application would have sent to cast. We then setup the media element that will be managed by Cast. (In this case there is a audio element that has an id of ‘music-player’).

Here is the full HTML of the receiver application:

<html>
   <script src="https://www.gstatic.com/cast/js/receiver/1.0/cast_receiver.js"></script>
   <script type="text/javascript">

	var receiver = new cast.receiver.Receiver(
	    'YOUR_APP_ID', [cast.receiver.RemoteMedia.NAMESPACE], "", 5);
	var remoteMedia = new cast.receiver.RemoteMedia();
	remoteMedia.addChannelFactory(
	    receiver.createChannelFactory(cast.receiver.RemoteMedia.NAMESPACE));

	receiver.start();

	window.addEventListener('load', function() {
	  var elem = document.getElementById('music-player');
	  remoteMedia.setMediaElement(elem);
	});

   </script>

   <body>
      <img src="logo.png"/>
      <audio autoplay id="music-player">
         <source src="test.mp3" type="audio/mpeg">
      </audio>
   </body>
</html>

Screen Shot 2013-09-15 at 1.21.00 PM

Thats it!, we have the receiver application that. This page is simple when loaded will play the test.mp3 music on the receiver. Remember the media controls we did on the sender, like pause, stop. That will mange this audio here. You can try my sender app from github. Load the “music-player.html”

Full code could be found on github. https://github.com/manijshrestha/chromecast

Chromecast Hello World

Since the launch of google chromecast, I had been thinking about writing a quick app. Here is my attempt to build a simple chromecast app.
This will be multipart post as chromecast app needs different pieces to work together.

Chromecast Overview
Chromecast app consist of 2 part. One is the “Sender” App and another is the “Receiver”. Below image describes how it all fits together:
https://developers.google.com/cast/images/Diagram.jpg
Sender app can be a web app or a native ios or an android app.

Only thing sender does is to message the chromecast device to play a content. It can pass various parameters.

Behind the scene, your device and cast device in the network is using a managed websocket connection.

Today I am going to start with a simple web app as a sender app that will play youtube content on your cast device.
Google Chromecast web app can be a simple html page where “Chrome cast plugin” in Chrome browser will inject cast specific stuff to it.

Before we begin there are few things we need to take care of.

We must be running Chrome version 28 or higher.

Download the chomecast extension from chrome web store.

Enable developer option

We would need to enable developer option for your cast extension.
Here is how: Open “chrome://extensions” on your browser address bar.
Look for “Google Cast” extension, click on “options”, You should see page like below:

Screen Shot 2013-09-14 at 2.05.52 PM

Click on the cast icon 4 times. You should see following developer options appear (Google Loves Easter Egg… 🙂 )

Screen Shot 2013-09-14 at 2.08.44 PM

While you are at it, put “localhost” in the box, so the chromecast extension will inject in the required javascript on your page. You can add more domain as you would like but remember you need to get google’s blessing and get it whitelisted first.

White listing your receiver

In order build application and run on your chromecast for development, you will need to “whitelist” your device. Detailed instruction could be found here:
It takes few hours to a day to get it approved. You can get 2 URL whitelisted as well, usually one for test and one for production.

Sender

Sender Part of the application is responsible to detect available cast devices in the network. Sender app then is able to launch the given application on the Receiver cast device.

This tutorial we will be building a simple Sender app, that will open youtube on your cast device. Lets get started.
To test this, I had apache server running on my machine where I could host my app to send these messages to cast device. (Remember we had to put localhost on the extension?, without that it would not have initialized the cast api)

So Lets get it started.

First thing we need to do is to tell cast that it is able to “cast” content, to do this we need to put data-cast-api-enabled=”true” attribute on the html tag.

<html data-cast-api-enabled="true">
<head>
	<title>Chromecast Sender</title>
.. .. ..

I am going to be using very simple page and jquery to put it all together rather than using other js framework to demonstrate this.

Lets import the jQuery in our page

<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>

Now, let the fun begin, start a new script tag and lets initialize the cast.

   var cast_api, cv_activity;
   var receiverList = {};

   // Wait for API to post a message to us
   window.addEventListener("message", function(event) {
     if (event.source == window && event.data && event.data.source == "CastApi" && event.data.event == "Hello") {
	    initializeApi();
     }
   });

Here we what we did, we created some global variables to keep track of things. We added a event listener, this is because, the chomecast extension basically triggers this event. We verify it by running those checks 🙂 CastApi sends “Hello” event telling our page that cast extension is present. When this happens, we start by calling our initializeApi function.

Lets write that function,

   initializeApi = function() {
      cast_api = new cast.Api();
      cast_api.addReceiverListener("YouTube", onReceiverList);
      };

We are creating an instance of cast.Api telling it that we will be calling “YouTube” receiver app. The second parameter is the function name that will be called by cast api with list of receiver that is available.

Lets take care of that now.

   onReceiverList = function(list) {
   if (list.length > 0 ) {
      $("#receivers").empty();
      $.each(list, function(index, receiver){
         receiverList[receiver.id] = receiver;
         $device = $("<input type='radio' name='device-to-play' data-receiver-id=" +receiver.id+">"+receiver.name+"</li>");
         $("#receivers").append($device);
       });
    } else {
      $("#receivers").html("Opps No Cast device was found in the network.");
    }
   };

“list” consist of all the receiver that is available currently. We need to keep track of this so that we can send message to particular receiver later.

So, at this point we now have a sender application that is aware of cast devices that we can send message to.

Lets, send a message now.

Sending a message

We send a message to a receiver cast device via javascript. The device will then start the activity (“Activity”, if you have done some android stuff, you will feel right at home)
For this demo, lets assume that we are going to start a youtube video, we pass on the video id to be played.

	doLaunch = function(receiver, videoId) {
					var request = new cast.LaunchRequest("YouTube", receiver);
					request.parameters = "v="+videoId;
					request.description = new cast.LaunchDescription();
					request.description.text = "Playing Via Sender App";
					cast_api.launch(request, onLaunch);
				}

Here we are telling the cast device that we want to start “YouTube” app. (This could be other app id as well, we will talk about it in receiver section).
“receiver”, is one of the receiver we got from the list above.
we then call the “launch” function with a callback function name, in this case we call it “onLaunch”. This function will be called by the api once it gets a response from the receiver.

Here is onLaunch:

onLaunch = function(activity) {
					if (activity.status == "running") {
						cv_activity = activity;
						$("#status").html("On Air");
					} else {
						$("#status").html("Idle");
					}
				}

When we get the activity response we can check its status to know whats going on. If it is “running” we know that it is now running the activity. On the UI, we are putting “On Air” message “Idle” otherwise. (Currently you could get one of the three status: ‘running’, ‘stopped’, or ‘error’)

Thats it with the code above you are now able to fire up an activity on cast device.
Lets cover one more thing. If you need to send other message such as “pause” or “stop”, we would need to pass on activity id and call back function that needs to be called.
I am going to show how to stop the running media below:

   doStop = function() {
                         cast_api.stopActivity(cv_activity.activityId, onStop);
                       }

   onStop = function(mediaResult) {
					$("#status").html(mediaResult.status);
				}

Here we are calling “stopActivity” along with activityId of the running activity and a function to call, in this case it is “onStop”. Here we are simply putting the status string on the page.

You can see my sender.html code in following gist

Here is the github repo if you want to look at full code.
https://github.com/manijshrestha/chromecast/blob/master/sender/sender.html

Here is a view of finished product.
Screen Shot 2013-09-14 at 3.25.11 PM

Using SSH like a Pro

SSH is probably the most used command on my machine. If you use linux or OSX, ssh is most likely preinstalled for you. Even if you use windows, most likely you have Putty installed to securely connect to other machines. Today, I am going to show few things about the way I use SSH and may help you using it efficiently as well.

Keys Keys Keys…
The heart and power of ssh comes with its Public Key cryptography, using keys effectively you can eliminate the use of username and passwords completely. If not used correctly, it could be dangerous thing.
Setting up a key pair will let us connect to a server w/o having to key in a username and passwords. (I will discuss further below:)

Creating a key pair

You can use “ssh-keygen” to generate a key-pair on your local machine.
You may want to skip the “passphrase”, having it adds an extra layer of security but if you want to seamlessly be able to connect to servers or connect via scripts, having a passphrase will not help.

Here is how you can create a ssh key (rsa):

$ ssh-keygen -t rsa

You will output like below: Note here you can simply hit enter to continue or specify location of a file and passphrase

Generating public/private rsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/username/.ssh/id_rsa.
Your public key has been saved in /home/username/.ssh/id_rsa.pub.
The key fingerprint is:
31:XX:ee:XX:aa:bb:XX:XX username@linux
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|        .        |
| .   + o +       |
|      o S        |
|.o . o           |
|...+....         |
|..===...         |
|........         |
+-----------------+


At this point you should have 2 files in your “.ssh” folder

$ cd ~/.ssh
$ ls -l
-rw-------  1 username  admin  1557 May 22 21:23 id_rsa
-rw-r--r--  1 username  admin   410 May 22 21:23 id_rsa.pub

In most cases you dont have to touch either of them except that you should know its existence. If you use cygwin or someone else modified/copied the file changing its permission, you will have problem. Pay close attention to the file permission. The “id_rsa”, ie. the private key must have RW to owner only. If the permission is not set correctly, SSH will not use your keys.

identity

Now you have a key pair you can use. Lets go ahead and use it.
Normally you may already know that you would connect to remote server by running a command like below:

$ ssh remoteuser@remoteserver
... Enter password...

Since we create a key lets setup it up.

ssh-copy-id

You can copy your public key over to remote host using the ssh-copy-id command:

$ ssh-copy-id -i ~/.ssh/id_rsa remoteuser@remoteserver
remoteuser@remoteserver's password: [ENTER PASSWORD]
Now try logging into the machine, with "ssh 'remoteuser@remoteserver'", and check in:

  ~/.ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.

Lets login to the remote server. We can simply run the ssh command along with the identity file.

$ ssh -i ~/.ssh/id_rsa remoteuser@remoteserver

You should notice that we just logged into the remote server w/o entering a password.
In the ssh command we passed “-i” flag along with the location to our private key. This means, we passed our identity file as our id_rsa private key telling ssh to use it to connect to the remote server.

If you have multiple key pairs and long list of servers to go along with it, it might be hard to keep track and hard to manage. If you use Amazon EC2, or other private/public cloud, you know will have to keep track of them specially with hard server names and multiple keys.
But, there is a solution for that. And it is “config” file.

The ssh “config” file

“config” file in your “.ssh” folder does a lot of magic. I will show you some tricks.
If the file doesn’t already exist, you can just create one. If the file exist, you can keep adding entries at the end of the file.
I will explain an entry here:
So to go along with our example. We can now setup a config to our remote server.
Let’s add following entry in our config file.

$ vi ~/.ssh/config
...
...
...

Host rs
HostName remoteserver
User username
IdentityFile ~/.ssh/id_rsa

Here we added all the information we need to connect to our remoteserver. We entered “User” that we will login as. Pointed to your private key. At the very first we added a word “rs” after Host, ie. we are giving an alias to my “remotesever”. So we can now do “ssh rs”.
Try it for yourself.

$ ssh rs

Walla you just logged in to your remote server w/o a password yet with one single word.

Port Forwarding

Port Forwarding is an advanced feature of ssh. It is very useful in many cases.
Using port forwarding, your communication over the port is encrypted over ssh. This creates a p2p “tunnel” between the server and you.
This is often referred as poor man’s vpn.

Local Forwarding

Local port forwarding will let us forward any communication that happens in our “local” box on that port to be forwarded on to the remote server.
Let’s say that we have mysql installed in our remote server. We want to connect to that database from our local server as if it is installed locally, we can configure it as follows:

$ ssh rs -L 3306:localhost:3306

Above we configured a local port forwarding (“-L”), we binded our local port “3306”, to remote port “3306” on the localhost i.e. the remote host.
this means if you configure your application to connect to “localhost:3306″, it is actually connecting to the port 3306 on the remote server.
You can have more than one port forwarding. If you want more, simply add more ” -L localport:host:remoteport”

Another example to clarify this more:
Lets say you want to bind port 8181 on your local box to point to http://www.cnn.com through the ssh connection. (Basically the traffic to cnn.com will be routed from the remote box)

$ ssh -L 8181:www.cnn.com:80 rs

Now, open a browser and navigate to “localhost:8181”. You will see that cnn.com page comes up :).

Screen Shot 2013-05-22 at 10.22.01 PM

Remote Forwarding

Similar to local forwarding, we can bind a port on the remote box back to our local machine. This is done via “-R” flag.

$ ssh -R 8282:localhost:8585

After ssh connection is established, on the remote box’s port 8282 is bound back to box initiating the connection to port 8585.

Using port forwarding, remote and local, you can create these tunnels between servers.

SOCKS-PROXY

SSH could be used as socks proxy. To explain this lets say the machine you are using locally does not have access to the internet. Or your access to facebook or youtube is blocked. But say a “remote” server has unrestricted access to the internet and is able to surf facebook or youtube.
You can setup a ssh dynamic port binding and use it as socks proxy. This means, your local machine can access those site through the “remote” server bypassing the firewall. Your connection to facebook / youtube is happening through the secure “tunnel”.
Let’s set one up.

$ ssh -C -D 1080 remoteserver

You can now configure your browser to use “localhost:1080” as SOCKS proxy.
Screen Shot 2013-05-22 at 10.43.15 PM

You can go to any site on that browser and all the web traffic will be routed over through remoteserver.

Hope this helps you use ssh like a pro 🙂

Building app with responsive design using jQuery mobile and CSS3 (Media Query)

Having built few mobile apps with HTML5 and CSS, it allowed to build apps quickly with simple text editor using HTML and JS. Recently it has been very popular. There are many really good frameworks such as Sencha, Jo, The-M-Project , KendoUI just to name a few. JQuery Mobile is probably one of the simplest one to get started with.

One of the challenges these days is building an app that works on both phone and tablet  (able to utilize larger screen sizes). Today, I am going to quickly demonstrate building of a simple mobile app with “Responsive” mobile design that would work on both mobile phone as well as tablet. Just to show the end result,  here is what we will have at the end:

Wireframe: To get started let’s starts with code below. You can read more about it on jQuery Mobile website.

<!DOCTYPE html> 
<html> 
<head> 
	<title>Page Title</title> 
	
	<meta name="viewport" content="width=device-width, initial-scale=1"> 

	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
	<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
	<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
</head> 
<body> 

<div data-role="page">

	<div data-role="header">
		<h1>Cool App</h1>
	</div><!-- /header -->

	<div data-role="content">	
		<p>Some Cool Stuff</p>		
	</div><!-- /content -->
</div><!-- /page -->

</body>
</html>

If you crate index.html with above code you will have a mobile app using jQuery mobile:).

Adding Menu: Lets add the menu and some content. To do this, lets create two divs,
“menu-pane” and “content-pane”. These would be the direct child under “content” div.

<div data-role="content">
<div id="menu-pane">
<ul data-role="listview">
	<li><a id="menu-item-1" href="#">Menu Item 1</a></li>
	<li><a id="menu-item-2" href="#">Menu Item 2</a></li>
</ul>
</div>
<div id="content-pane">
 Some Cool Stuff</div>
</div>
<!-- /content -->

You should see a page like below:

Behavior on buttons: Now, Lets add a behavior when if we click on any menu item it will simply pop up ‘Not Yet Implemented’.
you can do so by adding following jQuery block in side the head tag.

<script type="text/javascript">
		$(document).ready(function() {

			//Just an alert to show its not implatemented..
			$("#menu-item-1, #menu-item-2").click( function () {alert("Not yet Implemented.")});

		}); // end of document Ready

</script>

CSS for menu: Let’s add a tiny little CSS so that menu and content page looks better on tablet.

<style>
	  #menu-pane {
		  width: 30%;
		  float: left;
		  }

	  #content-pane {
			width: 70%;
			height: 100%;
			float: left;
			text-align: center;
		}
</style>

At this time you should have a nice looking interface good for tablet. Similar to page below:

This wouldn’t look so nice on a mobile phone, and we are going to fix that next.
Idea here is that we are going to add a menu button on top right which will expose the menu for user on mobile phone and n tablet menu just appears on the left side.

Options Button: So, lets add a button in the HTML that will on click open a pop up with menu items. To do this, we will add a button and a empty popup div in which we will populate dynamically. Add the following HTML inside the header div.

<a id="options-btn" class="ui-btn-right" href="#popupPanel" data-icon="gear" data-rel="popup">Options</a>
<!-- Popup Menu Content -->
<div data-role="popup" id="popupPanel"><!--Empty for now--></div>

Populating Popup Menu: Now since we have an empty div for popup, lets populate that with the menu we have on the screen. Based on your implementation, you may choose to do it differently.

Add the following javascript in the document.ready function. This will just copy the HTML from #menu-pane in to the #popupPanel

$("#popupPanel").html($("#menu-pane").html());

You can see the ui would look something like below:

Making it “Responsive” with Media Query: Now finally we want to make it “Responsive” by using media query. What we would want to do is that,
when its on a tablet, we want to take off the “Options” button. And, when we are on a mobile phone we want to remove the menu from left and show the “Options” button.
Let’s do that by adding media query css.

  /* Hide the menu-pane when on mobile */
		@media screen and (max-width: 480px) {
	      #menu-pane{
			display: none;
		  }

		}

Also lets update the existing css we had before and wrap it for tablet view.

/* Hide Options button on tablet */
		@media screen and (min-width: 481px) {
		  #menu-pane {
			  width: 30%;
			  float: left;
			  }

	      #content-pane {
				width: 70%;
				height: 100%;
				float: left;
				text-align: center;
			}

			#options-btn {
					display: none;
			}
		}

At this time we have have a working app that works on both tablet and mobile! On the browser, you can change the browser and see it in action :).

Complete source code of this could be found in github at: https://github.com/manijshrestha/jQueryMobileResponsiveDemo

Final output: The final HTML would look like one below:

<!DOCTYPE html> 
<html> 
<head> 
	<title>Cool App</title> 
	
	<meta name="viewport" content="width=device-width, initial-scale=1"> 

	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
	<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
	<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
	
	<script type="text/javascript">
		$(document).ready(function() {
			$("#popupPanel").html($("#menu-pane").html());	
			//Just an alert to show its not implatemented..
			$("#menu-item-1, #menu-item-2").click( function () {alert("Not yet Implemented.")});
		
		}); // end of document Ready
	</script>
	
	<style>
		
	  /* Hide the menu-pane when on mobile */	 
		@media screen and (max-width: 480px) {
	      #menu-pane{
			display: none;
		  }

		}
		
	  /* Hide Options button on tablet */
		@media screen and (min-width: 481px) {
		  #menu-pane {
			  width: 30%;
			  float: left;
			  }
	      
	      #content-pane {
				width: 70%;
				height: 100%;
				float: left;
				text-align: center;
			}
			
			#options-btn {
					display: none;
			}
		}
		
	</style>
	
</head> 
<body> 

<div data-role="page">

	<div data-role="header">
		<h1>Cool App</h1>
		<a id="options-btn" href="#popupPanel" data-icon="gear" data-rel="popup" class="ui-btn-right">Options</a>		
		<!-- Popup Menu Content -->
		<div data-role="popup" id="popupPanel" >
			<!--Empty for now-->
		</div>
	</div><!-- /header -->

	<div data-role="content">
		<div id="menu-pane">
		   <ul data-role="listview">
				<li><a id="menu-item-1" href="#">Menu Item 1</a></li>
				<li><a id="menu-item-2" href="#">Menu Item 2</a></li>
		   </ul>
		</div>
		
		<div id="content-pane">	
			<p>		Some Cool Stuff		</p>		
		</div>
		
	</div><!-- /content -->
</div><!-- /page -->

</body>
</html>

Hope you enjoyed this post. Thank you,

Grails Gotcha’s

I have been playing around with Grails for a while now. It is a great framework. One of the best alternatives for rapid application development under java stack.
Its idea of Convention over configuration is the seller. However, As I started developing apps on grails, it was hard to get use to the “convention” as sometimes the “convention” was not clear. When I searched the issue online, I could hardly find any relevant information. So I am starting to keep track of things I learned the hard way.

1. Plugin-Installation:
I wanted to install jQuery plug-in on my app so I followed instructions found at http://www.grails.org/plugin/jquery
I was having hard time installing it (will talk about that in bullet 2). So finally I installed jQuery Plug-in 1.4.2.
Later on I wanted to upgrade it to jQuery plug-in 1.4.4.
So this is what i did
a. uninstalled jquery plugin
b. ran grails install-plugin jquery 1.4.4.1

So issue so far, then I ran
c. grails install-jquery
but it kept adding jquery 1.4.2.

After hunting my file system down I figured out that apparently, Grails caches the script in \.grails\1.3.6\projects\\scriptCache
so when i installed the 1.4.2 it had kept scripts there but then when i wanted to upgrade, it still had the old script cached so it did not over write with 1.4.4.1 script.
So the solution was to delete all the scripts in scriptCache folder and run through steps a-c and walla.. it works!
Lesson learned: clear the scriptCache

2. Proxy Server Setup:
I was trying to install grails plug-ins at my work. I am behind a proxy. So when I tried to install a plug-in it basically gave me error saying “Host could not be reached”.
Then I simply went to the “Network Settings” in the SpringsourceTool Set and fixed the proxy. But still I kept on getting the same error.
After much of research I found out that we need to exclusively set up Proxy in Grails. And here is how we set it up:
a. grails add-proxy myProxy “–host=someproxyserver” “–port= 8080″
b. grails set-proxy myProxy

here you can call anything you want. and dont forget the part b ie set-proxy. Also, dont forget the ” around the host and port, for some reason in the OS i am using if i did not put ” it did not work correctly.
more info could be found at http://grails.org/doc/latest/ref/Command%20Line/set-proxy.html

QuickAction Implementation on Android

A while ago I watched the google IO video on UI Design patterns.
http://www.youtube.com/watch?v=M1ZBjlCRfz0&feature=player_embedded#at=1634
I was quite impressed by what I saw. One in particular caught my attention was the “Quick Action”.
Basically when a user clicks on an “Item” a quick Action bar appears where a user can select action he/she wants to perform. This could be a very handy tool especially for the application which have items that are context sensitive yet don’t need to click on “Menu” button the device.
As this is not provided by standard Android SDK, we have to implement our own. However, I found this great article on how this could be Impleted.
http://www.londatiga.net/it/how-to-create-quickaction-dialog-in-android/

Groovy Meta programming

I have been playing around with Groovy for a while now. As a traditional Java developer, when I started playing with Groovy, I just fell in LOVE with it. Things just worked! It was really cool to see that there was a language that ran on JVM which was much more intuitive. (Groovy guys did an awesome job! Brought Coolness of other langs like Ruby, Python etc into a lang on JVM).

I am going to jump into a really cool feature of Groovy, ie. Meta programming. This concept was out of the ordinary for me but as I saw few use cases, I was really impressed.

Lets talk Expando! (Ref. Based on Webcast by Jeff Brown from springsource.)
Unlike Java, in groovy, lots of things happen at run time. One of them is to resolve proprety, method execution etc.
Here is an example.
Say, I create a groovy class:

Code 1.1


class ExpandoLite {

}

Say, I create an instance of the Class

Code 1.2


  def expandoLite = new ExpandoLite()

  expandoLite.name = 'John'

  println expandoLite.name

// see no ; required... things are simple!

We will get an error

groovy.lang.MissingPropertyException: No such property: name for class: ExpandoLite

Groovy is dynamic, apparently Groovy calls a method called “setProperty” to set a property and getProperty to get the value off for it
So, we can do


class ExpandoLite {
	
	private dynamicProperties  = [:]

	void setProperty (String name, value){
		dynamicProperties[name] = value
	}

        def getProperty (String name){
		dynamicProperties[name]
	}
}

now if we run the code 1.2 again.
It will work

groovy> class ExpandoLite { 
groovy>      
groovy>     private dynamicProperties  = [:] 
groovy>     void setProperty (String name, value){ 
groovy>         dynamicProperties[name] = value 
groovy>     } 
groovy>      
groovy>     def getProperty (String name){ 
groovy>         dynamicProperties[name] 
groovy>     } 
groovy> } 
groovy> def expandoLite = new ExpandoLite() 
groovy> expandoLite.name = 'John' 
groovy> println expandoLite.name 
 
John

This feature allows us to dynamically create a field in the class. Behind the scene, we just have a map to store that stores value for a given attribute “Key”.