A/B Testing Marketing cloud

 A/B Testing Marketing Cloud

 Why A/B Testing :-

We use standard A/B testing to determine which version of your email(Or a subject line)receives the highest click-through rate or highest unique open rate. On the basis of that, we sends the best performing version to the remaining subscribers or Data Extentions.

  • You can test the following elements:
  • Test Type            Description
  1. Subject Line:                     Create two different subject lines and track which email send                                                                                             performs better. Each subject line has a 256 character limit.
  2. Email:                                Select two different emails and track which email send performs                                                                                       better.
  3. Content area:                    Select an email that contains at least two different content areas and                                                                               track which content area performs better.
  4. From Name:                     Create two different from names and track which email send                                                                                             performs better. You can select an existing from name in your account,                                                                           or manually enter a from name to use. To add additional from name                                                                               Select two different dates and/or times to send and track which time                                                                               options to your account, create an additional user.
  5. Send Time:                        performs better.
  6. Preheaders:                     Create two different preheaders and track which preheader performs                                                                  better.


  • IF Tie Happens :

If your A/B Test results in a tie, the system declares Condition A the winner. You can edit the winner criteria to see if one condition performed better than the other using a different winner criteria.

For example, if you ran your test by the highest open rate and your test results in a tie, you can edit the winner criteria to use highest click-through rate.

Or, if you ran your test by the highest open rate and Condition B had a significantly higher click-through rate than Condition A had an open rate, you can edit the winner criteria in order to send Condition B.  You will be able to make this change only if you scheduled the remainder to send at a later time.

  • WE Can Save the Winning Subject Line :

When running a subject line A/B test, you have the option to have the winning subject line save back to the original email. You configure this in the Winner stage of the test creation process.

Different Processes of A/B testing and Useful links.

Following link contain steps to create those processes.

  1. Configure A/B Test


  1. Duplicate A/B Test


  1. Edit A/B Test


  1. Track A/B Test


  1. Cancel A/B Test


Platform Cache varient 2 – Org Cache

Continuing with Platform Cache….

2. Org Cache : The second variant of Platform Cache is the Org Cache. Org Cache does the same thing of storing the data in session, but the data stored is accessible through out the org, irrespective of  user, which is not the case with Session Cache.
If user1 is storing a  value1 in org cache, it is accessible by user2 also.

We can have different partitions to store values. We use the Cache.Org and Cache.OrgPartition classes to manage values in the org cache. To manage values in any partition, use the methods in the Cache.Org class. If we are managing cache values in one partition, use the Cache.OrgPartition methods instead.

This example stores a DateTime cache value with the key orderDate. Next, the snippet checks if the orderDate key is in the cache, and if so, retrieves the value from the cache.

