From fc22096ed66749e2603613a696d71f59d2a061cc Mon Sep 17 00:00:00 2001 From: kenstir Date: Tue, 19 Nov 2013 20:08:46 -0500 Subject: [PATCH] checkpoint: starting app on new activity and getting an app token and forwarding to JunkActivity, just until the kinks are worked out --- Open-ILS/src/Android/AndroidManifest.xml | 309 +++++++++++---------- Open-ILS/src/Android/res/layout/activity_junk.xml | 20 ++ Open-ILS/src/Android/res/menu/junk.xml | 9 + Open-ILS/src/Android/res/values/dimens.xml | 54 ++-- Open-ILS/src/Android/res/values/strings.xml | 116 ++++---- .../src/org/evergreen/android/JunkActivity.java | 21 ++ .../android/accountAccess/CurrentLogin.java | 39 +++ .../evergreen/android/globals/AppPreferences.java | 31 +++ .../evergreen/android/views/StartupActivity.java | 239 +++++++++++++++- 9 files changed, 592 insertions(+), 246 deletions(-) create mode 100644 Open-ILS/src/Android/res/layout/activity_junk.xml create mode 100644 Open-ILS/src/Android/res/menu/junk.xml create mode 100644 Open-ILS/src/Android/src/org/evergreen/android/JunkActivity.java create mode 100644 Open-ILS/src/Android/src/org/evergreen/android/accountAccess/CurrentLogin.java create mode 100644 Open-ILS/src/Android/src/org/evergreen/android/globals/AppPreferences.java diff --git a/Open-ILS/src/Android/AndroidManifest.xml b/Open-ILS/src/Android/AndroidManifest.xml index dbc80c22ac..15cadea0b6 100644 --- a/Open-ILS/src/Android/AndroidManifest.xml +++ b/Open-ILS/src/Android/AndroidManifest.xml @@ -1,147 +1,162 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Open-ILS/src/Android/res/layout/activity_junk.xml b/Open-ILS/src/Android/res/layout/activity_junk.xml new file mode 100644 index 0000000000..77cf5e3cf6 --- /dev/null +++ b/Open-ILS/src/Android/res/layout/activity_junk.xml @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/Open-ILS/src/Android/res/menu/junk.xml b/Open-ILS/src/Android/res/menu/junk.xml new file mode 100644 index 0000000000..c002028230 --- /dev/null +++ b/Open-ILS/src/Android/res/menu/junk.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/Open-ILS/src/Android/res/values/dimens.xml b/Open-ILS/src/Android/res/values/dimens.xml index b4919ed1db..0dad7c1792 100644 --- a/Open-ILS/src/Android/res/values/dimens.xml +++ b/Open-ILS/src/Android/res/values/dimens.xml @@ -1,26 +1,28 @@ - - - - 45dip - 14sp - 18sp - 22sp - - - 16sp - 16dip - + + + + + 45dip + 14sp + 18sp + 22sp + 16sp + 16dip + 16dp + 16dp + + diff --git a/Open-ILS/src/Android/res/values/strings.xml b/Open-ILS/src/Android/res/values/strings.xml index f6faaceb60..decc082ff0 100644 --- a/Open-ILS/src/Android/res/values/strings.xml +++ b/Open-ILS/src/Android/res/values/strings.xml @@ -6,12 +6,11 @@ settings library hours barcode scan - - + + Evergreen My Account Options - Search Details Checked Out Holds @@ -21,14 +20,12 @@ Bookbag details Fines Copy Information - Place Hold Add to Bookbag - Choose a bookbag from the list. - + - + Please enter the Evergreen server url, username and password of your account. Library Catalog URL: Username: @@ -38,32 +35,26 @@ Sign in Signing in… Forgot password - Cancel Connect - + - + What are you looking for? Search - Please wait Searching catalog Fetching more results - Enter text here Add filter Added filters: - Advanced search Library hours Preferences - Availability of the book : Hello World, EvergreenAppActivity! Evergreen - Welcome to Evergreen Search My Account @@ -75,12 +66,12 @@ Search result : renew Record %1$d of %2$d - + Show More - + - + Recipient Title Author @@ -102,19 +93,18 @@ Contact phone number Hold expire time Date when the hold is frozen - Items on hold: - + Total items out: / Overdue items: - + Total Owned Total Paid Balance Owed Overdue Materials - + delete name @@ -127,54 +117,48 @@ create Bookbag name: add - - - - Sorry, the Android camera encountered a problem. You may need to restart the device. - OK - - - Login information - Username and password information - - Username - Please enter your login username - - Password - Enter your account password - - Server settings - Library server settings - - Library url address - Please enter the library url in format http:// - - Notification settings - Configure notifications and reminders for checkout items - - Enable notifications - Uncheck this option to remove notifications when checkout items are about to expire - Check this option to enable notifications each time a checkout item will expire - - Days before expiration - Chose how many days before the actual expiration date to set the reminder - - Each day notifications - Give a notification in every day before the actual start notification period and due date - - Notification settings - - + + + Sorry, the Android camera encountered a problem. You may need to restart the device. + OK + + + Login information + Username and password information + Username + Please enter your login username + Password + Enter your account password + Server settings + Library server settings + Library url address + Please enter the library url in format http:// + Notification settings + Configure notifications and reminders for checkout items + Enable notifications + Uncheck this option to remove notifications when checkout items are about to expire + Check this option to enable notifications each time a checkout item will expire + Days before expiration + Chose how many days before the actual expiration date to set the reminder + Each day notifications + Give a notification in every day before the actual start notification period and due date + Notification settings + + one copy %d copies - - + + One hold %d holds - - + + one item %d items - - + + + JunkActivity + Settings + Hello world! + diff --git a/Open-ILS/src/Android/src/org/evergreen/android/JunkActivity.java b/Open-ILS/src/Android/src/org/evergreen/android/JunkActivity.java new file mode 100644 index 0000000000..b45c2cb4b2 --- /dev/null +++ b/Open-ILS/src/Android/src/org/evergreen/android/JunkActivity.java @@ -0,0 +1,21 @@ +package org.evergreen.android; + +import org.evergreen.android.accountAccess.CurrentLogin; + +import android.app.Activity; +import android.os.Bundle; +import android.widget.TextView; + +public class JunkActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + TextView tv = new TextView(this); + String account_name = CurrentLogin.getUsername(); + String auth_token = CurrentLogin.getAuthToken(); + tv.setText("account.name="+((account_name==null)?"null":account_name) + + "\nauth_token="+((auth_token==null)?"null":auth_token)); + setContentView(tv); + } +} diff --git a/Open-ILS/src/Android/src/org/evergreen/android/accountAccess/CurrentLogin.java b/Open-ILS/src/Android/src/org/evergreen/android/accountAccess/CurrentLogin.java new file mode 100644 index 0000000000..37d65ecb2b --- /dev/null +++ b/Open-ILS/src/Android/src/org/evergreen/android/accountAccess/CurrentLogin.java @@ -0,0 +1,39 @@ +package org.evergreen.android.accountAccess; + +/** + * data representing the current logged-in user + * @author kenstir + */ +public class CurrentLogin { + + protected static CurrentLogin mInstance = null; + + protected String mUsername = null; + protected String mAuthToken = null; + + protected CurrentLogin() { + } + + protected static CurrentLogin getInstance() { + if (mInstance == null) + mInstance = new CurrentLogin(); + return mInstance; + } + + public static void clear() { + mInstance = null; + } + + public static void setAccountInfo(String username, String auth_token) { + getInstance().mUsername = username; + getInstance().mAuthToken = auth_token; + } + + public static String getUsername() { + return getInstance().mUsername; + } + + public static String getAuthToken() { + return getInstance().mAuthToken; + } +} diff --git a/Open-ILS/src/Android/src/org/evergreen/android/globals/AppPreferences.java b/Open-ILS/src/Android/src/org/evergreen/android/globals/AppPreferences.java new file mode 100644 index 0000000000..6d4a9064aa --- /dev/null +++ b/Open-ILS/src/Android/src/org/evergreen/android/globals/AppPreferences.java @@ -0,0 +1,31 @@ +package org.evergreen.android.globals; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; + +public class AppPreferences { + public static final String KEY_PREFS_LAST_ACCOUNT_NAME = "account_name"; + private static final String APP_SHARED_PREFS = AppPreferences.class.getSimpleName(); + private SharedPreferences _sharedPrefs; + private Editor _prefsEditor; + + public AppPreferences(Context context) { + this._sharedPrefs = context.getSharedPreferences(APP_SHARED_PREFS, Activity.MODE_PRIVATE); + this._prefsEditor = _sharedPrefs.edit(); + } + + public String getLastAccountName() { + return _sharedPrefs.getString(KEY_PREFS_LAST_ACCOUNT_NAME, ""); + } + + public void putLastAccountName(String text) { + _prefsEditor.putString(KEY_PREFS_LAST_ACCOUNT_NAME, text); + _prefsEditor.commit(); + } + + public void clearLastAccountName() { + putLastAccountName(null); + } +} diff --git a/Open-ILS/src/Android/src/org/evergreen/android/views/StartupActivity.java b/Open-ILS/src/Android/src/org/evergreen/android/views/StartupActivity.java index e12d484c70..78a91bda0a 100644 --- a/Open-ILS/src/Android/src/org/evergreen/android/views/StartupActivity.java +++ b/Open-ILS/src/Android/src/org/evergreen/android/views/StartupActivity.java @@ -1,13 +1,28 @@ package org.evergreen.android.views; import org.evergreen.android.R; +import org.evergreen.android.accountAccess.CurrentLogin; +import org.evergreen.android.globals.AppPreferences; import org.evergreen.android.searchCatalog.SearchCatalogListView; +import org.evergreen.android.JunkActivity; +import org.evergreen_ils.auth.Const; +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.AccountManagerCallback; +import android.accounts.AccountManagerFuture; import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; import android.content.Intent; import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import android.view.ContextThemeWrapper; import android.widget.TextView; +import android.widget.Toast; /** * Activity which displays a login screen to the user, offering registration as @@ -15,21 +30,48 @@ import android.widget.TextView; */ public class StartupActivity extends Activity { + private String TAG = StartupActivity.class.getSimpleName(); private TextView mLoginStatusMessageView; private StartupTask mStartupTask = null; private String mAlertMessage = null; + private AppPreferences mAppPrefs; + private AccountManager mAccountManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_startup); + + mAppPrefs = new AppPreferences(this); + mAccountManager = AccountManager.get(this); + mLoginStatusMessageView = (TextView) findViewById(R.id.login_status_message); - //TODO - /* - last_username = getPref(); - if (last_username) getAuthToken() - */ + signIn(); + } + + public void signIn() { + final String auth_token = CurrentLogin.getAuthToken(); + if (TextUtils.isEmpty(auth_token)) { + getTokenForLastActiveAccount(); + } else { + Log.d(TAG, "signIn> already have auth_token"); + initializeAccountInfo(); + } + } + + private void getTokenForLastActiveAccount() { + final String username = mAppPrefs.getLastAccountName(); + Log.d(TAG, "getToken> username="+username); + + // first try to get an auth token for the last account used + if (!TextUtils.isEmpty(username)) { + if (reuseExistingAccountAuthToken(username)) { + Log.d(TAG, "getToken> reuseExisting returned true"); + } + } else { + getTokenForAccountCreateIfNeeded(); + } } @Override @@ -46,8 +88,191 @@ public class StartupActivity extends Activity { } */ + /** + * Add new account to the account manager + */ + private void addNewAccount() { + //final AccountManagerFuture future = + mAccountManager.addAccount(Const.ACCOUNT_TYPE, Const.AUTHTOKEN_TYPE, null, null, this, new AccountManagerCallback() { + @Override + public void run(AccountManagerFuture future) { + try { + Bundle bnd = future.getResult(); + final String account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME); + showMessage("Account "+account_name+" was created"); + mAppPrefs.putLastAccountName(account_name); + Log.d(TAG, "addNewAccount bnd=" + bnd); + } catch (Exception e) { + mAppPrefs.clearLastAccountName(); + e.printStackTrace(); + showMessage(e.getMessage()); + } + } + }, null); + } + + /** + * Show all the accounts registered on the account manager. Request an auth token upon user select. + * @param authTokenType + */ + private void showAccountPicker() { + final Account availableAccounts[] = mAccountManager.getAccountsByType(Const.ACCOUNT_TYPE); + + if (availableAccounts.length == 0) { + Toast.makeText(this, "No accounts", Toast.LENGTH_SHORT).show(); + addNewAccount(); + } else { + String name[] = new String[availableAccounts.length]; + for (int i = 0; i < availableAccounts.length; i++) { + name[i] = availableAccounts[i].name; + } + + // Account picker + AlertDialog.Builder builder; + if (Build.VERSION.SDK_INT >= 1/*Build.VERSION_CODES.HONEYCOMB*/) { + builder = new AlertDialog.Builder(this); + } else { + ContextThemeWrapper wrapper = new ContextThemeWrapper(this, R.style.EvergreenTheme); + builder = new AlertDialog.Builder(wrapper); + } + AlertDialog aDialog = builder.setTitle("Pick Account").setItems(name, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + getExistingAccountAuthToken(availableAccounts[which]); + } + }).create(); + aDialog.show(); + } + } + + private void getExistingAccountAuthToken(final Account account) { + final AccountManagerFuture future = mAccountManager.getAuthToken(account, Const.AUTHTOKEN_TYPE, null, this, + new AccountManagerCallback() { + @Override + public void run(AccountManagerFuture future) { + Log.d(TAG, "getExistingAccountAuthToken> callback run> got future "+future); + } + }, null); + + new Thread(new Runnable() { + @Override + public void run() { + try { + Bundle bnd = future.getResult(); + Log.d(TAG, "getExistingAccountAuthToken> thread run> got future "+future); + final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN); + final String account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME); + onSuccessfulLogin(account_name, authtoken); + } catch (Exception e) { + Log.d(TAG, "getExistingAccountAuthToken caught "+e.getMessage()); + onFailedLogin(e.getMessage()); + } + } + }).start(); + } + + protected void onSuccessfulLogin(String account_name, String auth_token) { + Log.d(TAG,"onSuccessfulLogin> account_name "+account_name+" token "+auth_token); + showMessage((auth_token != null) ? "SUCCESS with "+account_name+"\ntoken: " + auth_token : "FAIL"); + if (auth_token != null) { + mAppPrefs.putLastAccountName(account_name); + CurrentLogin.setAccountInfo(account_name, auth_token); + startNextActivity(); + } + } + + protected void onFailedLogin(String msg) { + mAppPrefs.clearLastAccountName(); + CurrentLogin.clear(); + showMessage(msg); + } + + private boolean reuseExistingAccountAuthToken(final String account_name) { + final Account availableAccounts[] = mAccountManager.getAccountsByType(Const.ACCOUNT_TYPE); + for (int i = 0; i < availableAccounts.length; i++) { + Log.d(TAG, "reuseExistingAccountAuthToken> looking for "+account_name+", found "+availableAccounts[i].name); + if (account_name.equals(availableAccounts[i].name)) { + Log.d(TAG, "reuseExistingAccountAuthToken> found it"); + getExistingAccountAuthToken(availableAccounts[i]); + return true; + } + } + return false; + } + + /** + * Invalidates the auth token for the account + * @param account + * @param authTokenType + */ + private void invalidateAuthToken(final Account account) { + final AccountManagerFuture future = mAccountManager.getAuthToken(account, Const.AUTHTOKEN_TYPE, null, this, null,null); + + new Thread(new Runnable() { + @Override + public void run() { + try { + Bundle bnd = future.getResult(); + + final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN); + mAccountManager.invalidateAuthToken(account.type, authtoken); + showMessage(account.name + " invalidated"); + mAppPrefs.putLastAccountName(null); + } catch (Exception e) { + mAppPrefs.putLastAccountName(null); + e.printStackTrace(); + showMessage(e.getMessage()); + } + } + }).start(); + } + + /** + * Get an auth token for the account. + * If not exist - add it and then return its auth token. + * If one exist - return its auth token. + * If more than one exists - show a picker and return the select account's auth token. + * @param accountType + * @param authTokenType + */ + private void getTokenForAccountCreateIfNeeded() { + Log.d(TAG, "getTokenForAccountCreateIfNeeded> "); + final AccountManagerFuture future = mAccountManager.getAuthTokenByFeatures(Const.ACCOUNT_TYPE, Const.AUTHTOKEN_TYPE, null, this, null, null, + new AccountManagerCallback() { + @Override + public void run(AccountManagerFuture future) { + Bundle bnd = null; + try { + bnd = future.getResult(); + Log.d(TAG, "getTokenForAccountCreateIfNeeded> bnd="+bnd); + final String authtoken = bnd.getString(AccountManager.KEY_AUTHTOKEN); + final String account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME); + onSuccessfulLogin(account_name, authtoken); + } catch (Exception e) { + Log.d(TAG, "getTokenForAccountCreateIfNeeded> caught "+e.getMessage()); + onFailedLogin(e.getMessage()); + } + } + } + , null); + } + + private void showMessage(final String msg) { + if (TextUtils.isEmpty(msg)) + return; + + runOnUiThread(new Runnable() { + @Override + public void run() { + Log.d(TAG, "showMessage> "+msg); + Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show(); + } + }); + } + private void startNextActivity() { - Intent intent = new Intent(this, SearchCatalogListView.class); + //Intent intent = new Intent(this, SearchCatalogListView.class); + Intent intent = new Intent(this, JunkActivity.class); startActivity(intent); finish(); } @@ -61,7 +286,7 @@ public class StartupActivity extends Activity { // mDownloadTask = new LoginTask(); } - public class StartupTask extends AsyncTask { + private class StartupTask extends AsyncTask { @Override protected Boolean doInBackground(Void... params) { try { -- 2.11.0