diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 928ad79..c445434 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ @@ -26,7 +27,8 @@ android:icon="@drawable/star_of_life_48x48" android:label="@string/app_name" android:networkSecurityConfig="@xml/network_security_config" - android:theme="@style/Theme.AppCompat"> + android:theme="@style/Theme.AppCompat" + > diff --git a/app/src/main/java/uk/org/openseizuredetector/AuthDialog.java b/app/src/main/java/uk/org/openseizuredetector/AuthDialog.java new file mode 100644 index 0000000..ed4d645 --- /dev/null +++ b/app/src/main/java/uk/org/openseizuredetector/AuthDialog.java @@ -0,0 +1,78 @@ +package uk.org.openseizuredetector; + + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; + +public class AuthDialog extends DialogFragment { + private String TAG = "AuthDialog"; + private AuthDialogInterface mListener; + private Context mContext; + private EditText mUnameEt; + private EditText mPasswdEt; + + @Override + public View onCreateView( + LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { + Log.v(TAG, "onCreateView()"); + View v = inflater.inflate(R.layout.dialog_authenticate, + container, false); + Button cancelBtn = + (Button) v.findViewById(R.id.cancelBtn); + cancelBtn.setOnClickListener(onCancel); + Button OKBtn = (Button) v.findViewById(R.id.OKBtn); + OKBtn.setOnClickListener(onOK); + + mUnameEt = (EditText) v.findViewById(R.id.username); + mPasswdEt = (EditText) v.findViewById(R.id.password); + + return v; + + } + + View.OnClickListener onCancel = + new View.OnClickListener() { + @Override + public void onClick(View view) { + Log.v(TAG, "onCancel"); + //m_status=false; + mListener.onDialogDone(false); + dismiss(); + } + }; + + View.OnClickListener onOK = + new View.OnClickListener() { + @Override + public void onClick(View view) { + //m_status=true; + Log.v(TAG, "onOK()"); + String uname = mUnameEt.getText().toString(); + String passwd = mPasswdEt.getText().toString(); + Log.v(TAG,"onOK() - uname="+uname+", passwd="+passwd); + mListener.onDialogDone(true); + dismiss(); + } + }; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + try { + mListener = (AuthDialogInterface) context; + } catch (ClassCastException e) { + throw new ClassCastException(context.toString() + + " must implement dialogDoneistener"); + } + } +} diff --git a/app/src/main/java/uk/org/openseizuredetector/AuthDialogInterface.java b/app/src/main/java/uk/org/openseizuredetector/AuthDialogInterface.java new file mode 100644 index 0000000..f59b062 --- /dev/null +++ b/app/src/main/java/uk/org/openseizuredetector/AuthDialogInterface.java @@ -0,0 +1,5 @@ +package uk.org.openseizuredetector; + +public interface AuthDialogInterface { + void onDialogDone(boolean state); +} \ No newline at end of file diff --git a/app/src/main/java/uk/org/openseizuredetector/LogManager.java b/app/src/main/java/uk/org/openseizuredetector/LogManager.java index 761d694..4f48765 100644 --- a/app/src/main/java/uk/org/openseizuredetector/LogManager.java +++ b/app/src/main/java/uk/org/openseizuredetector/LogManager.java @@ -175,6 +175,21 @@ public class LogManager { uploadSdData(); } + + /** + * Authenticate using the WebAPI to obtain a token for future API requests. + * @param uname - user name + * @param passwd - password + */ + public void authenticate(String uname, String passwd) { + Log.v(TAG, "authenticate()"); + // FIXME - this does not work!!!! + String dataStr = "data string to upload"; + //new PostDataTask().execute("http://" + mOSDUrl + ":8080/data", dataStr, mOSDUname, mOSDPasswd); + new PostDataTask().execute("http://192.168.43.175:8765/datapoints/add", dataStr, mOSDUname, mOSDPasswd); + + } + /** * Upload a batch of seizure detector data records to the server.. * Uses the UploadSdDataTask class to upload the data in the diff --git a/app/src/main/java/uk/org/openseizuredetector/LogManagerActivity.java b/app/src/main/java/uk/org/openseizuredetector/LogManagerActivity.java index 5da2319..27c0d0c 100644 --- a/app/src/main/java/uk/org/openseizuredetector/LogManagerActivity.java +++ b/app/src/main/java/uk/org/openseizuredetector/LogManagerActivity.java @@ -1,22 +1,25 @@ package uk.org.openseizuredetector; -import android.app.Activity; -import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.util.Log; +import android.view.View; +import android.widget.Button; import android.widget.ListView; -import java.util.Date; - import uk.org.openseizuredetector.EventLogManager.EventLogListAdapter; import uk.org.openseizuredetector.EventLogManager.EventLogManager; import uk.org.openseizuredetector.EventLogManager.LogEntryModel; -public class LogManagerActivity extends Activity { +public class LogManagerActivity extends FragmentActivity +implements AuthDialogInterface { + private String TAG = "LogManagerActivity"; private EventLogListAdapter mEventLogListAdapter; private ListView mEventLogListView; private EventLogManager mElm; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -28,15 +31,32 @@ public class LogManagerActivity extends Activity { lem.setDataJSON("[]"); lem.setAlarmState(1); - mElm = new EventLogManager(this); - mElm.addRow(lem); + //mElm = new EventLogManager(this); + //mElm.addRow(lem); - mEventLogListAdapter = new EventLogListAdapter(this); - mEventLogListView = (ListView) findViewById(R.id.eventLogListView); - mEventLogListView.setAdapter(mEventLogListAdapter); + //mEventLogListAdapter = new EventLogListAdapter(this); + //mEventLogListView = (ListView) findViewById(R.id.eventLogListView); + //mEventLogListView.setAdapter(mEventLogListAdapter); + Button b; + b = (Button) findViewById(R.id.authenticate_button); + b.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Log.v(TAG, "authenticate button clicked"); + AuthDialog authDialog = new AuthDialog(); + authDialog.show(getSupportFragmentManager(),"authDialog"); + } + }); } + public void updateUi() { + Log.v(TAG, "updateUi"); + } -} + public void onDialogDone(boolean State) { + Log.v(TAG,"onDialogDOne()"); + } + +} \ No newline at end of file diff --git a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java index d9f9270..52bb7d9 100644 --- a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java +++ b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java @@ -266,6 +266,17 @@ public class MainActivity extends AppCompatActivity { Log.i(TAG, "exception starting log manager activity " + ex.toString()); } return true; + case R.id.action_logmanager: + Log.i(TAG, "action_logmanager"); + try { + Intent intent = new Intent( + MainActivity.this, + LogManagerActivity.class); + this.startActivity(intent); + } catch (Exception ex) { + Log.i(TAG, "exception starting log manager activity " + ex.toString()); + } + return true; case R.id.action_settings: Log.i(TAG, "action_settings"); try { diff --git a/app/src/main/java/uk/org/openseizuredetector/data/LoginDataSource.java b/app/src/main/java/uk/org/openseizuredetector/data/LoginDataSource.java new file mode 100644 index 0000000..224ceed --- /dev/null +++ b/app/src/main/java/uk/org/openseizuredetector/data/LoginDataSource.java @@ -0,0 +1,29 @@ +package uk.org.openseizuredetector.data; + +import uk.org.openseizuredetector.data.model.LoggedInUser; + +import java.io.IOException; + +/** + * Class that handles authentication w/ login credentials and retrieves user information. + */ +public class LoginDataSource { + + public Result login(String username, String password) { + + try { + // TODO: handle loggedInUser authentication + LoggedInUser fakeUser = + new LoggedInUser( + java.util.UUID.randomUUID().toString(), + "Jane Doe"); + return new Result.Success<>(fakeUser); + } catch (Exception e) { + return new Result.Error(new IOException("Error logging in", e)); + } + } + + public void logout() { + // TODO: revoke authentication + } +} diff --git a/app/src/main/java/uk/org/openseizuredetector/data/LoginRepository.java b/app/src/main/java/uk/org/openseizuredetector/data/LoginRepository.java new file mode 100644 index 0000000..75df6a2 --- /dev/null +++ b/app/src/main/java/uk/org/openseizuredetector/data/LoginRepository.java @@ -0,0 +1,54 @@ +package uk.org.openseizuredetector.data; + +import uk.org.openseizuredetector.data.model.LoggedInUser; + +/** + * Class that requests authentication and user information from the remote data source and + * maintains an in-memory cache of login status and user credentials information. + */ +public class LoginRepository { + + private static volatile LoginRepository instance; + + private LoginDataSource dataSource; + + // If user credentials will be cached in local storage, it is recommended it be encrypted + // @see https://developer.android.com/training/articles/keystore + private LoggedInUser user = null; + + // private constructor : singleton access + private LoginRepository(LoginDataSource dataSource) { + this.dataSource = dataSource; + } + + public static LoginRepository getInstance(LoginDataSource dataSource) { + if (instance == null) { + instance = new LoginRepository(dataSource); + } + return instance; + } + + public boolean isLoggedIn() { + return user != null; + } + + public void logout() { + user = null; + dataSource.logout(); + } + + private void setLoggedInUser(LoggedInUser user) { + this.user = user; + // If user credentials will be cached in local storage, it is recommended it be encrypted + // @see https://developer.android.com/training/articles/keystore + } + + public Result login(String username, String password) { + // handle login + Result result = dataSource.login(username, password); + if (result instanceof Result.Success) { + setLoggedInUser(((Result.Success) result).getData()); + } + return result; + } +} diff --git a/app/src/main/java/uk/org/openseizuredetector/data/Result.java b/app/src/main/java/uk/org/openseizuredetector/data/Result.java new file mode 100644 index 0000000..cc92d09 --- /dev/null +++ b/app/src/main/java/uk/org/openseizuredetector/data/Result.java @@ -0,0 +1,48 @@ +package uk.org.openseizuredetector.data; + +/** + * A generic class that holds a result success w/ data or an error exception. + */ +public class Result { + // hide the private constructor to limit subclass types (Success, Error) + private Result() { + } + + @Override + public String toString() { + if (this instanceof Result.Success) { + Result.Success success = (Result.Success) this; + return "Success[data=" + success.getData().toString() + "]"; + } else if (this instanceof Result.Error) { + Result.Error error = (Result.Error) this; + return "Error[exception=" + error.getError().toString() + "]"; + } + return ""; + } + + // Success sub-class + public final static class Success extends Result { + private T data; + + public Success(T data) { + this.data = data; + } + + public T getData() { + return this.data; + } + } + + // Error sub-class + public final static class Error extends Result { + private Exception error; + + public Error(Exception error) { + this.error = error; + } + + public Exception getError() { + return this.error; + } + } +} diff --git a/app/src/main/java/uk/org/openseizuredetector/data/model/LoggedInUser.java b/app/src/main/java/uk/org/openseizuredetector/data/model/LoggedInUser.java new file mode 100644 index 0000000..806c32d --- /dev/null +++ b/app/src/main/java/uk/org/openseizuredetector/data/model/LoggedInUser.java @@ -0,0 +1,23 @@ +package uk.org.openseizuredetector.data.model; + +/** + * Data class that captures user information for logged in users retrieved from LoginRepository + */ +public class LoggedInUser { + + private String userId; + private String displayName; + + public LoggedInUser(String userId, String displayName) { + this.userId = userId; + this.displayName = displayName; + } + + public String getUserId() { + return userId; + } + + public String getDisplayName() { + return displayName; + } +} diff --git a/app/src/main/res/layout/activity_log_manager.xml b/app/src/main/res/layout/activity_log_manager.xml index 5143735..807bf4f 100644 --- a/app/src/main/res/layout/activity_log_manager.xml +++ b/app/src/main/res/layout/activity_log_manager.xml @@ -9,18 +9,37 @@ android:paddingTop="@dimen/activity_vertical_margin" tools:context="uk.org.openseizuredetector.LogManager"> + + +