package com.code44.finance.ui.playservices; import android.app.Activity; import android.app.Dialog; import android.content.IntentSender; import android.os.Bundle; import android.support.v4.app.DialogFragment; import com.code44.finance.ui.BaseFragment; 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.drive.Drive; import com.google.android.gms.plus.Plus; import javax.inject.Inject; public class GoogleApiFragment extends BaseFragment implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private static final String ARG_UNIQUE_CLIENT_ID = "ARG_UNIQUE_CLIENT_ID"; private static final String ARG_USE_PLUS = "ARG_USE_PLUS"; private static final String ARG_USE_DRIVE = "ARG_USE_DRIVE"; private static final String FRAGMENT_ERROR_DIALOG = "FRAGMENT_ERROR_DIALOG"; private static final int REQUEST_RESOLVE_ERROR = 9000; private static final int REQUEST_GOOGLE_PLAY_SERVICES = 9001; @Inject GoogleApiConnection googleApiConnection; private GoogleApiClient client; private String uniqueClientId; private boolean connectWhenPossible = false; public static Builder with(String uniqueClientId) { return new Builder(uniqueClientId); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); buildGoogleApiClient(); if (connectWhenPossible) { connect(); } } @Override public void onDestroy() { super.onDestroy(); disconnect(); } @Override public void onConnected(Bundle bundle) { sendEventConnected(); } @Override public void onConnectionSuspended(int cause) { sendEventSuspended(); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { sendEventFailed(); if (connectionResult.hasResolution()) { try { if (getActivity() == null) { return; } connectionResult.startResolutionForResult(getActivity(), REQUEST_RESOLVE_ERROR); } catch (IntentSender.SendIntentException e) { // There was an error with the resolution intent. Try again. client.connect(); } } else { // Show dialog using GooglePlayServicesUtil.getErrorDialog() showErrorDialog(connectionResult.getErrorCode()); } } public boolean handleOnActivityResult(int requestCode, int resultCode) { if (requestCode == REQUEST_RESOLVE_ERROR) { if (resultCode == Activity.RESULT_OK) { connect(); } return true; } return false; } public void connect() { if (getActivity() == null || client == null) { connectWhenPossible = true; return; } connectWhenPossible = false; if (checkGooglePlayServicesAvailable()) { if (client.isConnected() || client.isConnecting()) { sendEventConnected(); } else { client.connect(); } } } public void disconnect() { googleApiConnection.remove(uniqueClientId); connectWhenPossible = false; if (client != null && (client.isConnected() || client.isConnecting())) { client.disconnect(); } else { sendEventSuspended(); } } public GoogleApiClient getClient() { return client; } protected void sendEventConnected() { googleApiConnection.put(uniqueClientId, client); getEventBus().post(new GoogleApiConnectedEvent(client, uniqueClientId)); } protected void sendEventSuspended() { googleApiConnection.remove(uniqueClientId); getEventBus().post(new GoogleApiSuspendedEvent(client, uniqueClientId)); } protected void sendEventFailed() { googleApiConnection.remove(uniqueClientId); getEventBus().post(new GoogleApiFailedEvent(client, uniqueClientId)); } private void buildGoogleApiClient() { // Get arguments final Bundle args = getArguments(); final boolean usePlus = args.getBoolean(ARG_USE_PLUS, false); final boolean useDrive = args.getBoolean(ARG_USE_DRIVE, false); uniqueClientId = args.getString(ARG_UNIQUE_CLIENT_ID); // Init a client final GoogleApiClient.Builder builder = new GoogleApiClient.Builder(getActivity(), this, this); if (usePlus) { builder.addApi(Plus.API).addScope(Plus.SCOPE_PLUS_LOGIN); } if (useDrive) { builder.addApi(Drive.API).addScope(Drive.SCOPE_FILE); } client = builder.build(); } private boolean checkGooglePlayServicesAvailable() { final int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()); if (resultCode != ConnectionResult.SUCCESS) { //noinspection StatementWithEmptyBody if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) { GooglePlayServicesUtil.getErrorDialog(resultCode, getActivity(), REQUEST_GOOGLE_PLAY_SERVICES).show(); } else { // TODO Notify user that device is not supported } return false; } return true; } private void showErrorDialog(int errorCode) { final Activity activity = getActivity(); if (activity == null) { return; } // Get the error dialog fromInt Google Play services Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(errorCode, getActivity(), REQUEST_GOOGLE_PLAY_SERVICES); // If Google Play services can provide an error dialog if (errorDialog != null) { // Create a new DialogFragment in which to show the error dialog ErrorDialogFragment errorFragment = new ErrorDialogFragment(); // Set the dialog in the DialogFragment errorFragment.setDialog(errorDialog); // Show the error dialog in the DialogFragment errorFragment.show(getFragmentManager(), FRAGMENT_ERROR_DIALOG); } } public static class Builder { private final String uniqueClientId; boolean usePlus; boolean useDrive; public Builder(String uniqueClientId) { this.uniqueClientId = uniqueClientId; } public Builder setUsePlus(boolean usePlus) { this.usePlus = usePlus; return this; } public Builder setUseDrive(boolean useDrive) { this.useDrive = useDrive; return this; } public GoogleApiFragment build() { Bundle args = new Bundle(); args.putString(ARG_UNIQUE_CLIENT_ID, uniqueClientId); args.putBoolean(ARG_USE_PLUS, usePlus); args.putBoolean(ARG_USE_DRIVE, useDrive); GoogleApiFragment fragment = new GoogleApiFragment(); fragment.setArguments(args); return fragment; } } public static abstract class GoogleApiEvent { private final GoogleApiClient client; private final String uniqueClientId; public GoogleApiEvent(GoogleApiClient client, String uniqueClientId) { this.client = client; this.uniqueClientId = uniqueClientId; } public GoogleApiClient getClient() { return client; } public String getUniqueClientId() { return uniqueClientId; } } public static class GoogleApiConnectedEvent extends GoogleApiEvent { public GoogleApiConnectedEvent(GoogleApiClient client, String uniqueClientId) { super(client, uniqueClientId); } } public static class GoogleApiSuspendedEvent extends GoogleApiEvent { public GoogleApiSuspendedEvent(GoogleApiClient client, String uniqueClientId) { super(client, uniqueClientId); } } public static class GoogleApiFailedEvent extends GoogleApiEvent { public GoogleApiFailedEvent(GoogleApiClient client, String uniqueClientId) { super(client, uniqueClientId); } } public static class ErrorDialogFragment extends DialogFragment { private Dialog dialog; public ErrorDialogFragment() { super(); dialog = null; } public void setDialog(Dialog dialog) { this.dialog = dialog; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return dialog; } } }