diff --git a/app/res/values-ru/strings.xml b/app/res/values-ru/strings.xml
index 15152b5..ceeaf10 100644
--- a/app/res/values-ru/strings.xml
+++ b/app/res/values-ru/strings.xml
@@ -239,6 +239,7 @@
Введите email чтобы восстановить пароль
Зарегистрируйтесь или войдите в одно касание]]>
Пожалуйста выберите аккаунт google для входа
+ Пожалуйста выберите аккаунт trovebox для входа
email
пароль
diff --git a/app/res/values/strings.xml b/app/res/values/strings.xml
index dcefb76..0ebb122 100644
--- a/app/res/values/strings.xml
+++ b/app/res/values/strings.xml
@@ -240,6 +240,7 @@
Enter your email to recover your password
Sign up or sign in with a single tap]]>
Please select google account to login with
+ Please select trovebox account to login with
email
password
diff --git a/app/src/com/trovebox/android/app/AccountLogin.java b/app/src/com/trovebox/android/app/AccountLogin.java
index faa2f34..7021e31 100644
--- a/app/src/com/trovebox/android/app/AccountLogin.java
+++ b/app/src/com/trovebox/android/app/AccountLogin.java
@@ -1,6 +1,8 @@
package com.trovebox.android.app;
+import java.lang.ref.WeakReference;
+
import org.holoeverywhere.app.Activity;
import org.holoeverywhere.widget.TextView;
@@ -20,6 +22,8 @@
import com.trovebox.android.app.util.CommonUtils;
import com.trovebox.android.app.util.GuiUtils;
import com.trovebox.android.app.util.LoginUtils;
+import com.trovebox.android.app.util.LoginUtils.LoginActionHandler;
+import com.trovebox.android.app.util.ObjectAccessor;
import com.trovebox.android.app.util.TrackerUtils;
public class AccountLogin extends CommonActivity {
@@ -122,9 +126,44 @@ public RecoverPasswordFragment getRecoverPasswordFragment() {
* The log in fragment with the retained instance across configuration
* change
*/
- public static class LogInFragment extends CommonRetainedFragmentWithTaskAndProgress {
+ public static class LogInFragment extends CommonRetainedFragmentWithTaskAndProgress implements
+ LoginActionHandler {
private static final String TAG = LogInFragment.class.getSimpleName();
+ static WeakReference sCurrentInstance;
+ static ObjectAccessor sCurrentInstanceAccessor = new ObjectAccessor() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public LogInFragment run() {
+ return sCurrentInstance == null ? null : sCurrentInstance.get();
+ }
+ };
+
+ boolean mDelayedLoginProcessing = false;
+ AccountTroveboxResponse mLastResponse;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ sCurrentInstance = new WeakReference(this);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (sCurrentInstance != null) {
+ if (sCurrentInstance.get() == LogInFragment.this
+ || sCurrentInstance.get() == null) {
+ CommonUtils.debug(TAG, "Nullify current instance");
+ sCurrentInstance = null;
+ } else {
+ CommonUtils.debug(TAG,
+ "Skipped nullify of current instance, such as it is not the same");
+ }
+ }
+ super.onDestroy();
+ }
+
@Override
public String getLoadingMessage() {
return CommonUtils.getStringResource(R.string.logging_in_message);
@@ -134,6 +173,26 @@ public void doLogin(String user, String pwd) {
startRetainedTask(new LogInUserTask(new Credentials(user, pwd)));
}
+ @Override
+ public void processLoginCredentials(com.trovebox.android.app.model.Credentials credentials) {
+ Activity activity = getSupportActivity();
+ credentials.saveCredentials(activity);
+ LoginUtils.onLoggedIn(activity, true);
+ }
+
+ void processLoginResonse(Activity activity) {
+ LoginUtils.processSuccessfulLoginResult(mLastResponse, sCurrentInstanceAccessor,
+ activity);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ if (mDelayedLoginProcessing) {
+ mDelayedLoginProcessing = false;
+ processLoginResonse(getSupportActivity());
+ }
+ }
class LogInUserTask extends RetainedTask {
private Credentials credentials;
AccountTroveboxResponse result;
@@ -161,15 +220,14 @@ protected Boolean doInBackground(Void... params) {
protected void onSuccessPostExecuteAdditional() {
try
{
+ mLastResponse = result;
Activity activity = getSupportActivity();
- // save credentials.
- result.saveCredentials(activity);
-
- // start new activity
- startActivity(new Intent(activity,
- MainActivity.class));
- LoginUtils.sendLoggedInBroadcast(activity);
- activity.finish();
+ if (activity != null) {
+ processLoginResonse(activity);
+ } else {
+ TrackerUtils.trackErrorEvent("activity_null", TAG);
+ mDelayedLoginProcessing = true;
+ }
} catch (Exception e)
{
GuiUtils.error(TAG, e);
diff --git a/app/src/com/trovebox/android/app/AccountSignup.java b/app/src/com/trovebox/android/app/AccountSignup.java
index 9e355a5..03222d5 100644
--- a/app/src/com/trovebox/android/app/AccountSignup.java
+++ b/app/src/com/trovebox/android/app/AccountSignup.java
@@ -1,9 +1,10 @@
package com.trovebox.android.app;
+import java.lang.ref.WeakReference;
+
import org.holoeverywhere.app.Activity;
-import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
@@ -17,6 +18,8 @@
import com.trovebox.android.app.util.CommonUtils;
import com.trovebox.android.app.util.GuiUtils;
import com.trovebox.android.app.util.LoginUtils;
+import com.trovebox.android.app.util.LoginUtils.LoginActionHandler;
+import com.trovebox.android.app.util.ObjectAccessor;
import com.trovebox.android.app.util.TrackerUtils;
/**
@@ -83,9 +86,43 @@ NewUserFragment getNewUserFragment() {
* The create new user fragment with the retained instance across
* configuration change
*/
- public static class NewUserFragment extends CommonRetainedFragmentWithTaskAndProgress {
+ public static class NewUserFragment extends CommonRetainedFragmentWithTaskAndProgress implements
+ LoginActionHandler {
private static final String TAG = NewUserFragment.class.getSimpleName();
+ static WeakReference sCurrentInstance;
+ static ObjectAccessor sCurrentInstanceAccessor = new ObjectAccessor() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public NewUserFragment run() {
+ return sCurrentInstance == null ? null : sCurrentInstance.get();
+ }
+ };
+
+ boolean mDelayedLoginProcessing = false;
+ AccountTroveboxResponse mLastResponse;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ sCurrentInstance = new WeakReference(this);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (sCurrentInstance != null) {
+ if (sCurrentInstance.get() == NewUserFragment.this || sCurrentInstance.get() == null) {
+ CommonUtils.debug(TAG, "Nullify current instance");
+ sCurrentInstance = null;
+ } else {
+ CommonUtils.debug(TAG,
+ "Skipped nullify of current instance, such as it is not the same");
+ }
+ }
+ super.onDestroy();
+ }
+
@Override
public String getLoadingMessage() {
return CommonUtils.getStringResource(R.string.signup_message);
@@ -95,6 +132,26 @@ public void createNewUser(String username, String email, String password) {
startRetainedTask(new NewUserTask(username, email, password));
}
+ @Override
+ public void processLoginCredentials(com.trovebox.android.app.model.Credentials credentials) {
+ Activity activity = getSupportActivity();
+ credentials.saveCredentials(activity);
+ LoginUtils.onLoggedIn(activity, true);
+ }
+
+ void processLoginResonse(Activity activity) {
+ LoginUtils.processSuccessfulLoginResult(mLastResponse, sCurrentInstanceAccessor,
+ activity);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ if (mDelayedLoginProcessing) {
+ mDelayedLoginProcessing = false;
+ processLoginResonse(getSupportActivity());
+ }
+ }
class NewUserTask extends RetainedTask {
String username, password, email;
AccountTroveboxResponse result;
@@ -124,15 +181,14 @@ protected Boolean doInBackground(Void... params) {
protected void onSuccessPostExecuteAdditional() {
try
{
+ mLastResponse = result;
Activity activity = getSupportActivity();
- // save credentials.
- result.saveCredentials(activity);
-
- // start new activity
- startActivity(new Intent(activity,
- MainActivity.class));
- LoginUtils.sendLoggedInBroadcast(activity);
- activity.finish();
+ if (activity != null) {
+ processLoginResonse(activity);
+ } else {
+ TrackerUtils.trackErrorEvent("activity_null", TAG);
+ mDelayedLoginProcessing = true;
+ }
} catch (Exception e)
{
GuiUtils.error(TAG, e);
diff --git a/app/src/com/trovebox/android/app/GoogleLoginFragment.java b/app/src/com/trovebox/android/app/GoogleLoginFragment.java
index b84fec2..b2c9d83 100644
--- a/app/src/com/trovebox/android/app/GoogleLoginFragment.java
+++ b/app/src/com/trovebox/android/app/GoogleLoginFragment.java
@@ -4,14 +4,13 @@
import java.io.IOException;
import java.lang.ref.WeakReference;
+import org.holoeverywhere.app.Activity;
import org.holoeverywhere.app.AlertDialog;
import org.holoeverywhere.app.Dialog;
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.app.Activity;
import android.content.DialogInterface;
-import android.content.Intent;
import android.os.Bundle;
import android.view.View;
@@ -29,6 +28,8 @@
import com.trovebox.android.app.util.CommonUtils;
import com.trovebox.android.app.util.GuiUtils;
import com.trovebox.android.app.util.LoginUtils;
+import com.trovebox.android.app.util.LoginUtils.LoginActionHandler;
+import com.trovebox.android.app.util.ObjectAccessor;
import com.trovebox.android.app.util.TrackerUtils;
/**
@@ -36,16 +37,26 @@
*
* @author Eugene Popovich
*/
-public class GoogleLoginFragment extends CommonRetainedFragmentWithTaskAndProgress {
+public class GoogleLoginFragment extends CommonRetainedFragmentWithTaskAndProgress implements
+ LoginActionHandler {
private static final String TAG = GoogleLoginFragment.class.getSimpleName();
public static final String SCOPE =
"audience:server:client_id:"
+ CommonUtils.getStringResource(R.string.google_auth_server_client_id);
- int requestCode;
- boolean delayedLoggedIn = false;
+ static WeakReference sCurrentInstance;
+ static ObjectAccessor sCurrentInstanceAccessor = new ObjectAccessor() {
+ private static final long serialVersionUID = 1L;
- static WeakReference currentInstance;
+ @Override
+ public GoogleLoginFragment run() {
+ return sCurrentInstance == null ? null : sCurrentInstance.get();
+ }
+ };
+
+ int mRequestCode;
+ boolean mDelayedLoginProcessing = false;
+ AccountTroveboxResponse mLastResponse;
/**
* Empty constructor as per the Fragment documentation
@@ -57,19 +68,19 @@ public GoogleLoginFragment() {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- currentInstance = new WeakReference(this);
+ sCurrentInstance = new WeakReference(this);
}
@Override
public void onDestroy() {
super.onDestroy();
- if (currentInstance != null)
+ if (sCurrentInstance != null)
{
- if (currentInstance.get() == GoogleLoginFragment.this
- || currentInstance.get() == null)
+ if (sCurrentInstance.get() == GoogleLoginFragment.this
+ || sCurrentInstance.get() == null)
{
CommonUtils.debug(TAG, "Nullify current instance");
- currentInstance = null;
+ sCurrentInstance = null;
} else
{
CommonUtils.debug(TAG,
@@ -78,25 +89,8 @@ public void onDestroy() {
}
}
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- if (delayedLoggedIn)
- {
- delayedLoggedIn = false;
- onLoggedIn(getActivity());
- }
- }
-
- void onLoggedIn(Activity activity) {
- // start new activity
- startActivity(new Intent(activity,
- MainActivity.class));
- LoginUtils.sendLoggedInBroadcast(activity);
- }
-
public void doLogin(int requestCode) {
- this.requestCode = requestCode;
+ this.mRequestCode = requestCode;
int availabilityResult = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(getActivity());
if (availabilityResult == ConnectionResult.SUCCESS)
@@ -134,7 +128,7 @@ public void showGooglePlayErrorDialog(int availabilityResult) {
android.app.Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
availabilityResult,
getActivity(),
- requestCode);
+ mRequestCode);
errorDialog.show();
} catch (Exception ex)
{
@@ -188,6 +182,25 @@ public String getLoadingMessage() {
return CommonUtils.getStringResource(R.string.logging_in_message);
}
+ @Override
+ public void processLoginCredentials(com.trovebox.android.app.model.Credentials credentials) {
+ Activity activity = getSupportActivity();
+ credentials.saveCredentials(activity);
+ LoginUtils.onLoggedIn(activity, true);
+ }
+
+ void processLoginResonse(Activity activity) {
+ LoginUtils.processSuccessfulLoginResult(mLastResponse, sCurrentInstanceAccessor, activity);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ if (mDelayedLoginProcessing) {
+ mDelayedLoginProcessing = false;
+ processLoginResonse(getSupportActivity());
+ }
+ }
private class LogInUserTask extends
RetainedTask {
AccountTroveboxResponse result;
@@ -199,17 +212,17 @@ public LogInUserTask(String accountName) {
@Override
protected void onSuccessPostExecuteAdditional() {
- // save credentials.
- result.saveCredentials(TroveboxApplication.getContext());
-
- Activity activity = getActivity();
- if (activity != null)
- {
- onLoggedIn(activity);
- } else
- {
- TrackerUtils.trackErrorEvent("activity_null", TAG);
- delayedLoggedIn = true;
+ try {
+ mLastResponse = result;
+ Activity activity = getSupportActivity();
+ if (activity != null) {
+ processLoginResonse(activity);
+ } else {
+ TrackerUtils.trackErrorEvent("activity_null", TAG);
+ mDelayedLoginProcessing = true;
+ }
+ } catch (Exception e) {
+ GuiUtils.error(TAG, e);
}
}
@@ -238,7 +251,7 @@ protected Boolean doInBackground(Void... params) {
*/
protected String fetchToken() throws IOException {
try {
- Activity activity = getActivity();
+ Activity activity = getSupportActivity();
if (activity == null || activity.isFinishing())
{
return null;
@@ -258,7 +271,7 @@ public void run() {
} catch (UserRecoverableAuthException userRecoverableException) {
// Unable to authenticate, but the user can fix this.
// Forward the user to the appropriate activity.
- startActivityForResult(userRecoverableException.getIntent(), requestCode);
+ startActivityForResult(userRecoverableException.getIntent(), mRequestCode);
} catch (GoogleAuthException fatalException) {
GuiUtils.error(TAG, CommonUtils.getStringResource(
R.string.errorCouldNotFetchGoogleAccountToken,
@@ -279,7 +292,7 @@ public SelectAccountSelectedActionHandler(String[] accountNames) {
@Override
public void itemSelected(int i) {
- currentInstance.get().performLoginAction(getItems()[i]);
+ sCurrentInstance.get().performLoginAction(getItems()[i]);
}
@Override
diff --git a/app/src/com/trovebox/android/app/SetupActivity.java b/app/src/com/trovebox/android/app/SetupActivity.java
index bb257f9..984e966 100644
--- a/app/src/com/trovebox/android/app/SetupActivity.java
+++ b/app/src/com/trovebox/android/app/SetupActivity.java
@@ -5,15 +5,6 @@
import org.holoeverywhere.LayoutInflater;
import org.holoeverywhere.app.ProgressDialog;
-import com.trovebox.android.app.R;
-import com.trovebox.android.app.common.CommonActivity;
-import com.trovebox.android.app.common.CommonFragment;
-import com.trovebox.android.app.oauth.OAuthUtils;
-import com.trovebox.android.app.util.GuiUtils;
-import com.trovebox.android.app.util.ProgressDialogLoadingControl;
-import com.trovebox.android.app.util.TrackerUtils;
-import com.trovebox.android.app.util.regex.Patterns;
-
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -24,6 +15,14 @@
import android.widget.Button;
import android.widget.EditText;
+import com.trovebox.android.app.common.CommonActivity;
+import com.trovebox.android.app.common.CommonFragment;
+import com.trovebox.android.app.oauth.OAuthUtils;
+import com.trovebox.android.app.util.GuiUtils;
+import com.trovebox.android.app.util.ProgressDialogLoadingControl;
+import com.trovebox.android.app.util.TrackerUtils;
+import com.trovebox.android.app.util.regex.Patterns;
+
/**
* The activity that gets presented to the user in case the user is not logged
* in to a server. - setup screen
@@ -110,7 +109,7 @@ public void onClick(View v)
} else
{
Preferences.setServer(getActivity(), server);
- OAuthUtils.askOAuth(getActivity());
+ OAuthUtils.askOAuth(getSupportActivity());
}
break;
}
diff --git a/app/src/com/trovebox/android/app/model/Credentials.java b/app/src/com/trovebox/android/app/model/Credentials.java
new file mode 100644
index 0000000..765cbb6
--- /dev/null
+++ b/app/src/com/trovebox/android/app/model/Credentials.java
@@ -0,0 +1,145 @@
+package com.trovebox.android.app.model;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.trovebox.android.app.Preferences;
+import com.trovebox.android.app.R;
+
+/**
+ * Class representing login credentials for Trovebox.
+ *
+ * @author Eugene Popovich
+ */
+public class Credentials implements Parcelable {
+ private String mServer;
+ private String mOAuthConsumerKey;
+ private String mOAuthConsumerSecret;
+ private String mOAuthToken;
+ private String mOAuthTokenSecret;
+ private String mEmail;
+
+ private Credentials() {
+ }
+
+ public Credentials(JSONObject json) throws JSONException {
+ mServer = "http://" + json.getString("host");
+ mOAuthConsumerKey = json.getString("id");
+ mOAuthConsumerSecret = json.getString("clientSecret");
+ mOAuthToken = json.getString("userToken");
+ mOAuthTokenSecret = json.getString("userSecret");
+ mEmail = json.getString("owner");
+ }
+
+ public String getServer() {
+ return mServer;
+ }
+
+ public void setServer(String server) {
+ this.mServer = server;
+ }
+
+ public String getoAuthConsumerKey() {
+ return mOAuthConsumerKey;
+ }
+
+ public void setoAuthConsumerKey(String oAuthConsumerKey) {
+ this.mOAuthConsumerKey = oAuthConsumerKey;
+ }
+
+ public String getoAuthConsumerSecret() {
+ return mOAuthConsumerSecret;
+ }
+
+ public void setoAuthConsumerSecret(String oAuthConsumerSecret) {
+ this.mOAuthConsumerSecret = oAuthConsumerSecret;
+ }
+
+ public String getoAuthToken() {
+ return mOAuthToken;
+ }
+
+ public void setoAuthToken(String oAuthToken) {
+ this.mOAuthToken = oAuthToken;
+ }
+
+ public String getoAuthTokenSecret() {
+ return mOAuthTokenSecret;
+ }
+
+ public void setoAuthTokenSecret(String oAuthTokenSecret) {
+ this.mOAuthTokenSecret = oAuthTokenSecret;
+ }
+
+ public String getEmail() {
+ return mEmail;
+ }
+
+ public void setEmail(String email) {
+ this.mEmail = email;
+ }
+
+ public void saveCredentials(Context context) {
+ Preferences.setServer(context, this.getServer());
+
+ Preferences.getDefaultSharedPreferences(context).edit()
+ .putBoolean(context.getString(R.string.setting_account_loggedin_key), true)
+ .commit();
+
+ Preferences
+ .getSharedPreferences("oauth")
+ .edit()
+ .putString(context.getString(R.string.setting_oauth_consumer_key),
+ this.getoAuthConsumerKey())
+ .putString(context.getString(R.string.setting_oauth_consumer_secret),
+ this.getoAuthConsumerSecret())
+ .putString(context.getString(R.string.setting_oauth_token),
+ this.getoAuthToken())
+ .putString(context.getString(R.string.setting_oauth_token_secret),
+ this.getoAuthTokenSecret()).commit();
+ }
+
+ /*****************************
+ * PARCELABLE IMPLEMENTATION *
+ *****************************/
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mServer);
+ out.writeString(mEmail);
+ out.writeString(mOAuthConsumerKey);
+ out.writeString(mOAuthConsumerSecret);
+ out.writeString(mOAuthToken);
+ out.writeString(mOAuthTokenSecret);
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+ @Override
+ public Credentials createFromParcel(Parcel in) {
+ return new Credentials(in);
+ }
+
+ @Override
+ public Credentials[] newArray(int size) {
+ return new Credentials[size];
+ }
+ };
+
+ private Credentials(Parcel in) {
+ this();
+ mServer = in.readString();
+ mEmail = in.readString();
+ mOAuthConsumerKey = in.readString();
+ mOAuthConsumerSecret = in.readString();
+ mOAuthToken = in.readString();
+ mOAuthTokenSecret = in.readString();
+ }
+}
\ No newline at end of file
diff --git a/app/src/com/trovebox/android/app/net/account/AccountTroveboxResponse.java b/app/src/com/trovebox/android/app/net/account/AccountTroveboxResponse.java
index 6ca4453..bec6be4 100644
--- a/app/src/com/trovebox/android/app/net/account/AccountTroveboxResponse.java
+++ b/app/src/com/trovebox/android/app/net/account/AccountTroveboxResponse.java
@@ -2,14 +2,13 @@
package com.trovebox.android.app.net.account;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-import android.content.Context;
-
-import com.trovebox.android.app.Preferences;
import com.trovebox.android.app.R;
import com.trovebox.android.app.TroveboxApplication;
+import com.trovebox.android.app.model.Credentials;
import com.trovebox.android.app.net.TroveboxResponse;
/**
@@ -19,97 +18,25 @@ public class AccountTroveboxResponse extends TroveboxResponse {
public static int SUCCESSFUL_CODE = 200;
public static int INVALID_CREDENTIALS_CODE = 403;
public static int UNKNOWN_ERROR_CODE = 500;
- private String server;
- private String oAuthConsumerKey;
- private String oAuthConsumerSecret;
- private String oAuthToken;
- private String oAuthTokenSecret;
- private String email;
-
- public String getServer() {
- return server;
- }
-
- public void setServer(String server) {
- this.server = server;
- }
-
- public String getoAuthConsumerKey() {
- return oAuthConsumerKey;
- }
-
- public void setoAuthConsumerKey(String oAuthConsumerKey) {
- this.oAuthConsumerKey = oAuthConsumerKey;
- }
-
- public String getoAuthConsumerSecret() {
- return oAuthConsumerSecret;
- }
-
- public void setoAuthConsumerSecret(String oAuthConsumerSecret) {
- this.oAuthConsumerSecret = oAuthConsumerSecret;
- }
-
- public String getoAuthToken() {
- return oAuthToken;
- }
-
- public void setoAuthToken(String oAuthToken) {
- this.oAuthToken = oAuthToken;
- }
-
- public String getoAuthTokenSecret() {
- return oAuthTokenSecret;
- }
-
- public void setoAuthTokenSecret(String oAuthTokenSecret) {
- this.oAuthTokenSecret = oAuthTokenSecret;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
+ private Credentials[] mCredentials;
public AccountTroveboxResponse(RequestType requestType, JSONObject json) throws JSONException {
super(requestType, json);
- if (isSuccess() && json.get("result") instanceof JSONObject) {
- JSONObject result = json.getJSONObject("result");
- server = "http://" + result.getString("host");
- oAuthConsumerKey = result.getString("id");
- oAuthConsumerSecret = result.getString("clientSecret");
- oAuthToken = result.getString("userToken");
- oAuthTokenSecret = result.getString("userSecret");
- email = result.getString("owner");
+ if (isSuccess()) {
+ if (json.get("result") instanceof JSONArray) {
+ JSONArray array = json.getJSONArray("result");
+ mCredentials = new Credentials[array.length()];
+ for (int i = 0; i < mCredentials.length; i++) {
+ mCredentials[i] = new Credentials(array.getJSONObject(i));
+ }
+ } else if (json.get("result") instanceof JSONObject) {
+ JSONObject result = json.getJSONObject("result");
+ mCredentials = new Credentials[1];
+ mCredentials[0] = new Credentials(result);
+ }
}
}
- public void saveCredentials(Context context) {
- Preferences.setServer(context, this.getServer());
-
- Preferences
- .getDefaultSharedPreferences(context)
- .edit()
- .putBoolean(context.getString(R.string.setting_account_loggedin_key), true)
- .commit();
-
- Preferences
- .getSharedPreferences("oauth")
- .edit()
- .putString(context.getString(R.string.setting_oauth_consumer_key),
- this.getoAuthConsumerKey())
- .putString(context.getString(R.string.setting_oauth_consumer_secret),
- this.getoAuthConsumerSecret())
- .putString(context.getString(R.string.setting_oauth_token),
- this.getoAuthToken())
- .putString(context.getString(R.string.setting_oauth_token_secret),
- this.getoAuthTokenSecret())
- .commit();
- }
-
@Override
public boolean isSuccess()
{
@@ -136,4 +63,8 @@ public String getAlertMessage() {
return super.getAlertMessage();
}
}
+
+ public Credentials[] getCredentials() {
+ return mCredentials;
+ }
}
diff --git a/app/src/com/trovebox/android/app/oauth/OAuthUtils.java b/app/src/com/trovebox/android/app/oauth/OAuthUtils.java
index a349d47..94a09b4 100644
--- a/app/src/com/trovebox/android/app/oauth/OAuthUtils.java
+++ b/app/src/com/trovebox/android/app/oauth/OAuthUtils.java
@@ -6,7 +6,9 @@
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.basic.DefaultOAuthConsumer;
-import android.app.Activity;
+
+import org.holoeverywhere.app.Activity;
+
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
diff --git a/app/src/com/trovebox/android/app/util/LoginUtils.java b/app/src/com/trovebox/android/app/util/LoginUtils.java
index 05b8d39..7bbff1b 100644
--- a/app/src/com/trovebox/android/app/util/LoginUtils.java
+++ b/app/src/com/trovebox/android/app/util/LoginUtils.java
@@ -2,14 +2,27 @@
package com.trovebox.android.app.util;
-import android.app.Activity;
+import org.holoeverywhere.app.Activity;
+import org.holoeverywhere.app.AlertDialog;
+import org.holoeverywhere.app.Dialog;
+
import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Bundle;
+
+import com.trovebox.android.app.MainActivity;
+import com.trovebox.android.app.R;
+import com.trovebox.android.app.common.CommonDialogFragment;
+import com.trovebox.android.app.model.Credentials;
+import com.trovebox.android.app.net.account.AccountTroveboxResponse;
public class LoginUtils
{
+ public static final String TAG = LoginUtils.class.getSimpleName();
+
public static String LOGIN_ACTION = "com.trovebox.ACTION_LOGIN";
public static BroadcastReceiver getAndRegisterDestroyOnLoginActionBroadcastReceiver(
@@ -35,4 +48,155 @@ public static void sendLoggedInBroadcast(Activity activity)
activity.sendBroadcast(intent);
}
+ /**
+ * Should be called by external activities/fragments after the logged in
+ * action completed
+ *
+ * @param activity
+ * @param finishActivity whether to finish activity after the MainActivity
+ * started
+ */
+ public static void onLoggedIn(Activity activity, boolean finishActivity) {
+ // start new activity
+ activity.startActivity(new Intent(activity, MainActivity.class));
+ LoginUtils.sendLoggedInBroadcast(activity);
+ if (finishActivity) {
+ activity.finish();
+ }
+ }
+
+ /**
+ * Common successful AccountTroveboxResult processor
+ *
+ * @param result
+ * @param fragmentAccessor
+ * @param activity
+ */
+ public static void processSuccessfulLoginResult(AccountTroveboxResponse result,
+ ObjectAccessor extends LoginActionHandler> fragmentAccessor, Activity activity) {
+ Credentials[] credentials = result.getCredentials();
+ if (credentials.length == 1) {
+ CommonUtils.debug(TAG, "processSuccessfulLoginResult: found one login credentials");
+ performLogin(fragmentAccessor, credentials[0]);
+ } else {
+ CommonUtils
+ .debug(TAG, "processSuccessfulLoginResult: found multiple login credentials");
+ SelectAccountDialogFragment selectionFragment = SelectAccountDialogFragment
+ .newInstance(new SelectAccountSelectedActionHandler(credentials,
+ fragmentAccessor));
+ selectionFragment.show(activity);
+ }
+ }
+
+ private static void performLogin(
+ ObjectAccessor extends LoginActionHandler> loginActionHandlerAccessor,
+ Credentials credentials) {
+ LoginActionHandler handler = loginActionHandlerAccessor.run();
+ if (handler != null) {
+ handler.processLoginCredentials(credentials);
+ } else {
+ String error = "Current instance accessor returned null";
+ CommonUtils.error(TAG, error);
+ TrackerUtils.trackException(error);
+ }
+ }
+
+ public static class SelectAccountSelectedActionHandler implements
+ SelectAccountDialogFragment.SelectedActionHandler {
+
+ ObjectAccessor extends LoginActionHandler> mLoginActionHandlerAccessor;
+ Credentials[] mCredentials;
+
+ public SelectAccountSelectedActionHandler(Credentials[] credentials,
+ ObjectAccessor extends LoginActionHandler> loginActoinHandlerAccessor) {
+ this.mCredentials = credentials;
+ this.mLoginActionHandlerAccessor = loginActoinHandlerAccessor;
+ }
+
+ @Override
+ public void itemSelected(int i) {
+ performLogin(mLoginActionHandlerAccessor, getItems()[i]);
+ }
+
+ @Override
+ public Credentials[] getItems() {
+ return mCredentials;
+ }
+
+ @Override
+ public ObjectAccessor extends LoginActionHandler> getLoginActionHandlerAccessor() {
+ return mLoginActionHandlerAccessor;
+ }
+ }
+
+ /**
+ * The interface the login/signup fragments should implement to use
+ * processSuccessfulLoginResult method
+ */
+ public static interface LoginActionHandler
+ {
+ void processLoginCredentials(Credentials credentials);
+ }
+
+ /**
+ * The dialog fragment which shows list of retrieved accounts where user can
+ * select one to login
+ */
+ public static class SelectAccountDialogFragment extends CommonDialogFragment {
+ public static final String HANDLER_ITEMS = "SelectAccountDialogFragment.handlerItems";
+ public static final String LOGIN_HANDLER_ACCESSOR = "SelectAccountDialogFragment.loginHandlerAccessor";
+
+ public static interface SelectedActionHandler {
+ void itemSelected(int i);
+
+ Credentials[] getItems();
+
+ ObjectAccessor extends LoginActionHandler> getLoginActionHandlerAccessor();
+ }
+
+ private SelectedActionHandler handler;
+
+ public static SelectAccountDialogFragment newInstance(SelectedActionHandler handler) {
+ SelectAccountDialogFragment frag = new SelectAccountDialogFragment();
+ frag.handler = handler;
+ return frag;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelableArray(HANDLER_ITEMS, handler.getItems());
+ outState.putSerializable(LOGIN_HANDLER_ACCESSOR, handler.getLoginActionHandlerAccessor());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ if (savedInstanceState != null) {
+ handler = new SelectAccountSelectedActionHandler(
+ (Credentials[]) savedInstanceState.getParcelableArray(HANDLER_ITEMS),
+ (ObjectAccessor) savedInstanceState
+ .getSerializable(LOGIN_HANDLER_ACCESSOR));
+ }
+
+ final String[] items = new String[handler.getItems().length];
+ for (int i = 0; i < items.length; i++) {
+ items[i] = handler.getItems()[i].getEmail();
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.select_trovebox_account);
+ builder.setItems(items, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int item) {
+ if (handler == null) {
+ return;
+ }
+ handler.itemSelected(item);
+ }
+ });
+ return builder.create();
+ }
+ }
+
}
diff --git a/test/res/raw/json_credentials.txt b/test/res/raw/json_credentials.txt
new file mode 100644
index 0000000..7354804
--- /dev/null
+++ b/test/res/raw/json_credentials.txt
@@ -0,0 +1,7 @@
+{ "clientSecret" : "0f5d654bca",
+ "host" : "apigee.trovebox.com",
+ "id" : "102230629a6802fbca9825a4617bfe",
+ "owner" : "hello@trovebox.com",
+ "userSecret" : "6d1e8fc274",
+ "userToken" : "b662440d621f2f71352f8865888fe2"
+}
\ No newline at end of file
diff --git a/test/res/raw/json_login_multiple.txt b/test/res/raw/json_login_multiple.txt
new file mode 100644
index 0000000..840c853
--- /dev/null
+++ b/test/res/raw/json_login_multiple.txt
@@ -0,0 +1,18 @@
+{ "code" : 200,
+ "message" : "User credentials",
+ "result" : [ { "clientSecret" : "0f5d654bca",
+ "host" : "apigee.trovebox.com",
+ "id" : "102230629a6802fbca9825a4617bfe",
+ "owner" : "hello@trovebox.com",
+ "userSecret" : "6d1e8fc274",
+ "userToken" : "b662440d621f2f71352f8865888fe2"
+ },
+ { "clientSecret" : "0f5d654bca",
+ "host" : "apigee.trovebox.com",
+ "id" : "102230629a6802fbca9825a4617bfe",
+ "owner" : "hello2@trovebox.com",
+ "userSecret" : "6d1e8fc274",
+ "userToken" : "b662440d621f2f71352f8865888fe2"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/test/res/raw/json_login_simple.txt b/test/res/raw/json_login_simple.txt
new file mode 100644
index 0000000..a588ee8
--- /dev/null
+++ b/test/res/raw/json_login_simple.txt
@@ -0,0 +1,10 @@
+{ "code" : 200,
+ "message" : "User credentials",
+ "result" : { "clientSecret" : "0f5d654bca",
+ "host" : "apigee.trovebox.com",
+ "id" : "102230629a6802fbca9825a4617bfe",
+ "owner" : "hello@trovebox.com",
+ "userSecret" : "6d1e8fc274",
+ "userToken" : "b662440d621f2f71352f8865888fe2"
+ }
+}
\ No newline at end of file
diff --git a/test/src/com/trovebox/android/test/model/CredentialsTest.java b/test/src/com/trovebox/android/test/model/CredentialsTest.java
new file mode 100644
index 0000000..2f270e0
--- /dev/null
+++ b/test/src/com/trovebox/android/test/model/CredentialsTest.java
@@ -0,0 +1,62 @@
+
+package com.trovebox.android.test.model;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.os.Parcel;
+import android.test.InstrumentationTestCase;
+
+import com.trovebox.android.app.model.Credentials;
+import com.trovebox.android.test.R;
+import com.trovebox.android.test.net.JSONUtils;
+
+public class CredentialsTest extends InstrumentationTestCase {
+ public void testFromJson() {
+ Credentials c;
+ try {
+ JSONObject json = JSONUtils
+.getJson(getInstrumentation().getContext(),
+ R.raw.json_credentials);
+ c = new Credentials(json);
+ } catch (JSONException e) {
+ throw new AssertionError("This exception should not be thrown!");
+ }
+
+ checkCredentials(c, "hello@trovebox.com");
+ }
+
+ public void testCredentialsParcelable() {
+ Credentials c;
+ try {
+ JSONObject json = JSONUtils
+.getJson(getInstrumentation().getContext(),
+ R.raw.json_credentials);
+ c = new Credentials(json);
+ } catch (JSONException e) {
+ throw new AssertionError("This exception should not be thrown!");
+ }
+
+ checkCredentials(c, "hello@trovebox.com");
+
+ Parcel parcel = Parcel.obtain();
+ c.writeToParcel(parcel, 0);
+ // done writing, now reset parcel for reading
+ parcel.setDataPosition(0);
+ // finish round trip
+ Credentials createFromParcel = Credentials.CREATOR.createFromParcel(parcel);
+
+ checkCredentials(createFromParcel, "hello@trovebox.com");
+ }
+
+ public static void checkCredentials(Credentials c, String email) {
+ assertNotNull(c);
+ assertEquals(c.getEmail(), email);
+ assertEquals(c.getServer(), "http://apigee.trovebox.com");
+ assertEquals(c.getoAuthConsumerKey(), "102230629a6802fbca9825a4617bfe");
+ assertEquals(c.getoAuthConsumerSecret(), "0f5d654bca");
+ assertEquals(c.getoAuthToken(), "b662440d621f2f71352f8865888fe2");
+ assertEquals(c.getoAuthTokenSecret(), "6d1e8fc274");
+
+ }
+}
diff --git a/test/src/com/trovebox/android/test/net/account/AccountTroveboxApiTest.java b/test/src/com/trovebox/android/test/net/account/AccountTroveboxApiTest.java
index de4f19f..6338cbc 100644
--- a/test/src/com/trovebox/android/test/net/account/AccountTroveboxApiTest.java
+++ b/test/src/com/trovebox/android/test/net/account/AccountTroveboxApiTest.java
@@ -21,6 +21,7 @@
import com.google.api.client.json.gson.GsonFactory;
import com.trovebox.android.app.R;
import com.trovebox.android.app.TroveboxApplication;
+import com.trovebox.android.app.model.Credentials;
import com.trovebox.android.app.net.account.AccountTroveboxResponse;
import com.trovebox.android.app.net.account.IAccountTroveboxApi;
import com.trovebox.android.app.net.account.IAccountTroveboxApiFactory;
@@ -87,10 +88,14 @@ public void testSignInViaGoogle() throws ClientProtocolException, IllegalStateEx
tokenString);
assertNotNull(response);
assertTrue(response.isSuccess());
- checkoAuthString(response.getoAuthConsumerKey());
- checkoAuthString(response.getoAuthConsumerSecret());
- checkoAuthString(response.getoAuthToken());
- checkoAuthString(response.getoAuthConsumerSecret());
+ Credentials[] credentials = response.getCredentials();
+ assertNotNull(credentials);
+ assertTrue(credentials.length > 0);
+ Credentials c = credentials[0];
+ checkoAuthString(c.getoAuthConsumerKey());
+ checkoAuthString(c.getoAuthConsumerSecret());
+ checkoAuthString(c.getoAuthToken());
+ checkoAuthString(c.getoAuthConsumerSecret());
}
diff --git a/test/src/com/trovebox/android/test/net/account/AccountTroveboxResponseTest.java b/test/src/com/trovebox/android/test/net/account/AccountTroveboxResponseTest.java
new file mode 100644
index 0000000..72e99ca
--- /dev/null
+++ b/test/src/com/trovebox/android/test/net/account/AccountTroveboxResponseTest.java
@@ -0,0 +1,41 @@
+package com.trovebox.android.test.net.account;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.test.InstrumentationTestCase;
+
+import com.trovebox.android.app.model.Credentials;
+import com.trovebox.android.app.net.TroveboxResponse.RequestType;
+import com.trovebox.android.app.net.account.AccountTroveboxResponse;
+import com.trovebox.android.test.R;
+import com.trovebox.android.test.model.CredentialsTest;
+import com.trovebox.android.test.net.JSONUtils;
+
+public class AccountTroveboxResponseTest extends InstrumentationTestCase {
+
+ public void testSimpleResponse() throws JSONException {
+ JSONObject json = JSONUtils.getJson(getInstrumentation().getContext(),
+ R.raw.json_login_simple);
+ AccountTroveboxResponse response = new AccountTroveboxResponse(RequestType.UNKNOWN, json);
+ assertNotNull(response);
+ assertEquals(200, response.getCode());
+ Credentials[] credentials = response.getCredentials();
+ assertNotNull(credentials);
+ assertTrue(credentials.length == 1);
+ CredentialsTest.checkCredentials(credentials[0], "hello@trovebox.com");
+ }
+
+ public void testMultiResponse() throws JSONException {
+ JSONObject json = JSONUtils.getJson(getInstrumentation().getContext(),
+ R.raw.json_login_multiple);
+ AccountTroveboxResponse response = new AccountTroveboxResponse(RequestType.UNKNOWN, json);
+ assertNotNull(response);
+ assertEquals(200, response.getCode());
+ Credentials[] credentials = response.getCredentials();
+ assertNotNull(credentials);
+ assertTrue(credentials.length == 2);
+ CredentialsTest.checkCredentials(credentials[0], "hello@trovebox.com");
+ CredentialsTest.checkCredentials(credentials[1], "hello2@trovebox.com");
+ }
+}