Added authorisation dialog - doesn't do anything yet, which is a shame considering how much code it took!
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="uk.org.openseizuredetector"
|
||||
android:versionCode="70"
|
||||
android:versionName="3.2.0">
|
||||
@@ -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"
|
||||
>
|
||||
<activity android:name=".DBQueryActivity"></activity>
|
||||
<!-- android:usesCleartextTraffic="true" -->
|
||||
<activity android:name=".StartupActivity">
|
||||
|
||||
78
app/src/main/java/uk/org/openseizuredetector/AuthDialog.java
Normal file
78
app/src/main/java/uk/org/openseizuredetector/AuthDialog.java
Normal file
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package uk.org.openseizuredetector;
|
||||
|
||||
public interface AuthDialogInterface {
|
||||
void onDialogDone(boolean state);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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()");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<LoggedInUser> 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
|
||||
}
|
||||
}
|
||||
@@ -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<LoggedInUser> login(String username, String password) {
|
||||
// handle login
|
||||
Result<LoggedInUser> result = dataSource.login(username, password);
|
||||
if (result instanceof Result.Success) {
|
||||
setLoggedInUser(((Result.Success<LoggedInUser>) result).getData());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -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<T> {
|
||||
// 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<T> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -9,18 +9,37 @@
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
tools:context="uk.org.openseizuredetector.LogManager">
|
||||
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:text="Large Text"
|
||||
android:id="@+id/textView2"
|
||||
android:text="@string/not_authenticated"
|
||||
android:id="@+id/authStatusTv"
|
||||
/>
|
||||
<Button
|
||||
android:id="@+id/authenticate_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/authenticate" />
|
||||
|
||||
<!--
|
||||
<ListView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/eventLogListView"
|
||||
android:layout_marginTop="97dp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ems="10"
|
||||
android:inputType="textPersonName"
|
||||
android:text="Name" />
|
||||
-->
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
52
app/src/main/res/layout/dialog_authenticate.xml
Normal file
52
app/src/main/res/layout/dialog_authenticate.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:src="@drawable/star_of_life_24x24"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:scaleType="center"
|
||||
android:background="#FFFFBB33"
|
||||
android:contentDescription="@string/app_name" />
|
||||
<EditText
|
||||
android:id="@+id/username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:hint="username" />
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
android:inputType="textPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:hint="password"/>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<Button
|
||||
android:id="@+id/cancelBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/cancel" />
|
||||
<Button
|
||||
android:id="@+id/OKBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/authenticate" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -46,6 +46,13 @@
|
||||
android:showAsAction="never|withText"
|
||||
android:title="Test SMS Alarm Notification" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_logmanager"
|
||||
android:icon="@drawable/ic_action_settings"
|
||||
android:showAsAction="never|withText"
|
||||
android:title="Data Log Manager"
|
||||
android:enabled="true"
|
||||
/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_logs"
|
||||
|
||||
@@ -2,4 +2,7 @@
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="fragment_horizontal_margin">16dp</dimen>
|
||||
<dimen name="fragment_vertical_margin">16dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -79,4 +79,16 @@
|
||||
<string name="CancelAudibleAlarms">Cancel Audible Alarms (temporarily)</string>
|
||||
<string name="AudibleAlarmsOff">Audible Alarms OFF</string>
|
||||
<string name="Fault">FAULT</string>
|
||||
<string name="authenticate">Authenticate</string>
|
||||
<string name="not_authenticated">Not Authenticated</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<!-- Strings related to login -->
|
||||
<string name="prompt_email">Email</string>
|
||||
<string name="prompt_password">Password</string>
|
||||
<string name="action_sign_in">Sign in or register</string>
|
||||
<string name="action_sign_in_short">Sign in</string>
|
||||
<string name="welcome">"Welcome!"</string>
|
||||
<string name="invalid_username">Not a valid username</string>
|
||||
<string name="invalid_password">Password must be >5 characters</string>
|
||||
<string name="login_failed">"Login failed"</string>
|
||||
</resources>
|
||||
|
||||
59
app/src/main/res/xml/logmanager_prefs.xml
Normal file
59
app/src/main/res/xml/logmanager_prefs.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<EditTextPreference
|
||||
android:defaultValue="https://osd.dynu.net/"
|
||||
android:key="serverUrl"
|
||||
android:title="Server URL"
|
||||
android:summary="URL of OpenSeizureDetector Data Log Server"
|
||||
/>
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="LogToServer"
|
||||
android:summary="Log Data to OpenSeizureDetector Server"
|
||||
android:title="Log to Server" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="UploadOverMobileNetwork"
|
||||
android:summary="Upload Data when using Mobile Network"
|
||||
android:title="Use Mobile Network" />
|
||||
<EditTextPreference
|
||||
android:defaultValue="password"
|
||||
android:key="OSDPasswd"
|
||||
android:summary="Password for remote data logging."
|
||||
android:title="Remote Password" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="PreventSleep"
|
||||
android:summary="Prevent the screen from blanking while the application is running."
|
||||
android:title="Prevent the screen from blanking." />
|
||||
<EditTextPreference
|
||||
android:defaultValue="1000"
|
||||
android:key="UpdatePeriod"
|
||||
android:summary="Display update period in miliseconds."
|
||||
android:title="Display Update Period (ms)." />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="AutoStart"
|
||||
android:summary="Auto Start App on Boot"
|
||||
android:title="Auto Start App on Boot"
|
||||
android:enabled="true"
|
||||
/>
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue=""
|
||||
android:key="AppVersionName"
|
||||
android:summary="App Version Number - used to decide whether to display the welcome message or not."
|
||||
android:title="App Version Number" />
|
||||
<!--
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="UseIpCamera"
|
||||
android:summary="Use IP Camera to View Images"
|
||||
android:title="Enable IP Camera"
|
||||
android:enabled="false"
|
||||
/>
|
||||
-->
|
||||
|
||||
|
||||
</PreferenceScreen>
|
||||
Reference in New Issue
Block a user