org.qeo.deviceregistration.ui.GplusFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.qeo.deviceregistration.ui.GplusFragment.java

Source

/*
 * Copyright (c) 2015 - Qeo LLC
 *
 * The source code form of this Qeo Open Source Project component is subject
 * to the terms of the Clear BSD license.
 *
 * You can redistribute it and/or modify it under the terms of the Clear BSD
 * License (http://directory.fsf.org/wiki/License:ClearBSD). See LICENSE file
 * for more details.
 *
 * The Qeo Open Source Project also includes third party Open Source Software.
 * See LICENSE file for more details.
 */

package org.qeo.deviceregistration.ui;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.qeo.android.service.ui.R;
import org.qeo.android.service.ServiceApplication;
import org.qeo.deviceregistration.service.OAuthTokenService;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.actionbarsherlock.app.SherlockFragment;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.plus.Plus;

/**
 * Google plus login fragment.
 */
public class GplusFragment extends SherlockFragment implements OnClickListener, GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener, View.OnTouchListener {

    private static final Logger LOG = Logger.getLogger("GplusFragment");

    // private static final int DIALOG_GET_GOOGLE_PLAY_SERVICES = 1;
    private static final int REQUEST_CODE_SIGN_IN = 1;
    private static final int REQUEST_CODE_GET_GOOGLE_PLAY_SERVICES = 2;

    private GoogleApiClient mGoogleApiClient;

    private Button mGplusButtonSignIn;
    private Button mButtonOther;
    private ConnectionResult mConnectionResult;
    private TextView mTextViewStatus;
    private boolean mDowntouch = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LOG.finest("onCreate");
        GoogleApiClient.Builder builder = new GoogleApiClient.Builder(getActivity());
        builder.addApi(Plus.API);
        builder.addScope(Plus.SCOPE_PLUS_PROFILE);
        builder.addConnectionCallbacks(this);
        builder.addOnConnectionFailedListener(this);
        mGoogleApiClient = builder.build();
        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        LOG.finest("onCreateView");
        View rootView = inflater.inflate(R.layout.fragment_gplus, container, false);

        mGplusButtonSignIn = (Button) rootView.findViewById(R.id.fragmentGplus_Button_signIn);
        mGplusButtonSignIn.setOnClickListener(this);
        mGplusButtonSignIn.setEnabled(false);
        mGplusButtonSignIn.setOnTouchListener(this);
        mButtonOther = (Button) rootView.findViewById(R.id.fragmentGplus_Button_other);
        mButtonOther.setOnClickListener(this);
        mTextViewStatus = (TextView) rootView.findViewById(R.id.fragmentGplus_TextView_Status);
        mTextViewStatus.setVisibility(View.INVISIBLE);