// Add a value to the cache//
DateTime dt = DateTime.parse(’06/16/2015 11:46 AM’);  Cache.Org.put(‘ns1.partition1.orderDate’, dt);
if (Cache.Org.contains(‘ns1.partition1.orderDate’)) {
       DateTime cachedDt = (DateTime)Cache.Org.get(‘ns1.partition1.orderDate’);


To refer to the default partition and the namespace of the invoking class, omit the namespace.partition prefix and specify the key name.

Cache.Org.put(‘orderDate’, dt);
if (Cache.Org.contains(‘orderDate’)) {
DateTime cachedDt = (DateTime)Cache.Org.get(‘orderDate’);

The local prefix refers to the namespace of the current org where the code is running. The local prefix refers to the namespace of the current org where the code is running, regardless of whether the org has a namespace defined. If the org has a namespace defined as ns1, the following two statements are equivalent.

Cache.Org.put(‘local.myPartition.orderDate’, dt);
Cache.Org.put(‘ns1.myPartition.orderDate’, dt);

This is all about the Org Cache in apex.  There is another interesting thing about Platform Cache!

We can access cached values stored in the session or org cache from a Visualforce page with global variables.We can use either the $Cache.Session or $Cache.Org global variable. Include the global variable’s fully qualified key name with the namespace and partition name.

This output text component retrieves a session cache value using the global variable’s namespace, partition, and key.

<apex:outputText value=”{!$Cache.Session.myNamespace.myPartition.key1}”/>

This example is similar but uses the $Cache.Org global variable to retrieve a value from the org cache.


Now the Platform Cache concept seems more useful! We can directly use it in Vf page!!

Salesforce is Awesome!

Use Glide Cache efficiently in Glide Android

The issue is that currently if I call Glide.load() multiple times with the same URL. however, each time with an image views the image gets downloaded again.

It happens because the width and height are mixed into the cache key so if you load the same image into multiple different views with different sizes, the image will be fetched once per image by default.

You can change this by calling  .diskCacheStrategy() with  DiskCacheStrategy.SOURCE on remote image loads. Doing so will use only the original URL as the cache key and so you will get a cache hit if you try to load the same URL with multiple sizes.


    .with( context )
    .load( URL )
    .diskCacheStrategy( DiskCacheStrategy.SOURCE )
    .into( imageViewInternet );

For more details click here

Bundles in Steelbrick CPQ

Steelbrick CPQ allows users to define bundles to be added to Quote. This proves very helpful as it saves time of adding every product individually.

For achieving this there are two objects in CPQ.

The first is Features. Features is basically definition of the bundle. Features can be added from related lists of Products. The product that has a feature becomes the master. So whenever the Master is added, the feature can be added.

Feature is just the name of the bundle, but actual contents of the bundle are stored in Options object.

Options can be added from related list of the Features record. Options are references to the products to be included in the bundle.

Apart from just adding the products in the Bundles, various configurations can be added like predefining the quantity and whether the Quantity can be edited while adding the products in the Quote or it has to be fixed, whether the Product is mandatory or not, whether the product has to be selected by default in the bundle etc.

Bundle proves to be one of the most useful feature of the CPQ.

Alternative for xib in swift3 iOS

Hi all,

Lets see the simplest and best way to replace or avoid use of xib by using UIView on storyboard.


  1.  Go on storyboard ,select Viewcontroller Drag UIView and drop it between FirstResponder and exit button on that.
  2.  Add IBOutlet of that UIView on ViewController.swift file.
  3.  set the center, width, height for that UIView
  4.  Refer Following code :


——– IBOutlet ——–

@IBOutlet var View_alternativeForXib: UIView!

var view_BGDimmer = UIView()


——– Set the center , width, height for that UIView as well as add transperent Background view ———


       View_alternativeForXib.center = (UIApplication.shared.keyWindow?.center)!

          view_BGDimmer.frame = (UIApplication.shared.keyWindow?.frame)!

         View_alternativeForXib.frame.size.width = (UIApplication.shared.keyWindow?.frame.width)! – 40

         View_alternativeForXib.frame.origin.x = (UIApplication.shared.keyWindow?.frame.origin.x)! + 20

          view_BGDimmer.backgroundColor =  colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)

          view_BGDimmer.alpha = 0.3


          UIApplication.shared.keyWindow?.insertSubview(self.View_alternativeForXib, aboveSubview: self.view_BGDimmer)

          UIView.animate(withDuration: 0.1, animations: {

          }) { (completed) in



——-  To dismiss view ——

   func dimissPopUp() {

        UIView.animate(withDuration: 0.2, animations: {

            self.view_BGDimmer.alpha = 0.0



        }) { (completed) in









Save and Load from KeyChain | Swift 4

import Cocoa

import Security

// see https://stackoverflow.com/a/37539998/1694526

// Arguments for the keychain queries

let kSecClassValue = NSString(format: kSecClass)

let kSecAttrAccountValue = NSString(format: kSecAttrAccount)

let kSecValueDataValue = NSString(format: kSecValueData)

let kSecClassGenericPasswordValue = NSString(format: kSecClassGenericPassword)

let kSecAttrServiceValue = NSString(format: kSecAttrService)

let kSecMatchLimitValue = NSString(format: kSecMatchLimit)

let kSecReturnDataValue = NSString(format: kSecReturnData)

let kSecMatchLimitOneValue = NSString(format: kSecMatchLimitOne)

public class KeychainService: NSObject {

    class func updatePassword(service: String, account:String, data: String) {

        if let dataFromString: Data = data.data(using: String.Encoding.utf8, allowLossyConversion: false) {

            // Instantiate a new default keychain query

            let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue])

            let status = SecItemUpdate(keychainQuery as CFDictionary, [kSecValueDataValue:dataFromString] as CFDictionary)

            if (status != errSecSuccess) {

                if let err = SecCopyErrorMessageString(status, nil) {

                    print(“Read failed: \(err)”)





    class func removePassword(service: String, account:String) {

        // Instantiate a new default keychain query

        let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue])

        // Delete any existing items

        let status = SecItemDelete(keychainQuery as CFDictionary)

        if (status != errSecSuccess) {

            if let err = SecCopyErrorMessageString(status, nil) {

                print(“Remove failed: \(err)”)




    class func savePassword(service: String, account:String, data: String) {

        if let dataFromString = data.data(using: String.Encoding.utf8, allowLossyConversion: false) {

            // Instantiate a new default keychain query

            let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, dataFromString], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecValueDataValue])

            // Add the new keychain item

            let status = SecItemAdd(keychainQuery as CFDictionary, nil)

            if (status != errSecSuccess) {    // Always check the status

                if let err = SecCopyErrorMessageString(status, nil) {

                    print(“Write failed: \(err)”)





    class func loadPassword(service: String, account:String) -> String? {

        // Instantiate a new default keychain query

        // Tell the query to return a result

        // Limit our results to one item

        let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue])

        var dataTypeRef :AnyObject?

        // Search for the keychain items

        let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)

        var contentsOfKeychain: String?

        if status == errSecSuccess {

            if let retrievedData = dataTypeRef as? Data {

                contentsOfKeychain = String(data: retrievedData, encoding: String.Encoding.utf8)


        } else {

            print(“Nothing was retrieved from the keychain. Status code \(status)”)


        return contentsOfKeychain



You need to imagine the following wired up to a text input field and a label, then having four buttons wired up, one for each of the methods.

class ViewController: NSViewController {

    @IBOutlet weak var enterPassword: NSTextField!

    @IBOutlet weak var retrievedPassword: NSTextField!

    let service = “myService”

    let account = “myAccount”

    // will only work after

    @IBAction func updatePassword(_ sender: Any) {

        KeychainService.updatePassword(service: service, account: account, data: enterPassword.stringValue)


    @IBAction func removePassword(_ sender: Any) {

        KeychainService.removePassword(service: service, account: account)


    @IBAction func passwordSet(_ sender: Any) {

        let password = enterPassword.stringValue

        KeychainService.savePassword(service: service, account: account, data: password)


    @IBAction func passwordGet(_ sender: Any) {

        if let str = KeychainService.loadPassword(service: service, account: account) {

            retrievedPassword.stringValue = str


        else {retrievedPassword.stringValue = “Password does not exist” }



Moshi – Modern JSON library for Android

Moshi is a modern JSON library for Android and Java. It makes it easy to parse JSON into Java objects:

Download  the jar or dependancy via Maven:


or Gradle:

compile 'com.squareup.moshi:moshi:1.5.0'

String json = ...;

Moshi moshi = new Moshi.Builder().build();
JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);

BlackjackHand blackjackHand = jsonAdapter.fromJson(json);

And it can just as easily serialize Java objects as JSON:

BlackjackHand blackjackHand = new BlackjackHand(
    new Card('6', SPADES),
    Arrays.asList(new Card('4', CLUBS), new Card('A', HEARTS)));

Moshi moshi = new Moshi.Builder().build();
JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);

String json = jsonAdapter.toJson(blackjackHand);

Built in support Adapter :

Moshi has built-in support for reading and writing Java’s core data types:

  • Primitives (int, float, char…) and their boxed counterparts (Integer, Float, Character…).
  • Arrays, Collections, Lists, Sets, and Maps
  • Strings
  • Enums

It supports your model classes by writing them out field-by-field.

In the example above Moshi uses these classes:

class BlackjackHand {
  public final Card hidden_card;
  public final List<Card> visible_cards;

class Card {
  public final char rank;
  public final Suit suit;

enum Suit {

to read and write this JSON:

  "hidden_card": {
    "rank": "6",
    "suit": "SPADES"
  "visible_cards": [
      "rank": "4",
      "suit": "CLUBS"
      "rank": "A",
      "suit": "HEARTS"

Firebase JobDispatcher

The Firebase JobDispatcher is a library for scheduling background jobs in your Android app. It provides a JobScheduler-compatible API that works on all recent versions of Android (API level 9+) that have Google Play services installed.


What’s a JobScheduler?

The JobScheduler is an Android system service available on API levels 21 (Lollipop)+. It provides an API for scheduling units of work (represented by JobService subclasses) that will be executed in your app’s process.

Why is this better than background services and listening for system broadcasts?

Running apps in the background is expensive, which is especially harmful when they’re not actively doing work that’s important to the user. That problem is multiplied when those background services are listening for frequently sent broadcasts (android.net.conn.CONNECTIVITY_CHANGE and android.hardware.action.NEW_PICTURE are common examples). Even worse, there’s no way of specifying prerequisites for these broadcasts. Listening for CONNECTIVITY_CHANGE broadcasts does not guarantee that the device has an active network connection, only that the connection was recently changed.

In recognition of these issues, the Android framework team created the JobScheduler. This provides developers a simple way of specifying runtime constraints on their jobs. Available constraints include network typecharging state, and idle state.

This library uses the scheduling engine inside Google Play services(formerly the GCM Network Manager component) to provide a backwards compatible (back to Gingerbread) JobScheduler-like API.

This I/O presentation has more information on why background services can be harmful and what you can do about them:


There’s more information on upcoming changes to Android’s approach to background services on the Android developer preview page.


The FirebaseJobDispatcher currently relies on the scheduling component in Google Play services. Because of that, it won’t work on environments without Google Play services installed.

Comparison to other libraries

Library Minimum API Requires Google Play Service API1 Custom retry strategies
Framework JobScheduler 21 No JobScheduler Yes
Firebase JobDispatcher 9 Yes JobScheduler Yes
evernote/android-job 14 No2 Custom Yes

1: Refers to the methods that need to be implemented in the Service subclass.
2: Uses AlarmManager to support API levels <= 21 if Google Play services is unavailable.

Getting started


Add the following to your build.gradle‘s dependencies section:

compile 'com.firebase:firebase-jobdispatcher:0.8.5'


Writing a new JobService

The simplest possible JobService:

import com.firebase.jobdispatcher.JobParameters;
import com.firebase.jobdispatcher.JobService;

public class MyJobService extends JobService {
    public boolean onStartJob(JobParameters job) {
        // Do some work here

        return false; // Answers the question: "Is there still work going on?"

    public boolean onStopJob(JobParameters job) {
        return false; // Answers the question: "Should this job be retried?"

Adding it to the manifest

        <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>

Creating a Dispatcher

// Create a new dispatcher using the Google Play driver.
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));

Scheduling a simple job

Job myJob = dispatcher.newJobBuilder()
    .setService(MyJobService.class) // the JobService that will be called
    .setTag("my-unique-tag")        // uniquely identifies the job


Scheduling a more complex job

Bundle myExtrasBundle = new Bundle();
myExtrasBundle.putString("some_key", "some_value");

Job myJob = dispatcher.newJobBuilder()
    // the JobService that will be called
    // uniquely identifies the job
    // one-off job
    // don't persist past a device reboot
    // start between 0 and 60 seconds from now
    .setTrigger(Trigger.executionWindow(0, 60))
    // don't overwrite an existing job with the same tag
    // retry with exponential backoff
    // constraints that need to be satisfied for the job to run
        // only run on an unmetered network
        // only run when the device is charging


Cancelling a job


Cancelling all jobs


For more info please check this link => https://github.com/firebase/firebase-jobdispatcher-android#user-content-firebase-jobdispatcher-

Google Calendar – Calendar API

Step 1: Acquire a SHA1 fingerprint

Step 2: Turn on the Google Calendar API

Step 3: Create a new Android project

Step 4: Prepare the project

Open the app build.gradle file and add dependencies  content with the following:

compile('com.google.api-client:google-api-client-android:1.23.0') {
        exclude group: 'org.apache.httpcomponents'
    compile('com.google.apis:google-api-services-calendar:v3-rev273-1.23.0') {
        exclude group: 'org.apache.httpcomponents'

Create a new Java class called "MainActivity" and replace the contents of the new file with the following code.
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;

import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.ExponentialBackOff;

import com.google.api.services.calendar.CalendarScopes;
import com.google.api.client.util.DateTime;

import com.google.api.services.calendar.model.*;

import android.Manifest;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;

public class MainActivity extends Activity
    implements EasyPermissions.PermissionCallbacks {
    GoogleAccountCredential mCredential;
    private TextView mOutputText;
    private Button mCallApiButton;
    ProgressDialog mProgress;

    static final int REQUEST_ACCOUNT_PICKER = 1000;
    static final int REQUEST_AUTHORIZATION = 1001;
    static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
    static final int REQUEST_PERMISSION_GET_ACCOUNTS = 1003;

    private static final String BUTTON_TEXT = "Call Google Calendar API";
    private static final String PREF_ACCOUNT_NAME = "accountName";
    private static final String[] SCOPES = { CalendarScopes.CALENDAR_READONLY };

     * Create the main activity.
     * @param savedInstanceState previously saved instance data.
    protected void onCreate(Bundle savedInstanceState) {
        LinearLayout activityLayout = new LinearLayout(this);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
        activityLayout.setPadding(16, 16, 16, 16);

        ViewGroup.LayoutParams tlp = new ViewGroup.LayoutParams(

        mCallApiButton = new Button(this);
        mCallApiButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

        mOutputText = new TextView(this);
        mOutputText.setPadding(16, 16, 16, 16);
        mOutputText.setMovementMethod(new ScrollingMovementMethod());
                "Click the \'" + BUTTON_TEXT +"\' button to test the API.");

        mProgress = new ProgressDialog(this);
        mProgress.setMessage("Calling Google Calendar API ...");


        // Initialize credentials and service object.
        mCredential = GoogleAccountCredential.usingOAuth2(
                getApplicationContext(), Arrays.asList(SCOPES))
                .setBackOff(new ExponentialBackOff());


     * Attempt to call the API, after verifying that all the preconditions are
     * satisfied. The preconditions are: Google Play Services installed, an
     * account was selected and the device currently has online access. If any
     * of the preconditions are not satisfied, the app will prompt the user as
     * appropriate.
    private void getResultsFromApi() {
        if (! isGooglePlayServicesAvailable()) {
        } else if (mCredential.getSelectedAccountName() == null) {
        } else if (! isDeviceOnline()) {
            mOutputText.setText("No network connection available.");
        } else {
            new MakeRequestTask(mCredential).execute();

     * Attempts to set the account used with the API credentials. If an account
     * name was previously saved it will use that one; otherwise an account
     * picker dialog will be shown to the user. Note that the setting the
     * account to use with the credentials object requires the app to have the
     * GET_ACCOUNTS permission, which is requested here if it is not already
     * present. The AfterPermissionGranted annotation indicates that this
     * function will be rerun automatically whenever the GET_ACCOUNTS permission
     * is granted.
    private void chooseAccount() {
        if (EasyPermissions.hasPermissions(
                this, Manifest.permission.GET_ACCOUNTS)) {
            String accountName = getPreferences(Context.MODE_PRIVATE)
                    .getString(PREF_ACCOUNT_NAME, null);
            if (accountName != null) {
            } else {
                // Start a dialog from which the user can choose an account
        } else {
            // Request the GET_ACCOUNTS permission via a user dialog
                    "This app needs to access your Google account (via Contacts).",

     * Called when an activity launched here (specifically, AccountPicker
     * and authorization) exits, giving you the requestCode you started it with,
     * the resultCode it returned, and any additional data from it.
     * @param requestCode code indicating which activity result is incoming.
     * @param resultCode code indicating the result of the incoming
     *     activity result.
     * @param data Intent (containing result data) returned by incoming
     *     activity result.
    protected void onActivityResult(
            int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch(requestCode) {
                if (resultCode != RESULT_OK) {
                            "This app requires Google Play Services. Please install " +
                            "Google Play Services on your device and relaunch this app.");
                } else {
            case REQUEST_ACCOUNT_PICKER:
                if (resultCode == RESULT_OK && data != null &&
                        data.getExtras() != null) {
                    String accountName =
                    if (accountName != null) {
                        SharedPreferences settings =
                        SharedPreferences.Editor editor = settings.edit();
                        editor.putString(PREF_ACCOUNT_NAME, accountName);
                if (resultCode == RESULT_OK) {

     * Respond to requests for permissions at runtime for API 23 and above.
     * @param requestCode The request code passed in
     *     requestPermissions(android.app.Activity, String, int, String[])
     * @param permissions The requested permissions. Never null.
     * @param grantResults The grant results for the corresponding permissions
     *     which is either PERMISSION_GRANTED or PERMISSION_DENIED. Never null.
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
                requestCode, permissions, grantResults, this);

     * Callback for when a permission is granted using the EasyPermissions
     * library.
     * @param requestCode The request code associated with the requested
     *         permission
     * @param list The requested permission list. Never null.
    public void onPermissionsGranted(int requestCode, List<String> list) {
        // Do nothing.

     * Callback for when a permission is denied using the EasyPermissions
     * library.
     * @param requestCode The request code associated with the requested
     *         permission
     * @param list The requested permission list. Never null.
    public void onPermissionsDenied(int requestCode, List<String> list) {
        // Do nothing.

     * Checks whether the device currently has a network connection.
     * @return true if the device has a network connection, false otherwise.
    private boolean isDeviceOnline() {
        ConnectivityManager connMgr =
                (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        return (networkInfo != null && networkInfo.isConnected());

     * Check that Google Play services APK is installed and up to date.
     * @return true if Google Play Services is available and up to
     *     date on this device; false otherwise.
    private boolean isGooglePlayServicesAvailable() {
        GoogleApiAvailability apiAvailability =
        final int connectionStatusCode =
        return connectionStatusCode == ConnectionResult.SUCCESS;

     * Attempt to resolve a missing, out-of-date, invalid or disabled Google
     * Play Services installation via a user dialog, if possible.
    private void acquireGooglePlayServices() {
        GoogleApiAvailability apiAvailability =
        final int connectionStatusCode =
        if (apiAvailability.isUserResolvableError(connectionStatusCode)) {

     * Display an error dialog showing that Google Play Services is missing
     * or out of date.
     * @param connectionStatusCode code describing the presence (or lack of)
     *     Google Play Services on this device.
    void showGooglePlayServicesAvailabilityErrorDialog(
            final int connectionStatusCode) {
        GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
        Dialog dialog = apiAvailability.getErrorDialog(

     * An asynchronous task that handles the Google Calendar API call.
     * Placing the API calls in their own task ensures the UI stays responsive.
    private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
        private com.google.api.services.calendar.Calendar mService = null;
        private Exception mLastError = null;

        MakeRequestTask(GoogleAccountCredential credential) {
            HttpTransport transport = AndroidHttp.newCompatibleTransport();
            JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
            mService = new com.google.api.services.calendar.Calendar.Builder(
                    transport, jsonFactory, credential)
                    .setApplicationName("Google Calendar API Android Quickstart")

         * Background task to call Google Calendar API.
         * @param params no parameters needed for this task.
        protected List<String> doInBackground(Void... params) {
            try {
                return getDataFromApi();
            } catch (Exception e) {
                mLastError = e;
                return null;

         * Fetch a list of the next 10 events from the primary calendar.
         * @return List of Strings describing returned events.
         * @throws IOException
        private List<String> getDataFromApi() throws IOException {
            // List the next 10 events from the primary calendar.
            DateTime now = new DateTime(System.currentTimeMillis());
            List<String> eventStrings = new ArrayList<String>();
            Events events = mService.events().list("primary")
            List<Event> items = events.getItems();

            for (Event event : items) {
                DateTime start = event.getStart().getDateTime();
                if (start == null) {
                    // All-day events don't have start times, so just use
                    // the start date.
                    start = event.getStart().getDate();
                        String.format("%s (%s)", event.getSummary(), start));
            return eventStrings;

        protected void onPreExecute() {

        protected void onPostExecute(List<String> output) {
            if (output == null || output.size() == 0) {
                mOutputText.setText("No results returned.");
            } else {
                output.add(0, "Data retrieved using the Google Calendar API:");
                mOutputText.setText(TextUtils.join("\n", output));

        protected void onCancelled() {
            if (mLastError != null) {
                if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
                            ((GooglePlayServicesAvailabilityIOException) mLastError)
                } else if (mLastError instanceof UserRecoverableAuthIOException) {
                            ((UserRecoverableAuthIOException) mLastError).getIntent(),
                } else {
                    mOutputText.setText("The following error occurred:\n"
                            + mLastError.getMessage());
            } else {
                mOutputText.setText("Request cancelled.");

Step 5: Run the app





Working with Calabash

Hi All,

Now we know how to install and run Calabash and its all requirements and prerequisites.

Now let’s see how to work with it.

Open the “calabash-android-0.9.0” folder. It resides at path C:\Ruby23\lib\ruby\gems\2.3.0\gems\calabash-android-0.9.0. The folder names will change in synch with the ruby/ calabash version you install on your machine.

Open the feature skeleton folder. Look out for this basic framework.

  • The *.feature file contains scenarios that we are going to automate.
  • The method used by the feature file is written in *.rb file inside “step_definitions” folder.
  • Common methods, environment setup, app installation and hooks should be placed inside “support” folder.

Resign & Build the app

  • Calabash-android resign *.apk
  • Calabash-android build *.apk

Attach the device to the system /Open the emulator

Check device attached. Type command >>adb devices

Attached devices list should be displayed.

How to Find the Element Locator

  • Open the console. Type the Command.>>calabash android console “APK Path”>>start_test_server_in_background
  • Above command launch the app on the device. To find the element locator use following command.>query “*”

Creating New Scripts

Open the feature file and following lines

Feature: Login feature
 Scenario: As a valid user I can log into my app
 When I press "Login"
 And I enter my username 
 And I enter my password
 Then I see "Welcome to coolest app ever"

Open the Step Definition file & Define the method into *.rb file.

Given /^I am on the login windows$/ do
 wait_for(:timeout =>100) { element_exists("* id:'loginInput;")}
 check_element_exists("* id:'loginInput;")
Now you can automate your UI testing using the Calabash.