package net.hockeyapp.android;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import net.hockeyapp.android.tasks.LoginTask;
import net.hockeyapp.android.utils.AsyncTaskUtils;
import net.hockeyapp.android.utils.Util;
import java.lang.ref.WeakReference;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
/**
* <h3>Description</h3>
*
* Activity to authenticate the user.
*
**/
public class LoginActivity extends Activity {
/**
* Parameter to supply login endpoint URL
*/
public static final String EXTRA_URL = "url";
/**
* Parameter to supply the app secret for the login API
*/
public static final String EXTRA_SECRET = "secret";
/**
* Parameter to define the verification mode for the login API
*/
public static final String EXTRA_MODE = "mode";
/**
* URL for HockeyApp API
*/
private String mUrl;
/**
* The APP mSecret.
*/
private String mSecret;
/**
* The Login Mode.
*/
private int mMode;
/**
* The LoginTask.
*/
private LoginTask mLoginTask;
/**
* The Handler for the LoginTask.
*/
private Handler mLoginHandler;
/**
* The Login button.
*/
private Button mButtonLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.hockeyapp_activity_login);
Bundle extras = getIntent().getExtras();
if (extras != null) {
mUrl = extras.getString(EXTRA_URL);
mSecret = extras.getString(EXTRA_SECRET);
mMode = extras.getInt(EXTRA_MODE);
}
configureView();
initLoginHandler();
@SuppressWarnings("deprecation")
Object object = getLastNonConfigurationInstance();
if (object != null) {
mLoginTask = (LoginTask) object;
mLoginTask.attach(this, mLoginHandler);
}
}
/**
* Detaches the activity from the LoginTask and returns the task
* as last instance. This way the task is restored when the activity
* is immediately re-created.
*
* @return The login task if present and null otherwise.
*/
@Override
public Object onRetainNonConfigurationInstance() {
if (mLoginTask != null) {
mLoginTask.detach();
}
return mLoginTask;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (LoginManager.listener != null) {
LoginManager.listener.onBack();
} else {
if (LoginManager.mainActivity != null) {
Intent intent = new Intent(this, LoginManager.mainActivity);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(LoginManager.LOGIN_EXIT_KEY, true);
startActivity(intent);
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
private void configureView() {
if (mMode == LoginManager.LOGIN_MODE_EMAIL_ONLY) {
EditText passwordInput = (EditText) findViewById(R.id.input_password);
passwordInput.setVisibility(View.INVISIBLE);
}
TextView headlineText = (TextView) findViewById(R.id.text_headline);
headlineText.setText(mMode == LoginManager.LOGIN_MODE_EMAIL_ONLY ? R.string.hockeyapp_login_headline_text_email_only : R.string.hockeyapp_login_headline_text);
mButtonLogin = (Button) findViewById(R.id.button_login);
mButtonLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
performAuthentication();
}
});
}
private void initLoginHandler() {
mLoginHandler = new LoginHandler(this);
}
private void performAuthentication() {
if (!Util.isConnectedToNetwork(this)) {
Toast errorToast = Toast.makeText(this, R.string.hockeyapp_error_no_network_message, Toast.LENGTH_LONG);
errorToast.show();
return;
}
String email = ((EditText) findViewById(R.id.input_email)).getText().toString();
String password = ((EditText) findViewById(R.id.input_password)).getText().toString();
boolean ready = false;
Map<String, String> params = new HashMap<String, String>();
if (mMode == LoginManager.LOGIN_MODE_EMAIL_ONLY) {
ready = !TextUtils.isEmpty(email);
params.put("email", email);
params.put("authcode", md5(mSecret + email));
} else if (mMode == LoginManager.LOGIN_MODE_EMAIL_PASSWORD) {
ready = !TextUtils.isEmpty(email) && !TextUtils.isEmpty(password);
params.put("email", email);
params.put("password", password);
}
if (ready) {
mLoginTask = new LoginTask(this, mLoginHandler, mUrl, mMode, params);
AsyncTaskUtils.execute(mLoginTask);
} else {
Toast.makeText(this, getString(R.string.hockeyapp_login_missing_credentials_toast), Toast.LENGTH_LONG).show();
}
}
public String md5(final String s) {
try {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
digest.update(s.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuilder hexString = new StringBuilder();
for (byte aMessageDigest : messageDigest) {
String h = Integer.toHexString(0xFF & aMessageDigest);
while (h.length() < 2)
h = "0" + h;
hexString.append(h);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
private static class LoginHandler extends Handler {
private final WeakReference<Activity> mWeakActivity;
public LoginHandler(Activity activity) {
mWeakActivity = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
final Activity activity = mWeakActivity.get();
if (activity == null) {
return;
}
Bundle bundle = msg.getData();
boolean success = bundle.getBoolean(LoginTask.BUNDLE_SUCCESS);
if (success) {
activity.finish();
if (LoginManager.listener != null) {
LoginManager.listener.onSuccess();
}
} else {
Toast.makeText(activity, "Login failed. Check your credentials.", Toast.LENGTH_LONG)
.show();
}
}
}
}