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.

<apex:outputTextvalue=”{!$Cache.Org.myNamespace.myPartition.key1}”/>

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.

e.g:

Glide
    .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?.addSubview(view_BGDimmer)

          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

            self.View_alternativeForXib.removeFromSuperview()

            self.view.layoutIfNeeded()

        }) { (completed) in

            self.view_BGDimmer.removeFromSuperview()

        }

    }

 

 

Thanks,

 

 

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:

<dependency>
  <groupId>com.squareup.moshi</groupId>
  <artifactId>moshi</artifactId>
  <version>1.5.0</version>
</dependency>

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);
System.out.println(blackjackHand);

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 {
  CLUBS, DIAMONDS, HEARTS, SPADES;
}

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.

Overview

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.

Requirements

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

Installation

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

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

Usage

Writing a new JobService

The simplest possible JobService:

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

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

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

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

Adding it to the manifest

<service
    android:exported="false"
    android:name=".MyJobService">
    <intent-filter>
        <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
    </intent-filter>
</service>

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
    .build();

dispatcher.mustSchedule(myJob);

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
    .setService(MyJobService.class)
    // uniquely identifies the job
    .setTag("my-unique-tag")
    // one-off job
    .setRecurring(false)
    // don't persist past a device reboot
    .setLifetime(Lifetime.UNTIL_NEXT_BOOT)
    // start between 0 and 60 seconds from now
    .setTrigger(Trigger.executionWindow(0, 60))
    // don't overwrite an existing job with the same tag
    .setReplaceCurrent(false)
    // retry with exponential backoff
    .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
    // constraints that need to be satisfied for the job to run
    .setConstraints(
        // only run on an unmetered network
        Constraint.ON_UNMETERED_NETWORK,
        // only run when the device is charging
        Constraint.DEVICE_CHARGING
    )
    .setExtras(myExtrasBundle)
    .build();

dispatcher.mustSchedule(myJob);

Cancelling a job

dispatcher.cancel("my-unique-tag");

Cancelling all jobs

