package com.github.andlyticsproject;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.support.v7.app.AppCompatActivity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.github.andlyticsproject.model.DeveloperAccount;
import com.github.andlyticsproject.sync.AutosyncHandler;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Used for initial login and managing accounts Because of this original legacy as the launcher
* activity, navigation is a little odd.
* On first startup: LoginActivity -> Main
* When managing
* accounts: Main -> LoginActivity <- Main
* or
* Main -> LoginActivity -> Main
*/
public class LoginActivity extends AppCompatActivity {
private static final String TAG = LoginActivity.class.getSimpleName();
public static final String EXTRA_MANAGE_ACCOUNTS_MODE = "com.github.andlyticsproject.manageAccounts";
public static final String AUTH_TOKEN_TYPE_ANDROID_DEVELOPER = "androiddeveloper";
protected static final int CREATE_ACCOUNT_REQUEST = 1;
private List<DeveloperAccount> developerAccounts;
private boolean manageAccountsMode = false;
private boolean blockGoingBack = false;
private DeveloperAccount selectedAccount = null;
private View okButton;
private LinearLayout accountList;
private AccountManager accountManager;
private DeveloperAccountManager developerAccountManager;
private AutosyncHandler syncHandler;
// TODO Clean this code and res/layout/login.xml up e.g. using a ListView
// instead of a LinearLayout
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
accountManager = AccountManager.get(this);
developerAccountManager = DeveloperAccountManager.getInstance(getApplicationContext());
syncHandler = new AutosyncHandler();
// When called from accounts action item in Main, this flag is passed to
// indicate
// that LoginActivity should not auto login as we are managing the
// accounts,
// rather than performing the initial login
Bundle extras = getIntent().getExtras();
if (extras != null) {
manageAccountsMode = extras.getBoolean(LoginActivity.EXTRA_MANAGE_ACCOUNTS_MODE);
}
selectedAccount = developerAccountManager.getSelectedDeveloperAccount();
setContentView(R.layout.login);
setProgressBarIndeterminateVisibility(false);
if (manageAccountsMode) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.manage_accounts);
}
accountList = (LinearLayout) findViewById(R.id.login_input);
okButton = findViewById(R.id.login_ok_button);
okButton.setClickable(true);
okButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new AsyncTask<Void, Void, Void>() {
@Override
protected void onPreExecute() {
setProgressBarIndeterminateVisibility(true);
okButton.setEnabled(false);
}
@Override
protected Void doInBackground(Void... args) {
saveDeveloperAccounts();
return null;
}
@Override
protected void onPostExecute(Void arg) {
setProgressBarIndeterminateVisibility(false);
okButton.setEnabled(true);
if (selectedAccount != null) {
redirectToMain(selectedAccount.getName(),
selectedAccount.getDeveloperId());
} else {
// Go to the first non hidden account
for (DeveloperAccount account : developerAccounts) {
if (account.isVisible()) {
redirectToMain(account.getName(), account.getDeveloperId());
break;
}
}
}
}
}.execute();
}
});
}
@Override
protected void onResume() {
super.onResume();
boolean skipAutologin = Preferences.getSkipAutologin(this);
if (!manageAccountsMode & !skipAutologin & selectedAccount != null) {
redirectToMain(selectedAccount.getName(), selectedAccount.getDeveloperId());
} else {
showAccountList();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.login_menu, menu);
return true;
}
/**
* Called if item in option menu is selected.
*
* @param item
* The chosen menu item
* @return boolean true/false
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.itemLoginmenuAdd:
addNewGoogleAccount();
break;
case android.R.id.home:
if (!blockGoingBack) {
setResult(RESULT_OK);
finish();
}
break;
default:
return false;
}
return true;
}
@Override
public void onBackPressed() {
setResult(blockGoingBack ? RESULT_CANCELED : RESULT_OK);
super.onBackPressed();
}
protected void showAccountList() {
Account[] googleAccounts = accountManager.getAccountsByType(AutosyncHandler.ACCOUNT_TYPE_GOOGLE);
List<DeveloperAccount> dbAccounts = developerAccountManager.getAllDeveloperAccounts();
developerAccounts = new ArrayList<DeveloperAccount>();
accountList.removeAllViews();
for (int i = 0; i < googleAccounts.length; i++) {
DeveloperAccount developerAccount = DeveloperAccount
.createHidden(googleAccounts[i].name);
int idx = dbAccounts.indexOf(developerAccount);
// use persistent object if exists
if (idx != -1) {
developerAccount = dbAccounts.get(idx);
}
developerAccounts.add(developerAccount);
// Setup auto sync
// only do this when managing accounts, otherwise sync may start
// in the background before accounts are actually configured
if (manageAccountsMode) {
// Ensure it matches the sync period (excluding disabled state)
syncHandler.setAutosyncPeriod(googleAccounts[i].name,
Preferences.getLastNonZeroAutosyncPeriod(this));
// Now make it match the master sync (including disabled state)
syncHandler.setAutosyncPeriod(googleAccounts[i].name,
Preferences.getAutosyncPeriod(this));
}
View accountItem = getLayoutInflater().inflate(R.layout.login_list_item, null);
TextView accountName = (TextView) accountItem.findViewById(R.id.login_list_item_text);
accountName.setText(googleAccounts[i].name);
accountItem.setTag(developerAccount);
CheckBox enabled = (CheckBox) accountItem.findViewById(R.id.login_list_item_enabled);
enabled.setChecked(!developerAccount.isHidden());
enabled.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
DeveloperAccount account = (DeveloperAccount) ((View) buttonView.getParent())
.getTag();
if (isChecked) {
account.activate();
} else {
account.hide();
}
if (manageAccountsMode && account.equals(selectedAccount)) {
// If they remove the current account, then stop them
// going back
blockGoingBack = account.isHidden();
}
okButton.setEnabled(isAtLeastOneAccountEnabled());
}
});
accountList.addView(accountItem);
}
// Update ok button
okButton.setEnabled(isAtLeastOneAccountEnabled());
}
private void saveDeveloperAccounts() {
for (DeveloperAccount account : developerAccounts) {
if (account.isHidden()) {
// They are removing the account from Andlytics, disable
// syncing
syncHandler.setAutosyncEnabled(account.getName(), false);
} else {
// Make it match the master sync period (including
// disabled state)
syncHandler.setAutosyncPeriod(account.getName(),
Preferences.getAutosyncPeriod(LoginActivity.this));
}
developerAccountManager.addOrUpdateDeveloperAccount(account);
}
}
private boolean isAtLeastOneAccountEnabled() {
for (DeveloperAccount acc : developerAccounts) {
if (acc.isVisible()) {
return true;
}
}
return false;
}
private void addNewGoogleAccount() {
AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bundle = future.getResult();
bundle.keySet();
Log.d(TAG, "account added: " + bundle);
showAccountList();
} catch (OperationCanceledException e) {
Log.d(TAG, "addAccount was canceled");
} catch (IOException e) {
Log.d(TAG, "addAccount failed: " + e);
} catch (AuthenticatorException e) {
Log.d(TAG, "addAccount failed: " + e);
}
// gotAccount(false);
}
};
// TODO request a weblogin: token here, so we have it cached?
accountManager.addAccount(AutosyncHandler.ACCOUNT_TYPE_GOOGLE,
LoginActivity.AUTH_TOKEN_TYPE_ANDROID_DEVELOPER, null, null /* options */,
LoginActivity.this, callback, null /* handler */);
}
private void redirectToMain(String selectedAccount, String developerId) {
Preferences.saveSkipAutoLogin(this, false);
Intent intent = new Intent(LoginActivity.this, Main.class);
intent.putExtra(BaseActivity.EXTRA_AUTH_ACCOUNT_NAME, selectedAccount);
intent.putExtra(BaseActivity.EXTRA_DEVELOPER_ID, developerId);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
overridePendingTransition(R.anim.activity_fade_in, R.anim.activity_fade_out);
finish();
}
}