commit 2554f0392300c42d9a7f171bed4ed9ef44b1d456 Author: unknown Date: Fri Jul 8 11:44:32 2022 +0200 first cmmit diff --git a/README.md b/README.md new file mode 100644 index 0000000..263056f --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# E4link Sample Project + +## Introduction + +This sample project gives you the boilerplate code you need to connect to an Empatica E4 device and start streaming data. + +The sample application implemented in the project has very simple functionalities: + +- It initializes the E4link library with your API key. +- If the previous step is successful, it starts scanning for Empatica devices, till it finds one that can be used with the API key you inserted in the code. +- When such a device has been found, the app connects to the devices and streams data for 10 seconds, then it disconnects. + +## Setup + +- Clone / download this repository. +- Open the sample project in Android Studio. +- Make sure you have a valid API key. You can request one for your Empatica Connect account from our [Developer Area][1]. +- Edit `MainActivity.java` and assign your API key to the `EMPATICA_API_KEY` constant . +- Download the Android E4 link 1.0 or newer SDK from our [Developer Area][1]. +- Unzip the archive you've downloaded and copy the `.aar` file you'll find inside into the `libs` folder contained in the sample project. +- Build and run the project. +- If a device is in range and its light is blinking green, but the app doesn't connect, please check that the discovered device can be used with your API key. If the `allowed` parameter is always false, the device is not linked to your API key. Please check your [Developer Area][1]. + +If you need any additional information about the Empatica API for Android, please check the [official documentation][2]. + +[1]: https://www.empatica.com/connect/developer.php +[2]: http://developer.empatica.com diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..eba4f5c --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,91 @@ +apply plugin: 'com.android.application' +apply plugin: 'com.google.gms.google-services' + +android { + compileSdkVersion 31 + useLibrary 'org.apache.http.legacy' + packagingOptions { + exclude 'META-INF/DEPENDENCIES' + exclude 'mozilla/public-suffix-list.txt' + + } + defaultConfig { + applicationId 'com.empatica.empalinksample' + minSdkVersion 19 + targetSdkVersion 30 + versionCode 2323 + versionName "1.2" + multiDexEnabled true + + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + productFlavors { + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + buildFeatures { + viewBinding true + } +} + +//// DE-COMMENT THIS IF YOU HAVE ISSUES AT RUNTIME, CRASHING WITH java.lang.UnsatisfiedLinkError + +//android { +// +// splits { +// +// // Configures multiple APKs based on ABI. +// abi { +// +// // Enables building multiple APKs per ABI. +// enable true +// +// // By default all ABIs are included, so use reset() and include to specify that we only +// // want APKs for x86, armeabi-v7a, and mips. +// +// // Resets the list of ABIs that Gradle should create APKs for to none. +// reset() +// +// // Specifies a list of ABIs that Gradle should create APKs for. +// include 'armeabi-v7a', 'x86', 'x86_64' // de-comment this to test on emulator +// // include 'armeabi-v7a' +// +// // Specifies that we do not want to also generate a universal APK that includes all ABIs. +// universalApk false +// } +// } +//} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.empatica.empalink:E4link:1.0.0@aar' + implementation 'com.squareup.okhttp:okhttp:2.7.5' + implementation platform('com.google.firebase:firebase-bom:29.1.0') + implementation 'com.google.firebase:firebase-analytics:20.1.0' + implementation 'com.google.firebase:firebase-storage:20.0.0' + implementation 'com.google.firebase:firebase-auth:21.0.1' + implementation 'com.google.firebase:firebase-firestore:24.0.1' + implementation 'androidx.multidex:multidex:2.0.1' + implementation 'com.google.firebase:firebase-database:20.0.3' + implementation 'androidx.recyclerview:recyclerview:1.2.1' + implementation 'androidx.cardview:cardview:1.0.0' + implementation 'com.google.firebase:firebase-crashlytics-buildtools:2.8.1' + implementation 'com.google.http-client:google-http-client-android:+' + implementation 'com.google.api-client:google-api-client-android:+' + implementation 'com.google.api-client:google-api-client-gson:+' + implementation 'com.squareup.okhttp3:okhttp:4.7.2' + implementation 'com.android.volley:volley:1.1.1' + implementation 'com.google.android.material:material:1.5.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + implementation 'androidx.navigation:navigation-fragment:2.3.5' + implementation 'androidx.navigation:navigation-ui:2.3.5' + implementation 'com.google.android.material:material:1.5.0-alpha02' +} \ No newline at end of file diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000..f00fff8 --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,69 @@ +{ + "project_info": { + "project_number": "800514867625", + "firebase_url": "https://empaticae4-3e023-default-rtdb.europe-west1.firebasedatabase.app", + "project_id": "empaticae4-3e023", + "storage_bucket": "empaticae4-3e023.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:800514867625:android:991bb941fb5f3d87df44b8", + "android_client_info": { + "package_name": "com.empatica.empalinksample" + } + }, + "oauth_client": [ + { + "client_id": "800514867625-i7rbc19o1ndunjim276j4us3tkake405.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAGCef7cUf5-b0CPiZMb1ZkiZN6JVKitRo" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "800514867625-i7rbc19o1ndunjim276j4us3tkake405.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:800514867625:android:ba61c3e2e28c1c8adf44b8", + "android_client_info": { + "package_name": "com.example.prueba" + } + }, + "oauth_client": [ + { + "client_id": "800514867625-i7rbc19o1ndunjim276j4us3tkake405.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAGCef7cUf5-b0CPiZMb1ZkiZN6JVKitRo" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "800514867625-i7rbc19o1ndunjim276j4us3tkake405.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/libs/_COPY HERE EMPALINK_ b/app/libs/_COPY HERE EMPALINK_ new file mode 100644 index 0000000..e66b232 --- /dev/null +++ b/app/libs/_COPY HERE EMPALINK_ @@ -0,0 +1 @@ +COPY HERE THE EMPALINK LIBRARY \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..77a0560 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/andrea/Library/Android/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9b60eeb --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/empatica/domain/Acceleration.java b/app/src/main/java/com/empatica/domain/Acceleration.java new file mode 100644 index 0000000..48b1cd1 --- /dev/null +++ b/app/src/main/java/com/empatica/domain/Acceleration.java @@ -0,0 +1,64 @@ +package com.empatica.domain; + +import java.io.Serializable; + +public class Acceleration implements Serializable{ + private String key; + private int acc_x; + private int acc_y; + private int acc_z; + private double timestamp; + + public Acceleration(){} + + public int getAcc_x() { + return acc_x; + } + + public void setAcc_x(int acc_x) { + this.acc_x = acc_x; + } + + public int getAcc_y() { + return acc_y; + } + + public void setAcc_y(int acc_y) { + this.acc_y = acc_y; + } + + public int getAcc_z() { + return acc_z; + } + + public void setAcc_z(int acc_z) { + this.acc_z = acc_z; + } + + public double getTimestamp() { + return timestamp; + } + + public void setTimestamp(double timestamp) { + this.timestamp = timestamp; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Acceleration(String key, int acc_x, int acc_y, int acc_z, double timestamp) { + this.key = key; + this.acc_x = acc_x; + this.acc_y = acc_y; + this.acc_z = acc_z; + this.timestamp = timestamp; + } + + + +} diff --git a/app/src/main/java/com/empatica/domain/BVP.java b/app/src/main/java/com/empatica/domain/BVP.java new file mode 100644 index 0000000..ed8544d --- /dev/null +++ b/app/src/main/java/com/empatica/domain/BVP.java @@ -0,0 +1,43 @@ +package com.empatica.domain; + +import java.io.Serializable; + +public class BVP implements Serializable{ + private String key; + private float bvp; + private double timestamp; + + public BVP(){} + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public BVP(String key, float bvp, double timestamp){ + this.key=key; + this.bvp=bvp; + this.timestamp=timestamp; + } + + public float getBvp() { + return bvp; + } + + public void setBvp(float bvp) { + this.bvp = bvp; + } + + public double getTimestamp() { + return timestamp; + } + + public void setTimestamp(double timestamp) { + this.timestamp = timestamp; + } + + +} diff --git a/app/src/main/java/com/empatica/domain/Click.java b/app/src/main/java/com/empatica/domain/Click.java new file mode 100644 index 0000000..af5df6f --- /dev/null +++ b/app/src/main/java/com/empatica/domain/Click.java @@ -0,0 +1,34 @@ +package com.empatica.domain; + +import java.io.Serializable; + +public class Click implements Serializable { + public String getDateInit() { + return dateInit; + } + + public void setDateInit(String dateInit) { + this.dateInit = dateInit; + } + + public String getDateEnd() { + return dateEnd; + } + + public void setDateEnd(String dateEnd) { + this.dateEnd = dateEnd; + } + + + public Click(String dateInit, String dateEnd) { + this.dateInit = dateInit; + this.dateEnd = dateEnd; + } + + public Click(){} + + private String dateInit; + private String dateEnd; + + +} diff --git a/app/src/main/java/com/empatica/domain/Data.java b/app/src/main/java/com/empatica/domain/Data.java new file mode 100644 index 0000000..70d8fc9 --- /dev/null +++ b/app/src/main/java/com/empatica/domain/Data.java @@ -0,0 +1,72 @@ +package com.empatica.domain; + +import java.io.Serializable; + +public class Data { + private float bvp; + private float gsr; + private float temp; + private float acc_x; + private float acc_y; + private float acc_z; + + + public float getBvp() { + return bvp; + } + + public void setBvp(float bvp) { + this.bvp = bvp; + } + + public float getGsr() { + return gsr; + } + + public void setGsr(float gsr) { + this.gsr = gsr; + } + + public float getTemp() { + return temp; + } + + public void setTemp(float temp) { + this.temp = temp; + } + + public float getAcc_x() { + return acc_x; + } + + public void setAcc_x(float acc_x) { + this.acc_x = acc_x; + } + + public float getAcc_y() { + return acc_y; + } + + public void setAcc_y(float acc_y) { + this.acc_y = acc_y; + } + + public float getAcc_z() { + return acc_z; + } + + public void setAcc_z(float acc_z) { + this.acc_z = acc_z; + } + + public Data(float bvp, float gsr, float temp, float acc_x, float acc_y, float acc_z) { + this.bvp = bvp; + this.gsr = gsr; + this.temp = temp; + this.acc_x = acc_x; + this.acc_y = acc_y; + this.acc_z = acc_z; + } + + public Data(){} +} diff --git a/app/src/main/java/com/empatica/domain/GSR.java b/app/src/main/java/com/empatica/domain/GSR.java new file mode 100644 index 0000000..9602c25 --- /dev/null +++ b/app/src/main/java/com/empatica/domain/GSR.java @@ -0,0 +1,41 @@ +package com.empatica.domain; + +import java.io.Serializable; + +public class GSR implements Serializable { + private String key; + private float gsr; + private double timestamp; + + public GSR(){} + + public float getGsr() { + return gsr; + } + + public void setGsr(float gsr) { + this.gsr = gsr; + } + + public double getTimestamp() { + return timestamp; + } + + public void setTimestamp(double timestamp) { + this.timestamp = timestamp; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public GSR(String key, float gsr, double timestamp) { + this.key = key; + this.gsr = gsr; + this.timestamp = timestamp; + } +} diff --git a/app/src/main/java/com/empatica/domain/IBI.java b/app/src/main/java/com/empatica/domain/IBI.java new file mode 100644 index 0000000..0e6c461 --- /dev/null +++ b/app/src/main/java/com/empatica/domain/IBI.java @@ -0,0 +1,41 @@ +package com.empatica.domain; + +import java.io.Serializable; + +public class IBI implements Serializable { + private String key; + private float ibi; + private double timestamp; + + public IBI(){} + + public float getIbi() { + return ibi; + } + + public void setIbi(float ibi) { + this.ibi = ibi; + } + + public double getTimestamp() { + return timestamp; + } + + public void setTimestamp(double timestamp) { + this.timestamp = timestamp; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public IBI(String key,float ibi, double timestamp) { + this.key = key; + this.ibi = ibi; + this.timestamp = timestamp; + } +} diff --git a/app/src/main/java/com/empatica/domain/SuperUser.java b/app/src/main/java/com/empatica/domain/SuperUser.java new file mode 100644 index 0000000..9d1f8ad --- /dev/null +++ b/app/src/main/java/com/empatica/domain/SuperUser.java @@ -0,0 +1,63 @@ +package com.empatica.domain; + +import java.io.Serializable; + +public class SuperUser implements Serializable { + private String email; + private String pass; + private String name; + private String gender; + private String age; + + public SuperUser(){} + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPass() { + return pass; + } + + public void setPass(String pass) { + this.pass = pass; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getAge() { + return age; + } + + public void setAge(String age) { + this.age = age; + } + + public SuperUser(String email, String age, String gender, String name, String pass) { + this.email = email; + this.age = age; + this.gender = gender; + this.name = name; + this.pass = pass; + + } + +} diff --git a/app/src/main/java/com/empatica/domain/Temperature.java b/app/src/main/java/com/empatica/domain/Temperature.java new file mode 100644 index 0000000..c1770b0 --- /dev/null +++ b/app/src/main/java/com/empatica/domain/Temperature.java @@ -0,0 +1,41 @@ +package com.empatica.domain; + +import java.io.Serializable; + +public class Temperature implements Serializable { + private String key; + private float temp; + private double timestamp; + + public Temperature(){} + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Temperature(String key, float temp, double timestamp) { + this.key = key; + this.temp = temp; + this.timestamp = timestamp; + } + + public float getTemp() { + return temp; + } + + public void setTemp(float temp) { + this.temp = temp; + } + + public double getTimestamp() { + return timestamp; + } + + public void setTimestamp(double timestamp) { + this.timestamp = timestamp; + } +} diff --git a/app/src/main/java/com/empatica/sample/AdapterUsers.java b/app/src/main/java/com/empatica/sample/AdapterUsers.java new file mode 100644 index 0000000..a151b1c --- /dev/null +++ b/app/src/main/java/com/empatica/sample/AdapterUsers.java @@ -0,0 +1,82 @@ +package com.empatica.sample; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.cardview.widget.CardView; + +import android.content.Context; +import android.os.storage.StorageManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AnimationUtils; +import android.widget.LinearLayout; +import android.widget.TextView; + +import java.lang.invoke.MethodType; +import java.util.List; + +//A class to handle the recycler view +public class AdapterUsers extends RecyclerView.Adapter { + + private OnItemClickListener clickListener; + private List listUsers; + private Context ctx; + + public AdapterUsers(List listUsers, Context ctx) { + this.listUsers=listUsers; + this.ctx=ctx; + } + + //Create new views (invoked by the layout manager) + @Override + public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType){ + LayoutInflater inflater = LayoutInflater.from(ctx); + View view = inflater.inflate(R.layout.list_layout, null); + view.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT)); + return new MyViewHolder(view, clickListener); + } + + //Replace the contents of a view (invoked by the layout manager) + @Override + public void onBindViewHolder(MyViewHolder holder, int position){ + //holder.cardView.setAnimation(AnimationUtils.loadAnimation(ctx,R.anim.item_fall_down)); + String name = listUsers.get(position); + holder.textViewName.setText(name); + } + + //Return the size of the dataset + @Override + public int getItemCount(){return listUsers.size();} + + public interface OnItemClickListener{ + void onItemClick(int position); + } + + public void setOnItemClickListener(OnItemClickListener listener){ + clickListener = listener; + } + + public class MyViewHolder extends RecyclerView.ViewHolder{ + + TextView textViewName; + CardView cardView; + + public MyViewHolder(View itemView, OnItemClickListener listener){ + super(itemView); + textViewName = itemView.findViewById(R.id.textName); + cardView = itemView.findViewById(R.id.card_view); + + itemView.setOnClickListener(new View.OnClickListener(){ + @Override + public void onClick(View view){ + if(listener != null){ + int position = getAdapterPosition(); + if(position != RecyclerView.NO_POSITION){ + listener.onItemClick(position); + } + } + } + }); + } + } +} diff --git a/app/src/main/java/com/empatica/sample/LoginActivity.java b/app/src/main/java/com/empatica/sample/LoginActivity.java new file mode 100644 index 0000000..73f31c4 --- /dev/null +++ b/app/src/main/java/com/empatica/sample/LoginActivity.java @@ -0,0 +1,110 @@ +package com.empatica.sample; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; + +import com.empatica.domain.SuperUser; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; + +//A class to handle the users login activity +public class LoginActivity extends AppCompatActivity implements View.OnClickListener{ + private EditText editTextEmail; + private EditText editTextPassword; + private Button buttonLogin; + private Button buttonRegister; + private String email=""; + private String pass=""; + private SuperUser superUser; + private FirebaseAuth firebaseAuth; + private DatabaseReference databaseReference; + + @Override + protected void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + editTextEmail=(EditText) findViewById(R.id.editTextEmail); + editTextPassword=(EditText) findViewById(R.id.editTextPassword); + buttonLogin=(Button) findViewById(R.id.buttonLogin); + buttonRegister=(Button)findViewById(R.id.buttonRegister); + + firebaseAuth = FirebaseAuth.getInstance(); + databaseReference = FirebaseDatabase.getInstance("https://empaticae4-3e023-default-rtdb.europe-west1.firebasedatabase.app").getReference(); + + buttonLogin.setOnClickListener(this); + buttonRegister.setOnClickListener(this); + } + //Check if the values of 'email' and 'pass' are correct in the data base + private void loginUser(){ + firebaseAuth.signInWithEmailAndPassword(email,pass).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if(task.isSuccessful()){ + getUser(); + }else{ + Toast.makeText(LoginActivity.this,"wrong labels",Toast.LENGTH_SHORT).show(); + } + } + }); + } + + //2 options, login or register. If the user click on register goes to the activity of register. If the user click on login + //the variables 'email' and 'pass' take the values of the editText and calls the function loginUser + @Override + public void onClick(View v){ + switch (v.getId()){ + case R.id.buttonRegister: + startActivity(new Intent(LoginActivity.this, RegisterActivity.class)); + case R.id.buttonLogin: + email =editTextEmail.getText().toString(); + pass = editTextPassword.getText().toString(); + if (!email.isEmpty()&&!pass.isEmpty()){ + loginUser(); + }else{ + Toast.makeText(LoginActivity.this,"Empty label",Toast.LENGTH_SHORT).show(); + } + } + } + + //take the user and send it to the other activity + private void getUser(){ + email = firebaseAuth.getCurrentUser().getEmail().substring(0,firebaseAuth.getCurrentUser().getEmail().indexOf("@")); + databaseReference.child("superUser").child(email).addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot snapshot) { + if(snapshot.exists()){ + superUser = snapshot.getValue(SuperUser.class); + + Intent main = new Intent(LoginActivity.this,UsersActivity.class); + Bundle bundleMain = new Bundle(); + bundleMain.putSerializable("superUser", superUser); + bundleMain.putSerializable("layout",1); + main.putExtras(bundleMain); + startActivity(main); + //finish(); + + } + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + + } + }); + + } +} diff --git a/app/src/main/java/com/empatica/sample/MainActivity.java b/app/src/main/java/com/empatica/sample/MainActivity.java new file mode 100644 index 0000000..0bdc234 --- /dev/null +++ b/app/src/main/java/com/empatica/sample/MainActivity.java @@ -0,0 +1,565 @@ +package com.empatica.sample; + +import android.Manifest; +import android.app.Activity; +import android.app.AlertDialog; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.le.ScanCallback; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Bundle; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import com.empatica.domain.Acceleration; +import com.empatica.domain.GSR; +import com.empatica.domain.IBI; +import com.empatica.domain.SuperUser; +import com.empatica.domain.Temperature; +import com.empatica.domain.Click; +import com.empatica.empalink.ConnectionNotAllowedException; +import com.empatica.empalink.EmpaDeviceManager; +import com.empatica.empalink.EmpaticaDevice; +import com.empatica.empalink.config.EmpaSensorStatus; +import com.empatica.empalink.config.EmpaSensorType; +import com.empatica.empalink.config.EmpaStatus; +import com.empatica.empalink.delegate.EmpaDataDelegate; +import com.empatica.empalink.delegate.EmpaStatusDelegate; + +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; + +import com.empatica.domain.BVP; +import com.google.firebase.database.ValueEventListener; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; + +public class MainActivity extends AppCompatActivity implements EmpaDataDelegate, EmpaStatusDelegate { + + private static final String TAG = "MainActivity"; + + private static final int REQUEST_ENABLE_BT = 1; + + private static final int REQUEST_PERMISSION_ACCESS_COARSE_LOCATION = 1; + + + private static final String EMPATICA_API_KEY = "dfb56ca6b87841bd88b2bc5b076bba0f"; // TODO insert your API Key here + + + private EmpaDeviceManager deviceManager = null; + + private TextView accel_xLabel; + private TextView accel_yLabel; + private TextView accel_zLabel; + private TextView bvpLabel; + private TextView edaLabel; + private TextView ibiLabel; + private TextView temperatureLabel; + private TextView batteryLabel; + private TextView statusLabel; + private TextView deviceNameLabel; + private LinearLayout dataCnt; + + private DatabaseReference databaseReference; + private FirebaseDatabase firebaseDatabase; + + private String nameUser; + private SuperUser superUser; + private ArrayList listsession; + private String session; + private String currentDateandTimeInit; + private String currentDateandTimeEnd; + private boolean firstSession=false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_main); + + // Initialize vars that reference UI components + statusLabel = (TextView) findViewById(R.id.status); + dataCnt = (LinearLayout) findViewById(R.id.dataArea); + accel_xLabel = (TextView) findViewById(R.id.accel_x); + accel_yLabel = (TextView) findViewById(R.id.accel_y); + accel_zLabel = (TextView) findViewById(R.id.accel_z); + bvpLabel = (TextView) findViewById(R.id.bvp); + edaLabel = (TextView) findViewById(R.id.eda); + ibiLabel = (TextView) findViewById(R.id.ibi); + temperatureLabel = (TextView) findViewById(R.id.temperature); + batteryLabel = (TextView) findViewById(R.id.battery); + deviceNameLabel = (TextView) findViewById(R.id.deviceName); + firebaseDatabase = FirebaseDatabase.getInstance("https://empaticae4-3e023-default-rtdb.europe-west1.firebasedatabase.app"); + databaseReference = firebaseDatabase.getReference(); + final Button disconnectButton = findViewById(R.id.disconnectButton); + Bundle extra = getIntent().getExtras(); + nameUser = (String) extra.getSerializable("user"); + superUser = (SuperUser) extra.getSerializable("superUser"); + getSession(); + + + disconnectButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + if (deviceManager != null) { + // Get the timestamp when the user disconnect the wristbrand + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z"); + currentDateandTimeEnd = sdf.format(new Date()); + deviceManager.disconnect(); + } + } + }); + initEmpaticaDeviceManager(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + switch (requestCode) { + case REQUEST_PERMISSION_ACCESS_COARSE_LOCATION: + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // Permission was granted, yay! + initEmpaticaDeviceManager(); + } else { + // Permission denied, boo! + final boolean needRationale = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION); + new AlertDialog.Builder(this) + .setTitle("Permission required") + .setMessage("Without this permission bluetooth low energy devices cannot be found, allow it in order to connect to the device.") + .setPositiveButton("Retry", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // try again + if (needRationale) { + // the "never ask again" flash is not set, try again with permission request + initEmpaticaDeviceManager(); + } else { + // the "never ask again" flag is set so the permission requests is disabled, try open app settings to enable the permission + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", getPackageName(), null); + intent.setData(uri); + startActivity(intent); + } + } + }) + .setNegativeButton("Exit application", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // without permission exit is the only way + finish(); + } + }) + .show(); + } + break; + } + } + + private void initEmpaticaDeviceManager() { + // Android 6 (API level 23) now require ACCESS_COARSE_LOCATION permission to use BLE + if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, REQUEST_PERMISSION_ACCESS_COARSE_LOCATION); + } else { + + if (TextUtils.isEmpty(EMPATICA_API_KEY)) { + new AlertDialog.Builder(this) + .setTitle("Warning") + .setMessage("Please insert your API KEY") + .setNegativeButton("Close", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // without permission exit is the only way + finish(); + } + }) + .show(); + return; + } + + // Create a new EmpaDeviceManager. MainActivity is both its data and status delegate. + deviceManager = new EmpaDeviceManager(getApplicationContext(), this, this); + + // Initialize the Device Manager using your API key. You need to have Internet access at this point. + deviceManager.authenticateWithAPIKey(EMPATICA_API_KEY); + } + } + + @Override + protected void onPause() { + super.onPause(); + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + if (deviceManager != null) { + deviceManager.cleanUp(); + } + } + + @Override + protected void onStop() { + super.onStop(); + if (deviceManager != null) { + deviceManager.stopScanning(); + } + } + + @Override + public void didDiscoverDevice(EmpaticaDevice bluetoothDevice, String deviceName, int rssi, boolean allowed) { + // Check if the discovered device can be used with your API key. If allowed is always false, + // the device is not linked with your API key. Please check your developer area at + // https://www.empatica.com/connect/developer.php + + Log.i(TAG, "didDiscoverDevice" + deviceName + "allowed: " + allowed); + + if (allowed) { + // Stop scanning. The first allowed device will do. + deviceManager.stopScanning(); + try { + // Connect to the device + deviceManager.connectDevice(bluetoothDevice); + updateLabel(deviceNameLabel, "To: " + deviceName); + } catch (ConnectionNotAllowedException e) { + // This should happen only if you try to connect when allowed == false. + Toast.makeText(MainActivity.this, "Sorry, you can't connect to this device", Toast.LENGTH_SHORT).show(); + Log.e(TAG, "didDiscoverDevice" + deviceName + "allowed: " + allowed + " - ConnectionNotAllowedException", e); + } + } + } + + @Override + public void didFailedScanning(int errorCode) { + + /* + A system error occurred while scanning. + @see https://developer.android.com/reference/android/bluetooth/le/ScanCallback + */ + switch (errorCode) { + case ScanCallback.SCAN_FAILED_ALREADY_STARTED: + Log.e(TAG,"Scan failed: a BLE scan with the same settings is already started by the app"); + break; + case ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED: + Log.e(TAG,"Scan failed: app cannot be registered"); + break; + case ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED: + Log.e(TAG,"Scan failed: power optimized scan feature is not supported"); + break; + case ScanCallback.SCAN_FAILED_INTERNAL_ERROR: + Log.e(TAG,"Scan failed: internal error"); + break; + default: + Log.e(TAG,"Scan failed with unknown error (errorCode=" + errorCode + ")"); + break; + } + } + + @Override + public void didRequestEnableBluetooth() { + // Request the user to enable Bluetooth + Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); + } + + @Override + public void bluetoothStateChanged() { + // E4link detected a bluetooth adapter change + // Check bluetooth adapter and update your UI accordingly. + boolean isBluetoothOn = BluetoothAdapter.getDefaultAdapter().isEnabled(); + Log.i(TAG, "Bluetooth State Changed: " + isBluetoothOn); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // The user chose not to enable Bluetooth + if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) { + // You should deal with this + return; + } + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public void didUpdateSensorStatus(@EmpaSensorStatus int status, EmpaSensorType type) { + + didUpdateOnWristStatus(status); + } + + @Override + public void didUpdateStatus(EmpaStatus status) { + // Update the UI + updateLabel(statusLabel, status.name()); + + // The device manager is ready for use + if (status == EmpaStatus.READY) { + updateLabel(statusLabel, status.name() + " - Turn on your device"); + // Start scanning + deviceManager.startScanning(); + // The device manager has established a connection + + hide(); + + } else if (status == EmpaStatus.CONNECTED) { + // Get the timestamp when the user connect the wristbrand + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z"); + currentDateandTimeInit = sdf.format(new Date()); + show(); + // The device manager disconnected from a device + } else if (status == EmpaStatus.DISCONNECTED) { + String email = superUser.getEmail(); + if(firstSession==true) { // Check if is the first session of the user + databaseReference.child("users").child(email).child(nameUser).removeValue(); + } + Click click = new Click(); + click.setDateInit(currentDateandTimeInit); + click.setDateEnd(currentDateandTimeEnd); + // Store the timestamp of connect and disconnect in the data base + databaseReference.child("users").child(email).child(nameUser).child(session).setValue(click); + updateLabel(deviceNameLabel, ""); + + hide(); + } + } + + // Receive the acceleration of the wristband + @Override + public void didReceiveAcceleration(int x, int y, int z, double timestamp) { + Acceleration acc = new Acceleration(); + updateLabel(accel_xLabel, "" + x); + updateLabel(accel_yLabel, "" + y); + updateLabel(accel_zLabel, "" + z); + String email = superUser.getEmail(); + acc.setAcc_x(x); + acc.setAcc_y(y); + acc.setAcc_z(z); + acc.setTimestamp(timestamp); + Date date = new Date((long)timestamp*1000); + String year = getYear(date.getYear()); + String month = getMonth(date.getMonth()); + String day = getDay(); + String hour = String.valueOf(date.getHours()); + String minute = String.valueOf(date.getMinutes()); + String second = String.valueOf(date.getSeconds()); + // Store the acceleration with the date in the data base + databaseReference.child("acceleration").child(email).child(nameUser).child(session).child(year).child(month).child(day).child(hour).child(minute).child(second).push().setValue(acc); + } + + // Receive the BVP of the wristband + @Override + public void didReceiveBVP(float bvp, double timestamp) { + BVP classbvp = new BVP(); + updateLabel(bvpLabel, "" + bvp); + String email = superUser.getEmail(); + classbvp.setBvp(bvp); + classbvp.setTimestamp(timestamp); + Date date = new Date((long)timestamp*1000); + String year = getYear(date.getYear()); + String month = getMonth(date.getMonth()); + String day = getDay(); + String hour = String.valueOf(date.getHours()); + String minute = String.valueOf(date.getMinutes()); + String second = String.valueOf(date.getSeconds()); + // Store the BVP with the date in the data base + databaseReference.child("bvp").child(email).child(nameUser).child(session).child(year).child(month).child(day).child(hour).child(minute).child(second).push().setValue(classbvp); + + } + + @Override + public void didReceiveBatteryLevel(float battery, double timestamp) { + updateLabel(batteryLabel, String.format("%.0f %%", battery * 100)); + } + + // Receive the GSR of the wristband + @Override + public void didReceiveGSR(float gsr, double timestamp) { + GSR classgsr = new GSR(); + updateLabel(edaLabel, "" + gsr); + String email = superUser.getEmail(); + classgsr.setGsr(gsr); + classgsr.setTimestamp(timestamp); + Date date = new Date((long)timestamp*1000); + String year = getYear(date.getYear()); + String month = getMonth(date.getMonth()); + String day = getDay(); + String hour = String.valueOf(date.getHours()); + String minute = String.valueOf(date.getMinutes()); + String second = String.valueOf(date.getSeconds()); + // Store the GSR with the date in the data base + databaseReference.child("gsr").child(email).child(nameUser).child(session).child(year).child(month).child(day).child(hour).child(minute).child(second).push().setValue(classgsr); + } + + // Receive the IBI of the wristband + @Override + public void didReceiveIBI(float ibi, double timestamp) { + IBI classibi = new IBI(); + updateLabel(ibiLabel, "" + ibi); + String email = superUser.getEmail(); + classibi.setIbi(ibi); + classibi.setTimestamp(timestamp); + Date date = new Date((long)timestamp*1000); + String year = getYear(date.getYear()); + String month = getMonth(date.getMonth()); + String day = getDay(); + String hour = String.valueOf(date.getHours()); + String minute = String.valueOf(date.getMinutes()); + String second = String.valueOf(date.getSeconds()); + // Store the IBI with the date in the data base + databaseReference.child("ibi").child(email).child(nameUser).child(session).child(year).child(month).child(day).child(hour).child(minute).child(second).push().setValue(classibi); + } + + // Receive the temperature of the wristband + @Override + public void didReceiveTemperature(float temp, double timestamp) { + Temperature classtemp = new Temperature(); + updateLabel(temperatureLabel, "" + temp); + String email = superUser.getEmail(); + classtemp.setTemp(temp); + classtemp.setTimestamp(timestamp); + Date date = new Date((long)timestamp*1000); + String year = getYear(date.getYear()); + String month = getMonth(date.getMonth()); + String day = getDay(); + String hour = String.valueOf(date.getHours()); + String minute = String.valueOf(date.getMinutes()); + String second = String.valueOf(date.getSeconds()); + // Store the temperature with the date in the data base + databaseReference.child("temp").child(email).child(nameUser).child(session).child(year).child(month).child(day).child(hour).child(minute).child(second).push().setValue(classtemp); + } + + public String getYear(int year){ + return String.valueOf(year+1900); + } + + public String getMonth(int month){ + if(month==12){ + month=1; + }else{ + month=month+1; + } + return String.valueOf(month); + } + + public String getDay(){ + SimpleDateFormat sdf = new SimpleDateFormat("dd"); + String dia = sdf.format(new Date()); + return dia; + } + + // Check if is the first session of the user for change the first value of the data base because to create the user + // in firebase needs to create with min one child, in this case the session 0 + private void getSession(){ + String email = superUser.getEmail(); + databaseReference.child("users").child(email).child(nameUser).addListenerForSingleValueEvent(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot snapshot) { + listsession = new ArrayList<>(); + int ss; + if (snapshot.exists()) { + for (DataSnapshot ds : snapshot.getChildren()) { + String s =ds.getKey().toString(); + listsession.add(s); + + } + if (listsession.get(0).equals("0")){ + ss=0; + firstSession=true; + }else{ + ss=listsession.size(); + } + ss++; + session=String.valueOf(ss); + + } + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + + } + }); + + } + + // Update a label with some text, making sure this is run in the UI thread + private void updateLabel(final TextView label, final String text) { + runOnUiThread(new Runnable() { + @Override + public void run() { + label.setText(text); + } + }); + } + + @Override + public void didReceiveTag(double timestamp) { + + } + + @Override + public void didEstablishConnection() { + + show(); + } + + @Override + public void didUpdateOnWristStatus(@EmpaSensorStatus final int status) { + + runOnUiThread(new Runnable() { + + @Override + public void run() { + + if (status == EmpaSensorStatus.ON_WRIST) { + + ((TextView) findViewById(R.id.wrist_status_label)).setText("ON WRIST"); + } + else { + + ((TextView) findViewById(R.id.wrist_status_label)).setText("NOT ON WRIST"); + } + } + }); + } + + void show() { + + runOnUiThread(new Runnable() { + + @Override + public void run() { + + dataCnt.setVisibility(View.VISIBLE); + } + }); + } + + void hide() { + + runOnUiThread(new Runnable() { + + @Override + public void run() { + + dataCnt.setVisibility(View.INVISIBLE); + } + }); + } +} diff --git a/app/src/main/java/com/empatica/sample/MySingleton.java b/app/src/main/java/com/empatica/sample/MySingleton.java new file mode 100644 index 0000000..14f78c0 --- /dev/null +++ b/app/src/main/java/com/empatica/sample/MySingleton.java @@ -0,0 +1,42 @@ +package com.empatica.sample; + +import android.content.Context; + +import com.android.volley.Request; +import com.android.volley.RequestQueue; +import com.android.volley.toolbox.Volley; + + +public class MySingleton { + private static MySingleton instance; + private RequestQueue requestQueue; + private static Context ctx; + + private MySingleton(Context context) { + ctx = context; + requestQueue = getRequestQueue(); + + + } + + public static synchronized MySingleton getInstance(Context context) { + if (instance == null) { + instance = new MySingleton(context); + } + return instance; + } + + public RequestQueue getRequestQueue() { + if (requestQueue == null) { + // getApplicationContext() is key, it keeps you from leaking the + // Activity or BroadcastReceiver if someone passes one in. + requestQueue = Volley.newRequestQueue(ctx.getApplicationContext()); + } + return requestQueue; + } + + public void addToRequestQueue(Request req) { + getRequestQueue().add(req); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/empatica/sample/ProfileActivity.java b/app/src/main/java/com/empatica/sample/ProfileActivity.java new file mode 100644 index 0000000..dd64483 --- /dev/null +++ b/app/src/main/java/com/empatica/sample/ProfileActivity.java @@ -0,0 +1,65 @@ +package com.empatica.sample; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; + +import com.empatica.domain.SuperUser; + +import java.io.IOException; + + +//A class to handle 2 possible options, click on saved sessions or click on create new session +public class ProfileActivity extends AppCompatActivity implements View.OnClickListener{ + + private SuperUser superUser; + private String name; + private Button buttonSaved; + private Button buttonSession; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_profile); + buttonSession = (Button) findViewById(R.id.buttonSession); + buttonSaved = (Button) findViewById(R.id.buttonSaved); + Bundle extra = getIntent().getExtras(); + superUser = (SuperUser) extra.getSerializable("superUser"); + name = (String) extra.getSerializable("user"); + buttonSaved.setOnClickListener(this); + buttonSession.setOnClickListener(this); + + } + + @Override + public void onClick(View v){ + switch (v.getId()){ + case R.id.buttonSaved: + Intent main1 = new Intent(ProfileActivity.this, UsersActivity.class); + Bundle bundleMain = new Bundle(); + bundleMain.putSerializable("superUser", superUser); + bundleMain.putSerializable("user",name); + bundleMain.putSerializable("layout",2); + main1.putExtras(bundleMain); + startActivity(main1); + //finish(); + case R.id.buttonSession: + Intent main2 = new Intent(ProfileActivity.this, MainActivity.class); + bundleMain = new Bundle(); + bundleMain.putSerializable("superUser", superUser); + bundleMain.putSerializable("user",name); + main2.putExtras(bundleMain); + startActivity(main2); + //finish(); + } + } + + +} diff --git a/app/src/main/java/com/empatica/sample/RegisterActivity.java b/app/src/main/java/com/empatica/sample/RegisterActivity.java new file mode 100644 index 0000000..57f1125 --- /dev/null +++ b/app/src/main/java/com/empatica/sample/RegisterActivity.java @@ -0,0 +1,114 @@ +package com.empatica.sample; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; + +import com.empatica.domain.SuperUser; +import com.google.android.gms.tasks.OnCanceledListener; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; + +public class RegisterActivity extends AppCompatActivity implements View.OnClickListener{ + private Button buttonRegister; + private EditText editTextEmail; + private EditText editTextPassword; + private EditText editTextPasswordRepeat; + private EditText editTextName; + private EditText editTextGender; + private EditText editTextAge; + private FirebaseAuth firebaseAuth; + private DatabaseReference databaseReference; + + @Override + protected void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_register); + editTextEmail=(EditText) findViewById(R.id.editTextEmail); + editTextPassword=(EditText) findViewById(R.id.editTextPassword); + editTextPasswordRepeat=(EditText)findViewById(R.id.editTextPasswordRepeat); + editTextAge=(EditText)findViewById(R.id.editTextAge); + editTextGender=(EditText)findViewById(R.id.editTextGender); + editTextName=(EditText)findViewById(R.id.editTextName); + buttonRegister=(Button)findViewById(R.id.buttonRegister); + + firebaseAuth = FirebaseAuth.getInstance(); + databaseReference = FirebaseDatabase.getInstance("https://empaticae4-3e023-default-rtdb.europe-west1.firebasedatabase.app").getReference(); + + buttonRegister.setOnClickListener(this); + } + + @Override + public void onClick(View v){ + switch (v.getId()){ + case R.id.buttonRegister: + String email = editTextEmail.getText().toString(); + String pass = editTextPassword.getText().toString(); + String repass= editTextPasswordRepeat.getText().toString(); + String name=editTextName.getText().toString(); + String age=editTextAge.getText().toString(); + String gender=editTextGender.getText().toString(); + if(!email.isEmpty()&&!pass.isEmpty()&&!repass.isEmpty()&&!name.isEmpty()&&!age.isEmpty()&&!gender.isEmpty()){ + //got the values + if(pass.equals(repass)){ + //password matched + if(pass.length()>6){ + firebaseAuth.createUserWithEmailAndPassword(email,pass).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if(task.isSuccessful()){ + //user created + SuperUser superUser = new SuperUser(); + String email2= email.substring(0,email.indexOf("@")); + superUser.setEmail(email2); + superUser.setPass(pass); + superUser.setAge(age); + superUser.setGender(gender); + superUser.setEmail(name); + databaseReference.child("superUser").child(email2).setValue(superUser); + startActivity(new Intent(RegisterActivity.this, LoginActivity.class)); + finish(); + }else{ + //Something went wrong + Toast.makeText(RegisterActivity.this,"Something went wrong please try again", Toast.LENGTH_SHORT).show(); + } + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + //Failed + Toast.makeText(RegisterActivity.this,"Error: "+e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); + } + }).addOnCanceledListener(new OnCanceledListener() { + @Override + public void onCanceled() { + Toast.makeText(RegisterActivity.this,"Canceled, try again!", Toast.LENGTH_SHORT).show(); + } + }) + ; + }else{ + //pass length short + Toast.makeText(RegisterActivity.this,"Password must be 6 character long", Toast.LENGTH_SHORT).show(); + } + + }else{ + Toast.makeText(RegisterActivity.this,"Password must be the same", Toast.LENGTH_SHORT).show(); + } + }else{ + Toast.makeText(RegisterActivity.this,"Empty labels", Toast.LENGTH_SHORT).show(); + } + + } + } +} diff --git a/app/src/main/java/com/empatica/sample/SavedSessionsActivity.java b/app/src/main/java/com/empatica/sample/SavedSessionsActivity.java new file mode 100644 index 0000000..b0a9d69 --- /dev/null +++ b/app/src/main/java/com/empatica/sample/SavedSessionsActivity.java @@ -0,0 +1,584 @@ +package com.empatica.sample; + +import android.graphics.Color; +import android.os.Bundle; +import android.widget.TableLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import android.util.Log; + +import com.android.volley.DefaultRetryPolicy; +import com.android.volley.RequestQueue; +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.JsonArrayRequest; +import com.android.volley.toolbox.JsonObjectRequest; +import com.android.volley.toolbox.Volley; + +import org.checkerframework.checker.units.qual.A; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import com.empatica.domain.Acceleration; +import com.empatica.domain.BVP; +import com.empatica.domain.Data; +import com.empatica.domain.GSR; +import com.empatica.domain.SuperUser; +import com.empatica.domain.Temperature; +import com.google.firebase.database.ChildEventListener; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.ValueEventListener; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +import java.util.ArrayList; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.FormBody; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.RequestBody; + +import android.widget.TextView; +import android.widget.Toast; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.IOException; + +//A class to display the data of the session in a table +public class SavedSessionsActivity extends AppCompatActivity { + + private TableLayout tableLayout; + private TableDynamic tableDynamic; + private TextView textViewMood; + private String[] header = {"Time","BVP (BPM)", "GSR (µS)", "Temperature (ºC)","Acceleration x","Acceleration y","Acceleration z"}; + private ArrayList rows = new ArrayList<>(); + private DatabaseReference databaseReference; + private ArrayList listTemp, listBvp, listGsr, listAccx, listAccy, listAccz, listTime; + private ArrayList avgTemp, avgBvp, avgGsr, avgAccx, avgAccy, avgAccz; + private SuperUser superUser; + private String name; + private String session; + private String s, yearI, yearE, monthI, monthE, dayI, dayE, hourI="", hourE, minutI="", minutE, secondI="", secondE; //Variables of initial and end of the time + private int ints, intyearI, intyearE, intmonthI, intmonthE, intdayI, intdayE, inthourI, inthourE, intminutI, intminutE, intsecondI, intsecondE; + + private String postBodyString; + private MediaType mediaType; + private RequestBody requestBody; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_table); + databaseReference = FirebaseDatabase.getInstance("https://empaticae4-3e023-default-rtdb.europe-west1.firebasedatabase.app").getReference(); + Bundle extra = getIntent().getExtras(); + superUser = (SuperUser) extra.getSerializable("superUser"); + name = (String) extra.getSerializable("user"); + session = (String) extra.getSerializable("session"); + textViewMood = (TextView) findViewById(R.id.textViewMood); + tableLayout = (TableLayout) findViewById(R.id.table); + tableDynamic = new TableDynamic(tableLayout, getApplicationContext()); + getDate(); //Initialize the variables yearI, yearE, etc + avgAccx = new ArrayList<>(); + avgAccy = new ArrayList<>(); + avgAccz = new ArrayList<>(); + avgTemp = new ArrayList<>(); + avgBvp = new ArrayList<>(); + avgGsr = new ArrayList<>(); + listTime = new ArrayList<>(); + ints=Integer.parseInt(s); + intyearI=Integer.parseInt(yearI); + intmonthI=Integer.parseInt(monthI); + intdayI=Integer.parseInt(dayI); + inthourI=Integer.parseInt(hourI); + intminutI=Integer.parseInt(minutI); + intsecondI=Integer.parseInt(secondI); + intyearE=Integer.parseInt(yearE); + intmonthE=Integer.parseInt(monthE); + intdayE=Integer.parseInt(dayE); + inthourE=Integer.parseInt(hourE); + intminutE=Integer.parseInt(minutE); + intsecondE=Integer.parseInt(secondE); + getAcc(); + getBvp(); + getGsr(); + getTemp(); + + + } + + //Get accelerometer data but only the session data, from start time to end time of the session + private void getAcc() { + String email = superUser.getEmail(); + for(int i=intyearI; i<=intyearE;i++){ + for(int j=intmonthI; j<=intmonthE;j++){ + for(int k=intdayI; k<=intdayE; k++){ + for(int l=inthourI; l<=inthourE; l++){ + for(int m=intminutI; m<=intminutE; m++){ + for(int p = intsecondI; p(); + listAccy = new ArrayList<>(); + listAccz = new ArrayList<>(); + if (snapshot.exists()) { + for (DataSnapshot ds : snapshot.getChildren()) { + Acceleration acc = ds.getValue(Acceleration.class); + String datax = String.valueOf(acc.getAcc_x()); + String datay = String.valueOf(acc.getAcc_y()); + String dataz = String.valueOf(acc.getAcc_z()); + listAccx.add(datax); + listAccy.add(datay); + listAccz.add(dataz); + } + + } + //Calculates the average of all data collected in one second + Double a=AVG(listAccx); + avgAccx.add(String.valueOf(Math.round(a*100.0)/100.0)); + Double b=AVG(listAccy); + avgAccy.add(String.valueOf(Math.round(b*100.0)/100.0)); + Double c=AVG(listAccz); + avgAccz.add(String.valueOf(Math.round(c*100.0)/100.0)); + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + + } + }); + } + } + } + } + } + } + } + + //Get BVP data but only the session data, from start time to end time of the session + private void getBvp(){ + String email = superUser.getEmail(); + for(int i=intyearI; i<=intyearE;i++){ + for(int j=intmonthI; j<=intmonthE;j++){ + for(int k=intdayI; k<=intdayE; k++){ + for(int l=inthourI; l<=inthourE; l++){ + for(int m=intminutI; m<=intminutE; m++){ + for(int p = intsecondI; p(); + if (snapshot.exists()) { + for (DataSnapshot ds : snapshot.getChildren()) { + BVP bvp = ds.getValue(BVP.class); + String data = String.valueOf(bvp.getBvp()); + listBvp.add(data); + } + + } + //Calculates the average of all data collected in one second + Double a=AVG(listBvp); + avgBvp.add(String.valueOf(Math.round(a*100.0)/100.0)); + String stamp =String.valueOf(finalK)+"-"+String.valueOf(finalJ)+"-"+String.valueOf(finalI)+" "+String.valueOf(finalL)+":"+String.valueOf(finalM)+":"+String.valueOf(finalP); + listTime.add(stamp); + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + + } + }); + } + } + } + } + } + } + } + + //Get GSR data but only the session data, from start time to end time of the session + private void getGsr(){ + String email = superUser.getEmail(); + for(int i=intyearI; i<=intyearE;i++){ + for(int j=intmonthI; j<=intmonthE;j++){ + for(int k=intdayI; k<=intdayE; k++){ + for(int l=inthourI; l<=inthourE; l++){ + for(int m=intminutI; m<=intminutE; m++){ + for(int p = intsecondI; p(); + if (snapshot.exists()) { + for (DataSnapshot ds : snapshot.getChildren()) { + GSR gsr = ds.getValue(GSR.class); + String data = String.valueOf(gsr.getGsr()); + listGsr.add(data); + } + + } + //Calculates the average of all data collected in one second + Double a=AVG(listGsr); + avgGsr.add(String.valueOf(Math.round(a*100.0)/100.0)); + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + + } + }); + } + } + } + } + } + } + } + //Get temperature data but only the session data, from start time to end time of the session + private void getTemp(){ + String email = superUser.getEmail(); + for(int i=intyearI; i<=intyearE;i++){ + for(int j=intmonthI; j<=intmonthE;j++){ + for(int k=intdayI; k<=intdayE; k++){ + for(int l=inthourI; l<=inthourE; l++){ + for(int m=intminutI; m<=intminutE; m++){ + for(int p = intsecondI; p(); + if (snapshot.exists()) { + for (DataSnapshot ds : snapshot.getChildren()) { + Temperature temp = ds.getValue(Temperature.class); + String data = String.valueOf(temp.getTemp()); + listTemp.add(data); + } + + + //Calculates the average of all data collected in one second + Double a = AVG(listTemp); + avgTemp.add(String.valueOf(Math.round(a * 100.0) / 100.0)); + if (avgTemp.size() == avgBvp.size()) { + tableDynamic.addHeader(header); //Create header of the table + try { + tableDynamic.addData(getData()); //Add data to the table + } catch (JSONException e) { + e.printStackTrace(); + } + tableDynamic.backgroundHeader(Color.rgb(62, 151, 169)); //Set the color of the header + tableDynamic.backgroundData(Color.rgb(164, 233, 247), Color.rgb(220, 220, 220)); //Set the color of the data + tableDynamic.lineColor(Color.BLACK); //Color of the table borders + } + } + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + + } + }); + } + } + } + } + } + } + } + //Get the time of the String for initialize the variables + private void getDate(){ + String d=""; + for(int i = 0, n = session.length() ; i < n ; i++) { + char c = session.charAt(i); + d=d.concat(String.valueOf(c)); + switch (d){ + case "Session: ": + d=""; + i++; + s=String.valueOf(session.charAt(i)); + i++; + break; + case "Init: ": + i++; + d=""; + int dot=0; + for(int j = i; j listAvg){ + double sum=0; + for(int i=0; i getData() throws JSONException { + String email =superUser.getEmail(); + JSONObject jsonObject = new JSONObject(); + JSONArray jsonArrayAccx = new JSONArray(); + JSONArray jsonArrayAccy = new JSONArray(); + JSONArray jsonArrayAccz = new JSONArray(); + JSONArray jsonArrayBvp = new JSONArray(); + JSONArray jsonArrayGsr = new JSONArray(); + JSONArray jsonArrayTemp = new JSONArray(); + for(int i=0;i() { + @Override + public void onResponse(JSONObject response){ + String p="The mood is "; + JSONArray jsonArrayIndex = new JSONArray(); + JSONArray jsonArrayData = new JSONArray(); + ArrayList percent = new ArrayList(); + ArrayList index = new ArrayList(); + + try{ + jsonArrayIndex = response.getJSONArray("index"); + jsonArrayData = response.getJSONArray("data"); + for(int i =0;idata; + private TableRow tableRow; + private TextView textCell; + private int indexC; + private int indexR; + private boolean multicolor = false; + int firstColor, secondColor; + + public TableDynamic(TableLayout tableLayout, Context context) { + this.tableLayout=tableLayout; + this.context=context; + } + + public void addHeader(String[] header) { + this.header=header; + createHeader(); + } + + public void addData(ArrayListdata){ + this.data=data; + createDataTable(); + } + + private void newRow(){ + tableRow = new TableRow(context); + } + + private void newCell(){ + textCell = new TextView(context); + textCell.setGravity(Gravity.CENTER); + textCell.setTextSize(25); + } + + private void createHeader(){ + indexC=0; + newRow(); + while(indexC listUsers,listSessions; + private AdapterUsers adapterUsers; + private String user; + private int layout; + + @Override + protected void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_users); + recyclerView = (RecyclerView) findViewById(R.id.recyclerView); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + buttonAddUser = findViewById(R.id.buttonUser); + buttonAddUser.setOnClickListener(this); + editTextUser = findViewById(R.id.editTextUser); + Bundle extra = getIntent().getExtras(); + superUser = (SuperUser) extra.getSerializable("superUser"); + layout =(int) extra.getSerializable("layout"); + user = (String)extra.getSerializable("user"); + databaseReference = FirebaseDatabase.getInstance("https://empaticae4-3e023-default-rtdb.europe-west1.firebasedatabase.app").getReference(); + if(layout==1){ + getUsers(); + }else{ + getSession(); + buttonAddUser.setText("Search"); + editTextUser.setHint("Date: Format dd/mm/yyyy"); + } + + } + + //Get the list of different users from the data base, store it in an arraylist 'listUsers' and show it with the recycler view + private void getUsers(){ + String email = superUser.getEmail(); + databaseReference.child("users").child(email).addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot snapshot) { + listUsers = new ArrayList<>(); + if (snapshot.exists()){ + for (DataSnapshot ds : snapshot.getChildren()){ + String name = ds.getKey().toString(); + listUsers.add(name); + } + + adapterUsers = new AdapterUsers(listUsers, UsersActivity.this); + recyclerView.setAdapter(adapterUsers); + adapterUsers.setOnItemClickListener(new AdapterUsers.OnItemClickListener() { + @Override + //When click on in one user, send this user to the Profile activity + public void onItemClick(int position) { + String nameUser=listUsers.get(position); + Intent main = new Intent(UsersActivity.this,ProfileActivity.class); + Bundle bundleMain = new Bundle(); + bundleMain.putSerializable("user", nameUser); + bundleMain.putSerializable("superUser",superUser); + main.putExtras(bundleMain); + startActivity(main); + //finish(); + } + }); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + + } + }); + } + + //Get the list of saved sessions from the data base, store it in an arraylist 'listSessions' and show it with the recycler view + private void getSession(){ + String email = superUser.getEmail(); + databaseReference.child("users").child(email).child(user).addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot snapshot) { + listSessions = new ArrayList<>(); + if (snapshot.exists()) { + for (DataSnapshot ds : snapshot.getChildren()) { + Click time = ds.getValue(Click.class); + String n = ds.getKey().toString(); + String i = time.getDateInit(); + String e = time.getDateEnd(); + String c ="Session: "+n+" Init: "+i+" End: "+e; + listSessions.add(c); + + } + + adapterUsers = new AdapterUsers(listSessions, UsersActivity.this); + recyclerView.setAdapter(adapterUsers); + adapterUsers.setOnItemClickListener(new AdapterUsers.OnItemClickListener() { + @Override + //When click on in one session, send this session to the Record activity + public void onItemClick(int position) { + String session=listSessions.get(position); + Intent main = new Intent(UsersActivity.this, SavedSessionsActivity.class); + Bundle bundleMain = new Bundle(); + bundleMain.putSerializable("user", user); + bundleMain.putSerializable("session", session); + bundleMain.putSerializable("superUser",superUser); + main.putExtras(bundleMain); + startActivity(main); + //finish(); + } + }); + + } + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + + } + }); + + } + + //Different functions of the button, save a new user or search one session + @Override + public void onClick(View view){ + switch (view.getId()){ + case R.id.buttonUser: + //Save a new user + if (layout==1) { + String email = superUser.getEmail(); + String newUser = editTextUser.getText().toString(); + Click click = new Click(); + click.setDateEnd("0"); + click.setDateInit("0"); + databaseReference.child("users").child(email).child(newUser).child("0").setValue(click); + //Search one session + }else{ + List searchSession= new ArrayList<>(); + String date = editTextUser.getText().toString(); + String[] dat = date.split("/"); + String day = dat[0]; + String month = dat[1]; + String year = dat[2]; + for(int i=0;i + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/card.xml b/app/src/main/res/drawable/card.xml new file mode 100644 index 0000000..ff521d3 --- /dev/null +++ b/app/src/main/res/drawable/card.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/first_background.xml b/app/src/main/res/drawable/first_background.xml new file mode 100644 index 0000000..d5d868a --- /dev/null +++ b/app/src/main/res/drawable/first_background.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..1d3e734 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,59 @@ + + + + + + + + +