        return rootView;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        LOG.fine("OnActivityResult: " + requestCode + " -- " + resultCode);
        if (requestCode == REQUEST_CODE_SIGN_IN || requestCode == REQUEST_CODE_GET_GOOGLE_PLAY_SERVICES) {
            if (resultCode == Activity.RESULT_CANCELED) {
                updateButtons(false);
                getActivity().setProgressBarIndeterminateVisibility(false);
            } else if (resultCode == Activity.RESULT_OK) {
                LOG.fine("OnActivityResult: RESULT_OK");
                if (!mGoogleApiClient.isConnected()) {
                    LOG.fine("OnActivityResult: Google api not yet connected");
                    if (!mGoogleApiClient.isConnecting()) {
                        LOG.fine("OnActivityResult: start google api connect");
                        // This time, connect should succeed.
                        mGoogleApiClient.connect();
                    } else {
                        LOG.fine("OnActivityResult: Google api connect already in progress");
                    }
                }
            }
        }
    }

    @Override
    public void onClick(View view) {
        LOG.finest("onClick");

        int id = view.getId();
        if (id == R.id.fragmentGplus_Button_signIn) {
            int available = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity());
            if (available != ConnectionResult.SUCCESS) {
                LOG.warning("Google play services error: " + available);
                if (GooglePlayServicesUtil.isUserRecoverableError(available)) {
                    GooglePlayServicesUtil.showErrorDialogFragment(available, getActivity(),
                            REQUEST_CODE_GET_GOOGLE_PLAY_SERVICES);
                }
                new AlertDialog.Builder(getActivity())
                        .setMessage(getString(R.string.google_play_service_not_supported)).setCancelable(true)
                        .show();
                return;
            }

            try {
                LOG.info("Signing in to Google plus");
                mGplusButtonSignIn.setEnabled(false);
                mGplusButtonSignIn.setBackgroundResource(R.drawable.common_signin_btn_text_disabled_dark);
                mTextViewStatus.setVisibility(View.VISIBLE);
                mTextViewStatus.setText("Signing in to Google+");
                getActivity().setProgressBarIndeterminateVisibility(true);
                mConnectionResult.startResolutionForResult(getActivity(), REQUEST_CODE_SIGN_IN);
            } catch (IntentSender.SendIntentException e) {
                // Fetch a new result to start.
                mGoogleApiClient.connect();
            }
        } else if (id == R.id.fragmentGplus_Button_other) {
            WebviewFragment fragment = new WebviewFragment();
            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();

            // Replace whatever is in the fragment_container view with this fragment,
            // and add the transaction to the back stack so the user can navigate back
            transaction.replace(R.id.containerSingleFragment, fragment);
            transaction.addToBackStack(null);

            // Commit the transaction
            transaction.commit();
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //react to touch events for sign in button
        if (v.getId() == mGplusButtonSignIn.getId()) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                mGplusButtonSignIn.setBackgroundResource(R.drawable.common_signin_btn_text_focus_dark);
                mDowntouch = true;
            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                mGplusButtonSignIn.setBackgroundResource(R.drawable.common_signin_btn_text_dark);
                if (mDowntouch) {
                    mDowntouch = false;
                    v.performClick();
                }
            }
        }
        return false;
    }

    @Override
    public void onStart() {
        super.onStart();
        LOG.finest("onStart");
        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mBroadcastReceiverLogin,
                new IntentFilter(OAuthTokenService.ACTION_OAUTH_TOKEN_READY));
        mGoogleApiClient.connect();
    }

    @Override
    public void onStop() {
        LOG.finest("onStop");
        LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mBroadcastReceiverLogin);
        mGoogleApiClient.disconnect();
        super.onStop();
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        LOG.fine("onConnected");
        updateButtons(true); // signed in
        getServerToken();
    }

    @Override
    public void onConnectionSuspended(int cause) {
        LOG.fine("onConnectionsSuspended");
        // mSignInStatus.setText(R.string.loading_status);
        mGoogleApiClient.connect();
        updateButtons(false); // signed out
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        LOG.fine("onConnectionFailed");
        mConnectionResult = result;
        mGplusButtonSignIn.setEnabled(true);
        updateButtons(false); // signed out
    }

    private void updateButtons(boolean isSignedIn) {
        LOG.fine("UpdateButtons: " + isSignedIn + " -- " + mConnectionResult);
        if (isSignedIn) {
            //mGplusButtonSignIn.setVisibility(View.INVISIBLE);
        } else {
            if (mConnectionResult == null) {
                // Disable the sign-in button until onConnectionFailed is called with result.
                mGplusButtonSignIn.setVisibility(View.INVISIBLE);
                // mSignInStatus.setText(getString(R.string.loading_status));
            } else {
                // Enable the sign-in button since a connection result is available.
                mGplusButtonSignIn.setVisibility(View.VISIBLE);
                mGplusButtonSignIn.setEnabled(true);
                mGplusButtonSignIn.setBackgroundResource(R.drawable.common_signin_btn_text_normal_dark);
                mTextViewStatus.setVisibility(View.INVISIBLE);
            }
        }
    }

    private void getServerToken() {
        LOG.fine("GetServerToken");
        AsyncTask<Void, Void, String> myTask = new AsyncTask<Void, Void, String>() {

            @Override
            protected String doInBackground(Void... params) {
                String myApiKey = ServiceApplication.getMetaData(ServiceApplication.META_DATA_GOOGLE_CLIENT_ID);
                LOG.fine("Using google client id: " + myApiKey);

                String scopes = "audience:server:client_id:" + myApiKey;
                String jwt = null;
                try {
                    jwt = GoogleAuthUtil.getToken(getActivity(), // Context context
                            Plus.AccountApi.getAccountName(mGoogleApiClient), // String accountName
                            scopes // String scope
                    );
                } catch (IOException transientEx) {
                    // network or server error, the call is expected to succeed if you try again later.
                    // Don't attempt to call again immediately - the request is likely to
                    // fail, you'll hit quotas or back-off.
                    LOG.log(Level.WARNING, "IOException", transientEx);
                } catch (UserRecoverableAuthException e) {
                    // Requesting an authorization code will always throw
                    // UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken
                    // because the user must consent to offline access to their data. After
                    // consent is granted control is returned to your activity in onActivityResult
                    // and the second call to GoogleAuthUtil.getToken will succeed.
                    // startActivityForResult(e.getIntent(), AUTH_CODE_REQUEST_CODE);
                    LOG.log(Level.WARNING, "UserRecoverableAuthException", e);
                } catch (GoogleAuthException authEx) {
                    // Failure. The call is not expected to ever succeed so it should not be
                    // retried.
                    LOG.log(Level.WARNING, "authEx", authEx);
                }

                LOG.fine("JWT token: " + jwt);
                return jwt;
            }

            @Override
            protected void onPostExecute(String jwt) {
                LOG.fine("Got JWT, starting OAuthTokenService");

                mTextViewStatus.setVisibility(View.VISIBLE);
                mTextViewStatus.setText("Signing in to Qeo");
                // start the oauth service
                Intent i = new Intent(getActivity(), OAuthTokenService.class);
                i.putExtra(OAuthTokenService.INTENT_EXTRA_JWT, jwt);
                getActivity().startService(i);
            }
        };
        myTask.execute();

    }

    private BroadcastReceiver mBroadcastReceiverLogin = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(OAuthTokenService.ACTION_OAUTH_TOKEN_READY)) {
                boolean result = intent.getBooleanExtra(OAuthTokenService.INTENT_EXTRA_SUCCESS, false);
                if (!result) {
                    LOG.fine("Authentication problem. Sign our from google+");
                    Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
                    mGoogleApiClient.disconnect();
                    mGoogleApiClient.connect();
                    getActivity().setProgressBarIndeterminateVisibility(false);
                }
            }
        }
    };
}