org.fathens.cordova.googleplus.GooglePlusConnect.java Source code

Java tutorial

Introduction

Here is the source code for org.fathens.cordova.googleplus.GooglePlusConnect.java

Source

/*
   Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
   distributed with this work for additional information
   regarding copyright ownership.  The ASF licenses this file
   to you under the Apache License, Version 2.0 (the
   "License"); you may not use this file except in compliance
   with the License.  You may obtain a copy of the License at
    
     http://www.apache.org/licenses/LICENSE-2.0
    
   Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   KIND, either express or implied.  See the License for the
   specific language governing permissions and limitations
   under the License.
 */

package org.fathens.cordova.googleplus;

import java.io.IOException;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaArgs;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.json.JSONException;
import org.json.JSONObject;

import android.accounts.AccountManager;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

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.AccountPicker;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.Scopes;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.plus.Plus;
import com.google.android.gms.plus.PlusClient;
import com.google.android.gms.plus.model.people.Person;

public class GooglePlusConnect extends CordovaPlugin {
    private static final String TAG = "GooglePlusPlugin";

    public static final int REQUEST_PICK_ACCOUNT = 9000;
    public static final int REQUEST_AUTH_RECOVER = 9001;
    public static final int REQUEST_PCLIENT_RECOVER = 9002;
    public static final int REQUEST_GCLIENT_RECOVER = 9003;

    public static final String ACTION_LOGIN = "login";
    public static final String ACTION_DISCONNECT = "disconnect";
    public static final String ACTION_PROFILE = "profile";

    private static final String[] scopeUrls = new String[] { Scopes.PLUS_LOGIN,
            "https://www.googleapis.com/auth/userinfo.email" };

    private CallbackContext currentCallback;
    private PlusClient pClient;
    private GoogleApiClient gClient;
    private String accountName;
    private String[] actions = new String[] { "https://schemas.google.com/AddActivity" };

    @Override
    public void initialize(final CordovaInterface cordova, final CordovaWebView webView) {
        super.initialize(cordova, webView);
        Log.d(TAG, "Initialized");
    }

    @Override
    public boolean execute(final String action, final CordovaArgs args, final CallbackContext callback)
            throws JSONException {
        currentCallback = callback;
        accountName = args.optString(0);
        if (action.equals(ACTION_LOGIN)) {
            login();
            return true;
        } else if (action.equals(ACTION_DISCONNECT)) {
            disconnect();
            return true;
        } else if (action.equals(ACTION_PROFILE)) {
            profile();
            return true;
        } else {
            return false;
        }
    }

    private void login() {
        if (accountName != null && accountName.length() > 0) {
            obtainToken();
        } else {
            final Intent picker = AccountPicker.newChooseAccountIntent(null, null,
                    new String[] { GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE }, true, null, null, null, null);
            cordova.startActivityForResult(this, picker, REQUEST_PICK_ACCOUNT);
        }
    }

