/**
* This file is part of FileSpace for Android, an app for managing your server (files, talks...).
* <p>
* Copyright (c) 2014-2015 FileSpace for Android contributors (http://mercandalli.com)
* <p>
* LICENSE:
* <p>
* FileSpace for Android is free software: you can redistribute it and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any
* later version.
* <p>
* FileSpace for Android is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* @author Jonathan Mercandalli
* @license http://www.gnu.org/licenses/gpl.html
* @copyright 2014-2015 FileSpace for Android contributors (http://mercandalli.com)
*/
package com.mercandalli.android.apps.files.user;
import android.content.Intent;
import android.content.IntentSender;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.mercandalli.android.apps.files.R;
import com.mercandalli.android.apps.files.common.dialog.ConfirmationDialog;
import com.mercandalli.android.apps.files.common.dialog.DialogCallback;
import com.mercandalli.android.apps.files.common.listener.IPostExecuteListener;
import com.mercandalli.android.apps.files.common.net.TaskPost;
import com.mercandalli.android.apps.files.common.util.StringPair;
import com.mercandalli.android.apps.files.common.view.PagerSlidingTabStrip;
import com.mercandalli.android.apps.files.main.ApplicationActivity;
import com.mercandalli.android.apps.files.main.Config;
import com.mercandalli.android.apps.files.main.Constants;
import com.mercandalli.android.apps.files.main.MainActivity;
import com.mercandalli.android.apps.files.main.network.NetUtils;
import com.mercandalli.android.library.base.java.HashUtils;
import com.mercandalli.android.library.base.java.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import static android.Manifest.permission.GET_ACCOUNTS;
public class LoginRegisterActivity extends ApplicationActivity implements ViewPager.OnPageChangeListener, View.OnClickListener, DialogCallback, GoogleApiClient.OnConnectionFailedListener {
/* Request code used to invoke sign in user interactions. */
private static final int RC_GOOGLE_SIGN_IN = 0;
/**
* Id to identity READ_CONTACTS permission request.
**/
private static final int REQUEST_GET_ACCOUNT_PERMISSION = 1;
/**
* The name of the {@link android.content.SharedPreferences} used for saving the record audio permission state.
*/
private static final String SHARED_PREFERENCES_GET_ACCOUNT_PERMISSION = "ContactsPermission";
/**
* The key of the value stored for knowing if it is the first request of the account permission.
*/
private static final String KEY_IS_FIRST_ACCOUNT_PERMISSION_REQUEST = "AccountPermission.Key.KEY_1";
private static final int RC_SIGN_IN = 28757;
private static final String ADMIN = "admin";
private static final int NB_FRAGMENT = 2;
private int mInitialFragment = 1;
public Fragment mListFragment[] = new Fragment[NB_FRAGMENT];
private ViewPager mViewPager;
/* Client used to interact with Google APIs. */
private GoogleApiClient mGoogleApiClient;
/* Is there a ConnectionResult resolution in progress? */
private boolean mIsResolving = false;
/* Should we automatically resolve ConnectionResults when possible? */
private boolean mShouldResolve = false;
private boolean mRequestLaunched;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register_login);
final RegisterLoginPagerAdapter registerLoginPagerAdapter = new RegisterLoginPagerAdapter(
getSupportFragmentManager(), this);
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.activity_register_login_tabs);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(registerLoginPagerAdapter);
mViewPager.addOnPageChangeListener(this);
mViewPager.setOffscreenPageLimit(NB_FRAGMENT - 1);
if (Config.getUserUsername() == null || Config.getUserPassword() == null) {
mInitialFragment = 0;
} else if (Config.getUserUsername().equals("") || Config.getUserPassword().equals("")) {
mInitialFragment = 0;
}
mViewPager.setCurrentItem(this.mInitialFragment);
tabs.setViewPager(mViewPager);
tabs.setIndicatorColor(ContextCompat.getColor(this, android.R.color.white));
if (Config.isAutoConnection() && Config.getUserUsername() != null && Config.getUserPassword() != null &&
!Config.getUserUsername().equals("") && !Config.getUserPassword().equals("") && Config.getUserId() != -1) {
connectionSucceed();
}
findViewById(R.id.activity_register_login_signin).setOnClickListener(this);
findViewById(R.id.activity_register_login_gg_sign).setOnClickListener(this);
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
/*
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Plus.API)
.addApi(Auth.GOOGLE_SIGN_IN_API)
.addScope(new Scope(Scopes.PROFILE))
.build();*/
}
public void connectionSucceed() {
Intent intent = new Intent(this, MainActivity.class);
this.startActivity(intent);
this.overridePendingTransition(R.anim.left_in, R.anim.left_out);
this.finish();
}
@Override
public void onPageSelected(int arg0) {
LoginRegisterActivity.this.invalidateOptionsMenu();
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// Nothing here
}
@Override
public void onPageScrollStateChanged(int arg0) {
// Nothing here
}
public int getCurrentFragmentIndex() {
return mViewPager.getCurrentItem();
}
@Override
public void onClick(View v) {
final int viewId = v.getId();
switch (viewId) {
case R.id.activity_register_login_gg_sign:
onGoogleSignInClicked();
break;
case R.id.activity_register_login_signin:
if (mListFragment[getCurrentFragmentIndex()] != null) {
if (mListFragment[getCurrentFragmentIndex()] instanceof RegistrationFragment) {
((RegistrationFragment) mListFragment[getCurrentFragmentIndex()]).inscription();
} else if (mListFragment[getCurrentFragmentIndex()] instanceof LoginFragment) {
((LoginFragment) mListFragment[getCurrentFragmentIndex()]).login();
}
}
break;
}
}
/**
* Action when the user clicked the Google + signing button
**/
private void onGoogleSignInClicked() {
if (ContextCompat.checkSelfPermission(this, GET_ACCOUNTS) == PackageManager.PERMISSION_GRANTED) {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
/*
mShouldResolve = true;
mGoogleApiClient.connect();
*/
} else if (shouldRequestAccountPermissionRationale()) {
requestAccountPermissionRationale();
} else {
requestAccountPermissionInSettings();
}
}
/**
* Show a UI rationale for requesting the {@link android.Manifest.permission#GET_ACCOUNTS}.
* <p>
* If the user agree, a native poop-up will appear.
*/
private void requestAccountPermissionRationale() {
ConfirmationDialog.newInstance(
"Permission needed",
"FileSpace needs the Contacts permission in order to link your Google account to the app. Nothing will be saved, the permission is only used for the log-in.",
android.R.string.ok,
android.R.string.cancel,
this,
this).show();
}
private void requestAccountPermissionInSettings() {
Snackbar.make(findViewById(R.id.activity_register_login_signin), "FileSpace needs the Contacts permission for using Google.", Snackbar.LENGTH_LONG)
.setAction(android.R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View view) {
final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
})
.show();
}
/**
* Checks if the Contact permission has to be requested when the user want to log-in using
* his Google account.
*
* @return : False if the permission has already been granted, true otherwise.
*/
private boolean shouldRequestAccountPermissionRationale() {
return ActivityCompat.shouldShowRequestPermissionRationale(this, GET_ACCOUNTS) ||
isFirstAccountPermissionRequest();
}
@Override
public void onPositiveClick() {
// The user understood why the app needs the contacts permission
// Remember that the we requested the contacts permission.
final SharedPreferences.Editor editor = getSharedPreferences(SHARED_PREFERENCES_GET_ACCOUNT_PERMISSION, MODE_PRIVATE)
.edit();
editor.putBoolean(KEY_IS_FIRST_ACCOUNT_PERMISSION_REQUEST, false);
editor.apply();
//Request the account permission
ActivityCompat.requestPermissions(this, new String[]{GET_ACCOUNTS}, REQUEST_GET_ACCOUNT_PERMISSION);
}
@Override
public void onNegativeClick() {
}
@Override
public void onNeutralClick() {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e("RegisterLoginActivity", "onConnectionFailed error");
if (!mIsResolving && mShouldResolve) {
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(this, RC_GOOGLE_SIGN_IN);
mIsResolving = true;
} catch (IntentSender.SendIntentException e) {
mIsResolving = false;
mGoogleApiClient.connect();
}
} else {
// Could not resolve the connection result, show the user an error dialog.
//TODO login 1: Show a toast or a snackbar error.
}
} else {
//TODO login 3 : Show sign-out UI
}
}
public class RegisterLoginPagerAdapter extends FragmentPagerAdapter {
ApplicationActivity app;
public RegisterLoginPagerAdapter(FragmentManager fm, ApplicationActivity app) {
super(fm);
this.app = app;
}
@Override
public Fragment getItem(int i) {
Fragment fragment;
switch (i) {
case 0:
fragment = RegistrationFragment.newInstance();
break;
case 1:
fragment = LoginFragment.newInstance();
break;
default:
fragment = RegistrationFragment.newInstance();
break;
}
mListFragment[i] = fragment;
return fragment;
}
@Override
public int getCount() {
return NB_FRAGMENT;
}
@Override
public CharSequence getPageTitle(int i) {
String title = "null";
switch (i) {
case 0:
title = "REGISTER";
break;
case 1:
title = "LOGIN";
break;
}
return title;
}
}
private void googlePlusRegisterLogin(String username, String password) {
if (mRequestLaunched) {
return;
}
mRequestLaunched = true;
final UserModel user = new UserModel();
user.username = username;
user.password = password;
if (StringUtils.isNullOrEmpty(Constants.URL_DOMAIN)) {
mRequestLaunched = false;
return;
}
// Login : POST /user
List<StringPair> parameters = new ArrayList<>();
parameters.add(new StringPair("google_plus", "true"));
parameters.add(new StringPair("username", "" + user.username));
parameters.add(new StringPair("password", "" + user.password));
if (NetUtils.isInternetConnection(this)) {
(new TaskPost(this, Constants.URL_DOMAIN + Config.ROUTE_USER, new IPostExecuteListener() {
@Override
public void onPostExecute(JSONObject json, String body) {
try {
if (json != null) {
if (json.has("succeed") && json.getBoolean("succeed")) {
if (!StringUtils.isNullOrEmpty(user.username)) {
Config.setUserUsername(LoginRegisterActivity.this, user.username);
}
if (!StringUtils.isNullOrEmpty(user.password)) {
Config.setUserPassword(LoginRegisterActivity.this, user.password);
}
connectionSucceed();
}
if (json.has("user")) {
JSONObject user = json.getJSONObject("user");
if (user.has("id")) {
Config.setUserId(LoginRegisterActivity.this, user.getInt("id"));
}
if (user.has(ADMIN)) {
Object admin_obj = user.get(ADMIN);
if (admin_obj instanceof Integer) {
Config.setUserAdmin(LoginRegisterActivity.this, user.getInt(ADMIN) == 1);
} else if (admin_obj instanceof Boolean) {
Config.setUserAdmin(LoginRegisterActivity.this, user.getBoolean(ADMIN));
}
}
if (user.has("id_file_profile_picture")) {
Config.setUserIdFileProfilePicture(LoginRegisterActivity.this, user.getInt("id_file_profile_picture"));
}
}
} else {
Toast.makeText(LoginRegisterActivity.this, LoginRegisterActivity.this.getString(R.string.server_error), Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
Log.e(getClass().getName(), "Failed to convert Json", e);
}
mRequestLaunched = false;
}
}, parameters)).execute();
} else {
mRequestLaunched = false;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
private void handleSignInResult(GoogleSignInResult result) {
Log.d("RegisterLoginActivity", "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
googlePlusRegisterLogin(acct.getEmail(), HashUtils.sha1(acct.getId()));
} else {
// Signed out, show unauthenticated UI.
}
}
/**
* Check if this is the first request to allow the {@link android.Manifest.permission#GET_ACCOUNTS} permission.
*
* @return Returns true if this is the very first request to allow {@link android.Manifest.permission#GET_ACCOUNTS} permission, false otherwise
*/
private boolean isFirstAccountPermissionRequest() {
final SharedPreferences sharedPreferences = getSharedPreferences(SHARED_PREFERENCES_GET_ACCOUNT_PERMISSION, MODE_PRIVATE);
return sharedPreferences.getBoolean(KEY_IS_FIRST_ACCOUNT_PERMISSION_REQUEST, true);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQUEST_GET_ACCOUNT_PERMISSION &&
grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mShouldResolve = true;
mGoogleApiClient.connect();
}
}
}