/*
* Copyright 2013 Vishwa Patel
*
* Licensed 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 in the 'assets' directory of this
* application or 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 com.vishwa.pinit;
import java.io.ByteArrayOutputStream;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.andreabaccega.widget.FormEditText;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageContainer;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import com.facebook.Request;
import com.facebook.Response;
import com.facebook.model.GraphUser;
import com.parse.LogInCallback;
import com.parse.ParseException;
import com.parse.ParseFacebookUtils;
import com.parse.ParseFile;
import com.parse.ParseUser;
import com.parse.RequestPasswordResetCallback;
import com.parse.SaveCallback;
public class LoginActivity extends Activity {
private static final int USERNAME_TAKEN = 0;
private static final int USERNAME_MISSING = 0;
private Button mLoginButton;
private Button mSignupButton;
private Button mFbLoginButton;
private Button mForgotPasswordButton;
private FormEditText mUsernameField;
private FormEditText mPasswordField;
private EditText mPasswordResetField;
private ImageLoader mImageLoader;
private Bitmap mUserPhoto = null;
private ParseUser mCurrentUser;
private byte[] mPhotoByteArray = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser != null) {
((PinItApplication) getApplication()).setHasUserLoggedInSuccesfully(true);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_login);
setProgressBarIndeterminateVisibility(false);
mLoginButton = (Button) findViewById(R.id.login_button);
mSignupButton = (Button) findViewById(R.id.login_signup_button);
mFbLoginButton = (Button) findViewById(R.id.login_fb_button);
mForgotPasswordButton = (Button) findViewById(R.id.login_forgot_password);
mUsernameField = (FormEditText) findViewById(R.id.login_username_field);
mPasswordField = (FormEditText) findViewById(R.id.login_password_field);
mImageLoader = ((PinItApplication) getApplication()).getImageLoader();
mLoginButton.setOnClickListener(new OnLoginClickListener());
mFbLoginButton.setOnClickListener(new OnFbLoginClickListener());
mSignupButton.setOnClickListener(new OnSignupClickListener());
mForgotPasswordButton.setOnClickListener(new OnForgotPasswordClickListener());
}
public class OnForgotPasswordClickListener implements OnClickListener {
@Override
public void onClick(View v) {
final AlertDialog dialog = createForgotPasswordDialog();
dialog.show();
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
final String email = mPasswordResetField.getText().toString();
if(email.isEmpty()) {
mPasswordResetField.setError("Enter an email");
}
else {
mPasswordResetField.setError(null);
setProgressBarIndeterminateVisibility(true);
ParseUser.requestPasswordResetInBackground(email, new RequestPasswordResetCallback() {
@Override
public void done(ParseException e) {
setProgressBarIndeterminateVisibility(false);
if(e == null) {
Toast.makeText(getApplicationContext(), "An email has been sent to "+email+
" with a link to reset your password. Please check it.", Toast.LENGTH_LONG).show();
dialog.dismiss();
}
else if(e.getCode() == ParseException.EMAIL_NOT_FOUND) {
PinItUtils.createAlert("Email not found", "Sorry, that email address " +
"doesn't exist, please create a new account with it.", LoginActivity.this);
}
else {
PinItUtils.createAlert("We're sorry", "That email is invalid", LoginActivity.this);
}
}
});
}
}
});
}
}
class OnLoginClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
if(PinItUtils.isOnline(getApplicationContext())) {
FormEditText[] allFields = { mUsernameField, mPasswordField };
boolean allValid = true;
for(FormEditText field: allFields) {
allValid = field.testValidity() && allValid;
}
if(allValid) {
String username = mUsernameField.getText().toString().trim();
String password = mPasswordField.getText().toString();
setProgressBarIndeterminateVisibility(true);
ParseUser.logInInBackground(username, password, new LogInCallback() {
@Override
public void done(ParseUser user, ParseException e) {
setProgressBarIndeterminateVisibility(false);
if (e == null) {
((PinItApplication) getApplication()).setHasUserLoggedInSuccesfully(true);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
else {
String error = e.getMessage().substring(0, 1).toUpperCase() +
e.getMessage().substring(1);
PinItUtils.createAlert("Login Failed", error, LoginActivity.this);
}
}
});
}
}
else {
PinItUtils.createAlert("Internet connection not found.", "This app "+
"needs an active Internet connection!", LoginActivity.this);
}
}
}
class OnFbLoginClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
if(PinItUtils.isOnline(getApplicationContext())) {
setProgressBarIndeterminateVisibility(true);
ParseFacebookUtils.logIn(LoginActivity.this, new LogInCallback() {
@Override
public void done(ParseUser user, ParseException e) {
if(e == null) {
if(user != null) {
if(user.isNew()) {
mCurrentUser = user;
setupParseAccountInBackground();
}
else {
if(ParseUser.getCurrentUser().getParseFile("profilePhotoThumbnail") != null) {
((PinItApplication) getApplication()).setHasUserLoggedInSuccesfully(true);
setProgressBarIndeterminateVisibility(false);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
else {
setProgressBarIndeterminateVisibility(true);
mCurrentUser = user;
setupParseAccountInBackground();
}
}
}
}
else {
String error = e.getMessage().substring(0, 1).toUpperCase() +
e.getMessage().substring(1);
PinItUtils.createAlert("Unable to login", error, LoginActivity.this);
}
}
});
}
else {
PinItUtils.createAlert("Internet connection not found.", "This app "+
"needs an active Internet connection!", LoginActivity.this);
}
}
}
private void setupParseAccountInBackground() {
Request.executeMeRequestAsync(ParseFacebookUtils.getSession(), new Request.GraphUserCallback() {
@Override
public void onCompleted(final GraphUser user, Response response) {
if (user != null) {
String userPhotoUrl = String.format(
"http://graph.facebook.com/%s/picture?width=100&height=100", user.getId());
mImageLoader.get(userPhotoUrl, new ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
PinItUtils.createAlert("Facebook Sign In Error",
"We couldn't retrieve your Facebook photograph, please try again",
LoginActivity.this);
}
@Override
public void onResponse(ImageContainer response, boolean isImmediate) {
mUserPhoto = response.getBitmap();
if(mUserPhoto != null) {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
mUserPhoto.compress(CompressFormat.PNG, 100, byteStream);
mPhotoByteArray = byteStream.toByteArray();
recycleAllBitmaps();
mCurrentUser.put("isDefaultPhoto", false);
mCurrentUser.put("fbId", user.getId());
if(user.getUsername() != null) {
if(user.getUsername().isEmpty()) {
handleLackOfFacebookUsername();
}
else {
handlePresenceOfFacebookUsername(user);
}
}
else {
handleLackOfFacebookUsername();
}
}
}
});
}
}
});
}
private void handleLackOfFacebookUsername() {
setProgressBarIndeterminateVisibility(false);
String errorMessage = "It seems like you don't have a Facebook " +
"username, please enter a username here:";
createUsernameErrorDialog(errorMessage, USERNAME_MISSING).show();
}
private void handlePresenceOfFacebookUsername(GraphUser user) {
if(user.getUsername().isEmpty()) {
handleLackOfFacebookUsername();
}
else {
mCurrentUser.setUsername(user.getUsername());
final ParseFile userPhotoThumbnailFile =
new ParseFile("photoThumbnail.png", mPhotoByteArray);
userPhotoThumbnailFile.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if(e == null) {
mCurrentUser.put("profilePhotoThumbnail", userPhotoThumbnailFile);
saveParseUserInBackground(mCurrentUser);
}
}
});
}
}
private void saveParseUserInBackground(ParseUser user) {
user.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
setProgressBarIndeterminateVisibility(false);
if(e == null) {
((PinItApplication) getApplication()).setHasUserLoggedInSuccesfully(true);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
else if(e.getCode() == ParseException.USERNAME_TAKEN) {
((PinItApplication) getApplication()).setHasUserLoggedInSuccesfully(false);
String errorMessage = "Your Facebook username has already been taken, please enter "+
"another username:";
createUsernameErrorDialog(errorMessage, USERNAME_TAKEN).show();
}
else {
((PinItApplication) getApplication()).setHasUserLoggedInSuccesfully(false);
String error = e.getMessage().substring(0, 1).toUpperCase()+
e.getMessage().substring(1);
PinItUtils.createAlert("Login in using Facebook failed", error, LoginActivity.this);
}
}
});
}
class OnSignupClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
Intent signupIntent = new Intent(getApplicationContext(),
SignupActivity.class);
startActivity(signupIntent);
}
}
private AlertDialog createForgotPasswordDialog() {
String title = "Forgot Password?";
String message = "Please enter the email address you signed up with to reset your password";
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(title);
builder.setMessage(message);
mPasswordResetField = new EditText(this);
mPasswordResetField.setHint("Email address");
builder.setView(mPasswordResetField);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, int which) {
//We are overriding this to create the button with the Ok label. Android
//automatically dismisses AlertDialogs on button clicks, so to avoid this, we have to
//override the button's on click listener separately (done in the
//OnForgotPasswordClickListener class's onClick method).
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setProgressBarIndeterminateVisibility(false);
return;
}
});
return builder.create();
}
private Dialog createUsernameErrorDialog(String errorMessage, final int errorCode) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("We're sorry");
builder.setMessage(errorMessage);
final EditText input = new EditText(this);
builder.setView(input);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
String username = input.getText().toString();
if(username.isEmpty()) {
Toast.makeText(getApplicationContext(), "Username cannot be empty", Toast.LENGTH_LONG).show();
return;
}
mCurrentUser.setUsername(username);
if(errorCode == USERNAME_MISSING) {
setProgressBarIndeterminateVisibility(true);
final ParseFile userPhotoThumbnailFile =
new ParseFile("photoThumbnail.png", mPhotoByteArray);
userPhotoThumbnailFile.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if(e == null) {
mCurrentUser.put("profilePhotoThumbnail", userPhotoThumbnailFile);
saveParseUserInBackground(mCurrentUser);
}
}
});
}
else {
setProgressBarIndeterminateVisibility(true);
saveParseUserInBackground(mCurrentUser);
}
return;
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setProgressBarIndeterminateVisibility(false);
return;
}
});
return builder.create();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
ParseFacebookUtils.finishAuthentication(requestCode, resultCode, data);
}
public void recycleAllBitmaps() {
if(mUserPhoto != null) {
mUserPhoto.recycle();
mUserPhoto = null;
}
}
@Override
protected void onDestroy() {
recycleAllBitmaps();
if(ParseUser.getCurrentUser() != null && !((PinItApplication) getApplication()).getHasUserLoggedInSuccessfully()) {
try {
ParseUser.getCurrentUser().delete();
ParseUser.logOut();
} catch (ParseException e) {
}
}
super.onDestroy();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
}
}