Browse Category: Android

Butter Knife

Butterknife is a light weight library to inject views into Android components. It uses annotation processing.

The @BindView annotation allow to inject views and performs the cast to the correct type for you. The @@OnClick(R.id.yourid) annotation allows to add OnClickListener to a view. You can optional define the method parameter of the view in case you want it injected.

Butterknife includes also findById methods which simplify code that still has to find views on a View, Activity, or Dialog. It uses generics to infer the return type and automatically performs the cast.

http://www.vogella.com/tutorials/AndroidButterknife/article.html

Convert String to PrivateKey

Below code works to convert string to PrivateKey


public static class DecryptionUtil {
    private static final String ASYMMETRIC_ALGO =
            "RSA/ECB/PKCS1Padding";

    public static byte[] decryptUsingPrivateKey(PrivateKey privateKey, byte[] data)
            throws IOException, GeneralSecurityException {
        Cipher pkCipher = Cipher.getInstance(ASYMMETRIC_ALGO);
        pkCipher.init(Cipher.DECRYPT_MODE, privateKey);
        return pkCipher.doFinal(data);
    }

    public static byte[] decryptUsingSymmetricKey(byte[] symmetricKey, byte[]
            data) throws InvalidCipherTextException {
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new
                AESEngine(), new PKCS7Padding());
        cipher.init(false, new KeyParameter(symmetricKey));
        int outputSize = cipher.getOutputSize(data.length);
        byte[] tempOP = new byte[outputSize];
        int processLen = cipher.processBytes(data, 0, data.length, tempOP, 0);
        int outputLen = cipher.doFinal(tempOP, processLen);
        byte[] result = new byte[processLen + outputLen];
        System.arraycopy(tempOP, 0, result, 0, result.length);
        return result;
    }
}

public static PrivateKey getPrivateKey(String privateString) {

    PrivateKey privateKey = null;

    try {
       // String privateString = getString(key, context);
        if(privateString!=null){
            byte[] binCpk = Base64.decode(privateString,Base64.DEFAULT);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA","BC");
            PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(binCpk);
            privateKey = keyFactory.generatePrivate(privateKeySpec);

        }
    }
    catch(Exception e){
        String r="";
    }
    return privateKey;
}

Virtual Assistant

A virtual assistant is a software agent that can perform tasks or services for an individual. Sometimes the term “chatbot” is used to refer to virtual assistants generally or specifically those accessed by online chat (or in some cases online chat programs that are for entertainment and not useful purposes).

As of 2017, the capabilities and usage of virtual assistants is expanding rapidly, with new products entering the market. An online poll in May 2017 found the most widely used in the US were Apple’s Siri (34%), Google Assistant (19%), Amazon Alexa (6%), and Microsoft Cortana(4%). Facebook’s M is expected to be available to hundreds of millions on Facebook Messenger in 2017.

 

Cortana

Cortana is an operating system-oriented voice assistant available on Windows 10 devices, as well as the Xbox One console. Cortana is closely connected to productivity, but can also help answer more general questions by pulling information from Bing.

The Cortana VA has seen a lot of recent growth, expanding her use throughout Windows 10 and related services. Combined with newer offerings like Surface Studio, its clear Microsoft favors Cortana as an OS-based service to control Windows 10 while one is working.

While user can store specific bits of information with Cortana, Microsoft’s virtual assistant is constantly analyzing user’s interactions to learn more about him/her. This info is stored in something Microsoft calls the “Notebook,” which includes the places user likes to go, people he/she care about, user’s preferred quiet hours, and things he/she might be interested in, among other things. User can even edit it if he like.

Cortana can user’s emails, track user’s location, watch user’s browsing history, check user’s contact list, keep an eye on user’s calendar, and put all this data together to suggest useful info, if user allow it to. Cortana is designed to recognize context, so it should be able to understand follow-up requests, and you can phrase things in different ways and still expect a useful answer. User can also type his/her questions or requests, if you prefer to not speak out loud.