dispatcher.cancelAll();

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.
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout activityLayout = new LinearLayout(this);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT);
        activityLayout.setLayoutParams(lp);
        activityLayout.setOrientation(LinearLayout.VERTICAL);
        activityLayout.setPadding(16, 16, 16, 16);

        ViewGroup.LayoutParams tlp = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);

        mCallApiButton = new Button(this);
        mCallApiButton.setText(BUTTON_TEXT);
        mCallApiButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCallApiButton.setEnabled(false);
                mOutputText.setText("");
                getResultsFromApi();
                mCallApiButton.setEnabled(true);
            }
        });
        activityLayout.addView(mCallApiButton);

        mOutputText = new TextView(this);
        mOutputText.setLayoutParams(tlp);
        mOutputText.setPadding(16, 16, 16, 16);
        mOutputText.setVerticalScrollBarEnabled(true);
        mOutputText.setMovementMethod(new ScrollingMovementMethod());
        mOutputText.setText(
                "Click the \'" + BUTTON_TEXT +"\' button to test the API.");
        activityLayout.addView(mOutputText);

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

        setContentView(activityLayout);

        // 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()) {
            acquireGooglePlayServices();
        } else if (mCredential.getSelectedAccountName() == null) {
            chooseAccount();
        } 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.
     */
    @AfterPermissionGranted(REQUEST_PERMISSION_GET_ACCOUNTS)
    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) {
                mCredential.setSelectedAccountName(accountName);
                getResultsFromApi();
            } else {
                // Start a dialog from which the user can choose an account
                startActivityForResult(
                        mCredential.newChooseAccountIntent(),
                        REQUEST_ACCOUNT_PICKER);
            }
        } else {
            // Request the GET_ACCOUNTS permission via a user dialog
            EasyPermissions.requestPermissions(
                    this,
                    "This app needs to access your Google account (via Contacts).",
                    REQUEST_PERMISSION_GET_ACCOUNTS,
                    Manifest.permission.GET_ACCOUNTS);
        }
    }

    /**
     * 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.
     */
    @Override
    protected void onActivityResult(
            int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch(requestCode) {
            case REQUEST_GOOGLE_PLAY_SERVICES:
                if (resultCode != RESULT_OK) {
                    mOutputText.setText(
                            "This app requires Google Play Services. Please install " +
                            "Google Play Services on your device and relaunch this app.");
                } else {
                    getResultsFromApi();
                }
                break;
            case REQUEST_ACCOUNT_PICKER:
                if (resultCode == RESULT_OK && data != null &&
                        data.getExtras() != null) {
                    String accountName =
                            data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                    if (accountName != null) {
                        SharedPreferences settings =
                                getPreferences(Context.MODE_PRIVATE);
                        SharedPreferences.Editor editor = settings.edit();
                        editor.putString(PREF_ACCOUNT_NAME, accountName);
                        editor.apply();
                        mCredential.setSelectedAccountName(accountName);
                        getResultsFromApi();
                    }
                }
                break;
            case REQUEST_AUTHORIZATION:
                if (resultCode == RESULT_OK) {
                    getResultsFromApi();
                }
                break;
        }
    }

    /**
     * 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.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(
                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.
     */
    @Override
    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.
     */
    @Override
    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 =
                GoogleApiAvailability.getInstance();
        final int connectionStatusCode =
                apiAvailability.isGooglePlayServicesAvailable(this);
        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 =
                GoogleApiAvailability.getInstance();
        final int connectionStatusCode =
                apiAvailability.isGooglePlayServicesAvailable(this);
        if (apiAvailability.isUserResolvableError(connectionStatusCode)) {
            showGooglePlayServicesAvailabilityErrorDialog(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(
                MainActivity.this,
                connectionStatusCode,
                REQUEST_GOOGLE_PLAY_SERVICES);
        dialog.show();
    }

    /**
     * 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")
                    .build();
        }

        /**
         * Background task to call Google Calendar API.
         * @param params no parameters needed for this task.
         */
        @Override
        protected List<String> doInBackground(Void... params) {
            try {
                return getDataFromApi();
            } catch (Exception e) {
                mLastError = e;
                cancel(true);
                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")
                    .setMaxResults(10)
                    .setTimeMin(now)
                    .setOrderBy("startTime")
                    .setSingleEvents(true)
                    .execute();
            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();
                }
                eventStrings.add(
                        String.format("%s (%s)", event.getSummary(), start));
            }
            return eventStrings;
        }


        @Override
        protected void onPreExecute() {
            mOutputText.setText("");
            mProgress.show();
        }

        @Override
        protected void onPostExecute(List<String> output) {
            mProgress.hide();
            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));
            }
        }

        @Override
        protected void onCancelled() {
            mProgress.hide();
            if (mLastError != null) {
                if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
                    showGooglePlayServicesAvailabilityErrorDialog(
                            ((GooglePlayServicesAvailabilityIOException) mLastError)
                                    .getConnectionStatusCode());
                } else if (mLastError instanceof UserRecoverableAuthIOException) {
                    startActivityForResult(
                            ((UserRecoverableAuthIOException) mLastError).getIntent(),
                            MainActivity.REQUEST_AUTHORIZATION);
                } 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;")
end.
Now you can automate your UI testing using the Calabash.

Top 5 PHP Frameworks of 2017

List of top 5 PHP Frameworks of 2017

Before beginning the list of top 5 PHP frameworks of 2017, PHP is one of the most favored server-side scripting languages known for its simplicity, PHP frameworks complement PHP, by providing developers with some pre-built modules, a platform to create robust, reusable components, and by enabling faster development cycles.

PHP frameworks give the users a basic structure, with some pre-built modules to develop robust web applications faster. These frameworks enforce coding standards and development guidelines hence standardizing the process and stabilizing the product.

PHP frameworks use Model View Controller(MVC) architecture, where the development of the business logic is independent of both the underlying data and the overlaying presentation view. MVC helps developers to focus on their specific areas without worrying if their code will adversely affecting the development of the other modules or not. This breaking up of the development process into independent modules increases the speed of the entire development process and improves the stability and quality of the product.

Advantages of using frameworks

  • Rapid development using the libraries and tools provided by the framework
  • Easy to upgrade and maintain the developed applications
  • Excellent community support
  • Security features such as Input filtering and Output encoding

Top 5 PHP frameworks of 2017

There are a wide variety of PHP frameworks, many of them are open source frameworks. The most popular open-source PHP frameworks are:

google trends

  1. Laravel

As far as frameworks go, Laravel takes the cake with the most number of personal and professional users. The 2015’s Sitepoint survey indicates that excellent documentation, solid features and a thriving, growing support community has made Laravel a clear winner in the space of PHP framework. Google trends on PHP frameworks show similar results.

  1. Symfony

One of the older players, Symfony is considered to be a stable base for many other newer frameworks including Laravel. The quick adaptability and widely used documentation of Symfony makes it one of the most dependable PHP frameworks.

  1. CodeIgniter

A simple, powerful PHP framework, CodeIgniter is known for its flexibility and hassle-free installation. CodeIgniter is supposed to have an easy learning curve thus making it the best choice for beginners.

  1. CakePHP

One of the oldest frameworks, CakePHP has retained its strong user base and has continued to grow. It also boasts of an impressive portfolio consisting of brands such as BMW and Express.

  1. Zend Framework

Zend is considered to be a very stable and robust framework recommended for big, enterprise-level projects. It has a wide variety of features which facilitates the development of quality applications for enterprise clients.