    private void obtainToken() {
        final String scoping = String.format("oauth2:%s", TextUtils.join(" ", scopeUrls));
        Log.d(TAG, "Obtaining token by user(" + accountName + "): " + scoping);
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Log.d(TAG, "First try to get token");
                    final String waste = GoogleAuthUtil.getToken(cordova.getActivity(), accountName, scoping);
                    // TODO Check token if valid
                    Log.d(TAG, "Clearing the token: " + waste);
                    GoogleAuthUtil.clearToken(cordova.getActivity(), waste);
                    final Bundle bundle = new Bundle();
                    if (actions != null && actions.length > 0) {
                        final String actionString = TextUtils.join(" ", actions);
                        bundle.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES, actionString);
                    }
                    Log.d(TAG, "SignIn with " + bundle);
                    Log.d(TAG, "Second try to get token");
                    final String token = GoogleAuthUtil.getToken(cordova.getActivity(), accountName, scoping,
                            bundle);
                    Log.d(TAG, "Connected(" + accountName + "): " + token);
                    final JSONObject result = new JSONObject().put("accountName", accountName).put("accessToken",
                            token);
                    Log.d(TAG, "Callbacking result: " + result);
                    currentCallback.success(result);
                } catch (UserRecoverableAuthException ex) {
                    Log.e(TAG, "Recovering authorization", ex);
                    cordova.startActivityForResult(GooglePlusConnect.this, ex.getIntent(), REQUEST_AUTH_RECOVER);
                } catch (IOException ex) {
                    ex.printStackTrace();
                    currentCallback.error(ex.getLocalizedMessage());
                } catch (GoogleAuthException ex) {
                    ex.printStackTrace();
                    if ("BadUsername".equals(ex.getMessage())) {
                        Log.e(TAG, "Invoked with BadUsername(" + accountName + "). re-select account...", ex);
                        accountName = null;
                        login();
                    } else {
                        currentCallback.error(ex.getLocalizedMessage());
                    }
                } catch (JSONException ex) {
                    ex.printStackTrace();
                    currentCallback.error(ex.getLocalizedMessage());
                }
            }
        });
    }

    private void profile() {
        Log.d(TAG, "Getting profile of " + accountName);
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                gClient = new GoogleApiClient.Builder(cordova.getActivity()).addApi(Plus.API)
                        .addScope(Plus.SCOPE_PLUS_LOGIN).addScope(Plus.SCOPE_PLUS_PROFILE)
                        .addScope(new Scope("https://www.googleapis.com/auth/userinfo.email"))
                        .setAccountName(accountName).build();
                gClient.registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {

                    @Override
                    public void onConnectionSuspended(int reason) {
                        Log.d(TAG, "GoogleApiClient connection suspended: " + reason);
                    }

                    @Override
                    public void onConnected(Bundle bundle) {
                        try {
                            final Person me = Plus.PeopleApi.getCurrentPerson(gClient);
                            Log.d(TAG, "Current person: " + me);
                            final String name = me.getDisplayName();
                            final String avatar = me.getImage().getUrl();
                            final String userId = me.getId();
                            final JSONObject result = new JSONObject().put("id", userId).put("email", accountName)
                                    .put("name", name).put("avatar", avatar);
                            Log.d(TAG, "Callbacking result: " + result);
                            currentCallback.success(result);
                        } catch (JSONException ex) {
                            ex.printStackTrace();
                            currentCallback.error(ex.getLocalizedMessage());
                        }
                    }
                });
                gClient.registerConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {

                    @Override
                    public void onConnectionFailed(ConnectionResult result) {
                        Log.d(TAG, "GoogleApiClient: onConnectionFailed: " + result);
                        if (result.hasResolution()) {
                            try {
                                cordova.setActivityResultCallback(GooglePlusConnect.this);
                                result.startResolutionForResult(cordova.getActivity(), REQUEST_GCLIENT_RECOVER);
                            } catch (SendIntentException ex) {
                                pClient.connect();
                            }
                        } else {
                            currentCallback.error("PlusClient: Failed to connect");
                        }
                    }
                });
                gClient.connect();
            }
        });
    }

    private void disconnect() {
        Log.d(TAG, "Disconnecting with " + accountName);
        cordova.getThreadPool().execute(new Runnable() {
            final GooglePlayServicesClient.ConnectionCallbacks connectionCallbacks = new GooglePlayServicesClient.ConnectionCallbacks() {

                @Override
                public void onDisconnected() {
                    Log.d(TAG, "PlusClient: Disconnected while creating.");
                    currentCallback.error("PlusClient: Disconnected Somehow");
                }

                @Override
                public void onConnected(Bundle bundle) {
                    Log.d(TAG, "PlusClient: Connected");
                    pClient.clearDefaultAccount();
                    pClient.revokeAccessAndDisconnect(new PlusClient.OnAccessRevokedListener() {

                        @Override
                        public void onAccessRevoked(ConnectionResult result) {
                            Log.d(TAG, "PlusClient: onAccessRevoked: " + result);
                            currentCallback.success();
                        }
                    });
                }
            };
            final GooglePlayServicesClient.OnConnectionFailedListener onConnectionFailedListener = new GooglePlayServicesClient.OnConnectionFailedListener() {
                @Override
                public void onConnectionFailed(ConnectionResult result) {
                    Log.d(TAG, "PlusClient: onConnectionFailed: " + result);
                    if (result.hasResolution()) {
                        try {
                            cordova.setActivityResultCallback(GooglePlusConnect.this);
                            result.startResolutionForResult(cordova.getActivity(), REQUEST_PCLIENT_RECOVER);
                        } catch (SendIntentException ex) {
                            pClient.connect();
                        }
                    } else {
                        currentCallback.error("PlusClient: Failed to connect");
                    }
                }
            };

            @Override
            public void run() {
                pClient = new PlusClient.Builder(cordova.getActivity(), connectionCallbacks,
                        onConnectionFailedListener).setAccountName(accountName).build();
                pClient.connect();
            }
        });
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        Log.i(TAG, "onActivityResult:" + requestCode);
        switch (requestCode) {
        case REQUEST_PICK_ACCOUNT:
            if (resultCode == Activity.RESULT_OK) {
                accountName = intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                obtainToken();
            } else {
                currentCallback.error("No account selected");
            }
            break;

        case REQUEST_AUTH_RECOVER:
            if (resultCode == Activity.RESULT_OK) {
                obtainToken();
            } else {
                currentCallback.error("Cannot authrorize");
            }
            break;

        case REQUEST_PCLIENT_RECOVER:
            if (resultCode == Activity.RESULT_OK && pClient != null) {
                pClient.connect();
            } else {
                currentCallback.error("PlusClient: Failed to retry connection");
            }
            break;

        case REQUEST_GCLIENT_RECOVER:
            if (resultCode == Activity.RESULT_OK && pClient != null) {
                gClient.connect();
            } else {
                currentCallback.error("GoogleApiClient: Failed to retry connection");
            }
            break;

        default:
            break;
        }
    }
}