The latest changes from the Windows 10 Creators Update allow Cortana to help in the setup process for new computers, and include a new full screen mode for Cortana that serves as both a screensaver and voice-assistant focused mode when user is away from the computer—or is too far away to type. Cortana can also handle music and reminder commands more effectively, spanning multiple music apps and controlling volume as user desire.

 

Siri

Siri has been an integral part of iOS since the launch of iOS 5 in 2011. It started with the basics such as weather and messaging, but has expanded greatly since then to support more third-party integration with MacOS.

While Siri’s jokes are legendary, the virtual assistant is getting more capable every day. Now, user can ask it to call people, send messages, schedule meetings, launch apps and games, play music, answer questions, set reminders, and provide weather forecasts.

Siri can also integrate with third-party apps and understand follow-up queries. That’s a big change in strategy for Apple, which typically maintains a tight grip on which third-party companies get access to its native functions.

Siri is probably the most familiar of all the voice assistants. It also lags behind the other VAs when it comes to text input, which isn’t supported for most Siri functions. Apple appears to be using Siri for voice controls and Spotlight for similar text-based queries.

The latest news for Siri includes voice compatibility for WhatsApp, expanded payment options for Lyft and Uber, and the ability to look up international cricket scores. These are minor tweaks compared to the changes other VAs are going through, but they also point to Siri’s continued stability—particularly for long-term iOS users who already know the voice assistant well.

 

Google Assistant

Google Assistant (which has incorporated functions from the older Google Now, as Now is being phased out) is different from Cortana and Siri. It has less personality, but more functionality. While it is an integral part of Android, Google Assistant also lives in an iOS app, and can be accessed through the Chrome browser as needed.

Like Cortana and Siri, you can ask Assistant for directions to the closest Chinese restaurant, or what the weather looks like for the next 10 days. If you let it, Google’s software will utilize your search history and customize its responses based on what it knows about your queries.

Google’s integration with its search engine makes Google Assistant one of the most useful virtual assistants out of the box. It already has a treasure trove of data on what you’ve done on the web. It also reacts to questions in a similar way to the Google browser, which makes it great for general information and trivia.

 

Alexa

It is Amazon’s voice assistant and it isn’t focused on mobile or computer purposes, but rather for the standalone Amazon Echo speaker and a limited number of Amazon Fire devices, with a greater concentration on whole-house management and services rather than computer-oriented tasks.

Obviously, this limits Alexa compared to the alternatives. However, there are some advantages to the Amazon approach. Like Assistant, Alexa is highly conversational, and its ability to parse meaning is frequently excellent, whether you’re asking about the weather or listening to the latest news summaries from around the web. Alexa is meant to be used out in the open, away from the computer, while you’re working elsewhere but still need information, entertainment, or purchases.

The customization and management options for Alexa also impress. While other voice assistants hide many of their capabilities away from users, Alexa brings them all out in the form of “skills” and connections. The Alexa app allows you to add various mini-apps in the form of skills, and adjust current services and settings using these skills. It’s a great system, especially for those who like to tinker, but it does require learning a new approach to VA management.

Amazon is also doing a lot of work to bring Alexa into more mobile situations: The Alexa app, for example, brings many of its capabilities to your phone so you can organize lists while driving or control smart home features away from an Echo.

 

 

Bixby

Not to be outdone in the voice assistant game, Samsung has also created a mobile device assistant called Bixby, which now has full voice command compatibility (if you’ve picked up a Galaxy S8, you’ve probably encountered it). In general, Bixby shares a lot in common with Cortana. The VA lingers on the Galaxy phone, ready to access information and manage your data, schedule, events, and more. It doesn’t venture out into the Internet of Things much, but it does have an impressive amount of control over everything you do on your Samsung device.

You can divide Bixby into three basic different categories of abilities—Voice, Home, and Vision. They all work together, but use different Bixby abilities:

Voice includes both questions—”What’s the weather today?”—and commands. Start by saying “Hey Bixby” and you can get general information or facts. However, like Cortana, Bixby also excels at operating software, so you can also use it to control the Galaxy menus, change settings, set reminders, take pictures, edit video, and much, much more. If you’ve ever wanted to operate your smartphone hands free, there’s a lot to explore here. Some functionality goes even deeper – you can ask Bixby to read out your latest emails, or tell it to post your photo to Instagram, and Bixby will do so.

Home is the app face of Bixby, a screen that provides information based on what you have asked Bixby about in the past, as well as the different services that Bixby can control with the right compatibility—Including Facebook, CNN, and Spotify. In the future this area may include smart home capabilities (Samsung says it’s on the way), but for now it’s relegated to basic online services.

Vision is the most unique part of Bixby, as it can analyze what image the camera is picking up and give you a report on it. When this works (say, looking at a recognizable logo) Bixby can help you instantly compare online prices to in-store prices, or give you more information about local landmarks. If this feature takes off, other voice assistants may start getting jealous.

 

 

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

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

 

 

 

 

Uploading image to Google Drive from Android

Below code will help to upload image directly to your google drive

private void saveFileToDrive() {

    final Bitmap image = mBitmapToSave;
    Drive.DriveApi.newDriveContents(getGoogleApiClient())
            .setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {

                @Override
                public void onResult(DriveApi.DriveContentsResult result) {

                    if (!result.getStatus().isSuccess()) {
                        Log.i("ERROR", "Failed to create new contents.");
                        return;
                    }

                    final DriveContents driveContents = result.getDriveContents();

                    new Thread() {
                        @Override
                        public void run() {
                            // write content to DriveContents
                            OutputStream outputStream = driveContents.getOutputStream();
                            // Write the bitmap data from it.
                            ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
                            image.compress(Bitmap.CompressFormat.PNG, 100, bitmapStream);
                            try {
                                outputStream.write(bitmapStream.toByteArray());
                            } catch (IOException e1) {
                                Log.i("ERROR", "Unable to write file contents.");
                            }
                            // Create the initial metadata - MIME type and title.
                            // Note that the user will be able to change the title later.
                            MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
                                    .setMimeType("image/jpeg").setTitle("Android Photo.png").build();
                            // Create an intent for the file chooser, and start it.
                            IntentSender intentSender = Drive.DriveApi
                                    .newCreateFileActivityBuilder()
                                    .setInitialMetadata(metadataChangeSet)
                                    .setInitialDriveContents(driveContents)
                                    .build(getGoogleApiClient());
                            try {
                                startIntentSenderForResult(
                                        intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
                            } catch (IntentSender.SendIntentException e) {
                                Log.i("ERROR", "Failed to launch file chooser.");
                            }
                        }
                    }.start();


                }
            });
}

Maintain cookie session in Android(Retrofit)

A session is a sequence of requests made by a single end-user during a visit to a particular site. A session or query session may be all queries made by a user in a particular time period or it may also be a series of queries or navigation with a consistent underlying user need.

In Android, if we use the retrofit for web services call it internally uses OkHttp and OkHttp does not keep the track of session automatically. Generally, the session is maintained using the cookie value that we get in each response we receive.

So, we need to keep the cookie from one call to another. this can be down using CookieManager as follows:

HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

CookieHandler cookieHandler = new CookieManager();
OkHttpClient client = new OkHttpClient.Builder().addNetworkInterceptor(interceptor)
.cookieJar(new JavaNetCookieJar(cookieHandler))
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();

for this following dependencies are required:

compile ‘com.squareup.okhttp3:logging-interceptor:3.4.1’
compile ‘com.squareup.okhttp3:okhttp:3.4.1’
compile ‘com.squareup.okhttp3:okhttp-urlconnection:3.6.0’