Change the project into Testing app

This commit is contained in:
mohamedkaif356
2023-06-28 12:41:18 +05:30
parent 69df710006
commit 0c063583ca
118 changed files with 1729 additions and 2760 deletions

View File

@@ -2,15 +2,19 @@ plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.google.firebase.appdistribution'
id 'dagger.hilt.android.plugin'
id 'com.google.gms.google-services'
id 'androidx.navigation.safeargs.kotlin'
id 'kotlin-kapt'
}
//apply plugin: 'kotlin-android'
android {
compileSdk 33
namespace 'in.sminnovations.hpostesting'
defaultConfig {
applicationId "com.example.hpos"
applicationId "in.sminnovations.hpostesting"
minSdk 21
targetSdk 33
versionCode 2
@@ -26,11 +30,11 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = '17'
}
dataBinding {
enabled = true
@@ -48,19 +52,21 @@ android {
dependencies {
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1'
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.2'
implementation 'androidx.navigation:navigation-ui-ktx:2.5.2'
// Firebase
implementation 'com.google.firebase:firebase-firestore-ktx:24.4.1'
implementation 'com.google.firebase:firebase-storage-ktx:20.1.0'
//firebase
implementation platform('com.google.firebase:firebase-bom:32.1.0')
implementation 'com.google.firebase:firebase-firestore-ktx'
implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.firebase:firebase-storage-ktx'
implementation 'com.firebaseui:firebase-ui-firestore:8.0.2'
implementation 'com.google.android.gms:play-services-auth:20.5.0'
implementation 'com.google.android.gms:play-services-location:21.0.1'
// implementation 'androidx.core:core-ktx:+'
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
// Testing
testImplementation 'junit:junit:4.13.2'
@@ -68,11 +74,11 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1"
implementation 'com.opencsv:opencsv:4.6'
implementation 'com.github.mik3y:usb-serial-for-android:3.4.6'
implementation "androidx.fragment:fragment-ktx:1.5.5"
implementation "androidx.fragment:fragment-ktx:1.6.0"
// CSV read, write
implementation 'com.opencsv:opencsv:4.6'
@@ -83,7 +89,26 @@ dependencies {
// Google ML Kit usign play services
implementation 'com.google.android.gms:play-services-code-scanner:16.0.0'
}
//repositories {
// mavenCentral()
//}
//Room
implementation "androidx.room:room-ktx:2.6.0-alpha01"
implementation "androidx.room:room-runtime:2.6.0-alpha01"
kapt ("androidx.room:room-compiler:2.6.0-alpha01")
//image
implementation 'com.github.bumptech.glide:glide:4.13.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
// Navigation Component
implementation "androidx.navigation:navigation-fragment-ktx:2.7.0-beta01"
implementation "androidx.navigation:navigation-ui-ktx:2.7.0-beta01"
//Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.46"
kapt "com.google.dagger:hilt-android-compiler:2.46"
kapt "androidx.hilt:hilt-compiler:1.0.0"
// Retrofit + GSON
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
}

View File

@@ -1,4 +1,4 @@
package com.example.hpos
package com.example.hpostesting
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry

View File

@@ -1,7 +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="com.example.hpos">
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -16,7 +15,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".MyApplication"
android:name="com.example.hpostesting.HPOSTestingApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
@@ -24,26 +23,27 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/hpos_icon_round"
android:supportsRtl="true"
android:theme="@style/Theme.HPOS"
android:theme="@style/Theme.HPOSTesting"
tools:targetApi="31">
<activity
android:name=".presentation.KitScanActivity"
android:name="com.example.hpostesting.presentation.KitScanActivity"
android:noHistory="true"
android:exported="false" />
android:exported="false"
android:theme="@style/Theme.HPOS.NoActionBar"/>
<activity
android:name=".presentation.dashboard.DashboardActivity"
android:name="com.example.hpostesting.presentation.dashboard.DashboardActivity"
android:exported="false"
android:label="@string/title_activity_dashboard"
android:screenOrientation="portrait"
android:theme="@style/Theme.HPOS.NoActionBar" />
<service
android:name=".presentation.testRight.UsbService"
android:name="com.example.hpostesting.presentation.testRight.UsbService"
android:enabled="true"
android:exported="false" />
<activity
android:name=".presentation.SplashActivity"
android:name="com.example.hpostesting.presentation.SplashActivity"
android:exported="true"
android:noHistory="true"
android:theme="@style/AppTheme.NoActionBar">
@@ -54,12 +54,13 @@
</intent-filter>
</activity>
<activity
android:name=".presentation.testRight.TestRightActivity"
android:name="com.example.hpostesting.presentation.testRight.TestRightActivity"
android:exported="false"
android:parentActivityName=".presentation.MainActivity"
android:parentActivityName="com.example.hpostesting.presentation.MainActivity"
android:screenOrientation="portrait"
android:noHistory="true"
android:windowSoftInputMode="adjustPan">
android:windowSoftInputMode="adjustPan"
android:theme="@style/Theme.HPOS.NoActionBar">
<!-- <intent-filter> -->
<!-- <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> -->
@@ -71,9 +72,10 @@
<!-- android:resource="@xml/device_filter" /> -->
</activity> <!-- android:theme="@style/Theme.HPOS.ActionBar" -->
<activity
android:name=".presentation.MainActivity"
android:name="com.example.hpostesting.presentation.MainActivity"
android:exported="true"
android:screenOrientation="portrait">
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
@@ -88,9 +90,6 @@
android:stateNotNeeded="true"
tools:replace="android:screenOrientation" />
<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
</application>
</manifest>

View File

@@ -1,19 +0,0 @@
package com.example.hpos
import android.app.Application
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
class MyApplication : Application() {
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
// private val sampleDetails = PatientDetails("Change it later");
// fun getSampleDetails() : PatientDetails = sampleDetails
// fun setSampleDetails(sample: SampleDetails) {sampleDetails = sample}
}
// 1. firestore Database cache limit - full

View File

@@ -1,174 +0,0 @@
package com.example.hpos.data.model;
import android.graphics.Bitmap;
public class AadharCard {
private String uuid;
private String name;
private String dateOfBirth;
private String gender;
private String careOf;
private String district;
private String landmark;
private String house;
private String location;
private String pinCode;
private String postOffice;
private String state;
private String street;
private String subDistrict;
private String vtc;
private Bitmap image;
private String email;
private String mobile;
private String signature;
public void setUuid(String aUuid){ name = aUuid; }
public void setName(String aName){ name = aName; }
public void setDateOfBirth(String aDateOfBirth){
dateOfBirth = aDateOfBirth;
}
public void setGender(String aGender){
gender = aGender;
}
public void setCareOf(String aCareOf){
careOf = aCareOf;
}
public void setDistrict(String aDistrict){
district = aDistrict;
}
public void setLandmark(String aLandmark){
landmark = aLandmark;
}
public void setHouse(String aHouse){
house = aHouse;
}
public void setLocation(String aLocation){ location = aLocation; }
public void setPinCode(String aPinCode){
pinCode = aPinCode;
}
public void setPostOffice(String aPostOffice){
postOffice = aPostOffice;
}
public void setState(String aState){
state = aState;
}
public void setStreet(String aStreet){
street = aStreet;
}
public void setSubDistrict(String aSubDistrict){
subDistrict = aSubDistrict;
}
public void setVtc(String aVtc){
vtc = aVtc;
}
public void setImage(Bitmap aImage){
image = aImage;
}
public void setEmail(String aEmail){
email = aEmail;
}
public void setMobile(String aMobile){
mobile = aMobile;
}
public void setSignature(String aSignature){
signature = aSignature;
}
public AadharCard(){
uuid = "";
name = "";
dateOfBirth = "";
gender = "";
careOf = "";
district = "";
landmark = "";
house = "";
location = "";
pinCode = "";
postOffice = "";
state = "";
street = "";
subDistrict = "";
vtc = "";
email = "";
mobile = "";
signature = "";
}
public String getName() {
return name;
}
public String getUuid() {
return uuid;
}
public String getDateOfBirth() {
return dateOfBirth;
}
public String getGender() {
return gender;
}
public String getCareOf() {
return careOf;
}
public String getDistrict() {
return district;
}
public String getLandmark() {
return landmark;
}
public String getHouse() {
return house;
}
public String getLocation() {
return location;
}
public String getPinCode() {
return pinCode;
}
public String getPostOffice() {
return postOffice;
}
public String getState() {
return state;
}
public String getStreet() {
return street;
}
public String getSubDistrict() {
return subDistrict;
}
public String getVtc() {
return vtc;
}
public Bitmap getImage() {
return image;
}
public String getEmail() {
return email;
}
public String getMobile() {
return mobile;
}
public String getSignature() {
return signature;
}
}

View File

@@ -1,147 +0,0 @@
package com.example.hpos.data.repository
import android.net.Uri
import com.example.hpos.data.model.Response
import com.example.hpos.data.model.PendingUploads
import com.example.hpos.data.model.patient.PatientDetails
import com.example.hpos.data.model.test.TestDetails
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.ktx.storage
import kotlinx.coroutines.tasks.await
import java.io.File
class DatabaseRepository : Repository {
private val db: FirebaseFirestore = Firebase.firestore
private val storage = Firebase.storage
suspend fun addPatientToDatabase(data: PatientDetails) : Response<String> {
return try {
db.collection("patientData")
.document(data.id)
.set(data)
.await()
Response.Success(data.id)
} catch (e: Exception) {
Response.Error(e)
}
}
suspend fun getAllPatientsFromDatabase(): Response<List<PatientDetails>> {
return try {
val querySnapshot = db.collection("patientData").get().await()
val patientList = mutableListOf<PatientDetails>()
for (doc in querySnapshot.documents){
val patient = doc.toObject(PatientDetails::class.java)
patient?.let {
patientList.add(it)
}
}
Response.Success(patientList)
} catch (e: Exception) {
Response.Error(e)
}
}
suspend fun addTestToDatabase(data: TestDetails) : Response<String> {
return try {
db.collection("testData")
.document(data.testID)
.set(data)
.await()
Response.Success(data.testID)
} catch (e: Exception) {
Response.Error(e)
}
}
suspend fun getAllTestsFromDatabase(): List<TestDetails> {
val testList = mutableListOf<TestDetails>()
return try {
val querySnapshot = db.collection("testData").orderBy("registeredTime", Query.Direction.DESCENDING).get().await()
for (doc in querySnapshot.documents){
val patient = doc.toObject(TestDetails::class.java)
patient?.let {
testList.add(it)
}
}
// Response.Success(testList)
testList
} catch (e: Exception) {
e.printStackTrace()
testList
// Response.Error(e)
}
}
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean> {
try {
val file = Uri.fromFile(File(filePath))
val riversRef = storage.reference.child("$patientID/${file.lastPathSegment}")
riversRef.putFile(file).await()
return Response.Success(true)
} catch (e: Exception) {
e.printStackTrace()
return Response.Error(e)
}
}
suspend fun addToPendingQueue(pendingUploads: PendingUploads): Response<Boolean> {
return try {
db.collection("pendingUploads")
.document(pendingUploads.pendingId)
.set(pendingUploads)
.await()
Response.Success(true)
} catch (e: Exception) {
e.printStackTrace()
Response.Error(e)
}
}
suspend fun getAllFromPendingQueue(): List<PendingUploads> {
val pendingList = mutableListOf<PendingUploads>()
return try {
val querySnapshot = db.collection("pendingUploads").orderBy("timeAdded").get().await()
for (doc in querySnapshot.documents){
val pendingFile = doc.toObject(PendingUploads::class.java)
pendingFile?.let {
pendingList.add(it)
}
}
pendingList
} catch (e: Exception) {
e.printStackTrace()
pendingList
}
}
suspend fun removeFromPendingQueue(fileName: String): Response<Boolean> {
return try {
db.collection("pendingUploads")
.document(fileName)
.delete()
.await()
Response.Success(true)
} catch (e: Exception) {
e.printStackTrace()
Response.Error(e)
}
}
}

View File

@@ -1,20 +0,0 @@
package com.example.hpos.domain.AadhaarScanner;
/**
* QrCodeException wraps all the exceptions which occurs while scanning and decoding secure Aadharcard
* Qr Code
* @author Raj Deol
*/
public class QrCodeException extends Exception {
public QrCodeException(String message) {
super(message);
}
public QrCodeException(String message, Throwable cause) {
super(message, cause);
}
public QrCodeException(Throwable cause) {
super(cause);
}
}

View File

@@ -1,304 +0,0 @@
package com.example.hpos.domain.AadhaarScanner;
import android.content.Context;
import android.util.Log;
import com.example.hpos.data.model.AadharCard;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.GZIPInputStream;
/**
* Class to decode scanned QRcode
*/
public class SecureQrCode {
protected Context mContext;
protected static final byte SEPARATOR_BYTE = (byte)255;
protected static final int REFERENCE_ID_INDEX = 1,
NAME_INDEX = 2,
DATE_OF_BIRTH_INDEX = 3,
GENDER_INDEX = 4,
CARE_OF_INDEX = 5,
DISTRICT_INDEX = 6,
LANDMARK_INDEX = 7,
HOUSE_INDEX = 8,
LOCATION_INDEX = 9,
PIN_CODE_INDEX = 10,
POST_OFFICE_INDEX = 11,
STATE_INDEX = 12,
STREET_INDEX = 13,
SUB_DISTRICT_INDEX = 14,
VTC_INDEX = 15;
protected int emailMobilePresent, imageStartIndex, imageEndIndex;
protected ArrayList<String> decodedData;
protected String signature,email,mobile;
protected AadharCard scannedAadharCard;
public SecureQrCode(Context activity, String scanData) throws QrCodeException{
mContext = activity;
scannedAadharCard = new AadharCard();
// 1. Convert Base10 to BigInt
final BigInteger bigIntScanData = new BigInteger(scanData,10);
// 2. Convert BigInt to Byte Array
final byte byteScanData[] = bigIntScanData.toByteArray();
// 3. Decompress Byte Array
final byte[] decompByteScanData = decompressData(byteScanData);
// 4. Split the byte array using delimiter
List<byte[]> parts = separateData(decompByteScanData);
// Throw error if there are no parts
if(parts.size() == 0){
throw new QrCodeException("Invalid QR Code Data, no parts found after splitting by delimiter");
}
// 5. decode extracted data to string
decodeData(parts);
// 6. Extract Signature
decodeSignature(decompByteScanData);
// 7. Email and Mobile number
decodeMobileEmail(decompByteScanData);
// 8. Extract Image
decodeImage(decompByteScanData);
Log.d("Rajdeol","Data Decoded");
}
/**
* Decompress the byte array, compression used is GZIP
* @param byteScanData compressed byte array
* @return uncompressed byte array
* @throws QrCodeException
*/
protected byte[] decompressData(byte[] byteScanData) throws QrCodeException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(byteScanData.length);
ByteArrayInputStream bin = new ByteArrayInputStream(byteScanData);
GZIPInputStream gis = null;
try {
gis = new GZIPInputStream(bin);
} catch (IOException e) {
Log.e("Exception", "Decompressing QRcode, Opening byte stream failed: " + e.toString());
throw new QrCodeException("Error in opening Gzip byte stream while decompressing QRcode",e);
}
int size = 0;
byte[] buf = new byte[1024];
while (size >= 0) {
try {
size = gis.read(buf,0,buf.length);
if(size > 0){
bos.write(buf,0,size);
}
} catch (IOException e) {
Log.e("Exception", "Decompressing QRcode, writing byte stream failed: " + e.toString());
throw new QrCodeException("Error in writing byte stream while decompressing QRcode",e);
}
}
try {
gis.close();
bin.close();
} catch (IOException e) {
Log.e("Exception", "Decompressing QRcode, closing byte stream failed: " + e.toString());
throw new QrCodeException("Error in closing byte stream while decompressing QRcode",e);
}
return bos.toByteArray();
}
/**
* Function to split byte array with delimiter
* @param source source byte array
* @return list of separated byte arrays
*/
protected List<byte[]> separateData(byte[] source) {
List<byte[]> separatedParts = new LinkedList<>();
int begin = 0;
for (int i = 0; i < source.length; i++) {
if(source[i] == SEPARATOR_BYTE){
// skip if first or last byte is separator
if(i != 0 && i != (source.length -1)){
separatedParts.add(Arrays.copyOfRange(source, begin, i));
}
begin = i + 1;
// check if we have got all the parts of text data
if(separatedParts.size() == (VTC_INDEX + 1)){
// this is required to extract image data
imageStartIndex = begin;
break;
}
}
}
return separatedParts;
}
/**
* function to decode string values
* @param encodedData
* @throws QrCodeException
*/
protected void decodeData(List<byte[]> encodedData) throws QrCodeException{
Iterator<byte[]> i = encodedData.iterator();
decodedData = new ArrayList<String>();
while(i.hasNext()){
try {
decodedData.add(new String(i.next(), "ISO-8859-1"));
} catch (UnsupportedEncodingException e) {
Log.e("Exception", "Decoding QRcode, ISO-8859-1 not supported: " + e.toString());
throw new QrCodeException("Decoding QRcode, ISO-8859-1 not supported",e);
}
}
// set the value of email/mobile present flag
emailMobilePresent = Integer.parseInt(decodedData.get(0));
// populate decoded data
scannedAadharCard.setName(decodedData.get(2));
scannedAadharCard.setDateOfBirth(decodedData.get(3));
scannedAadharCard.setGender(decodedData.get(4));
scannedAadharCard.setCareOf(decodedData.get(5));
scannedAadharCard.setDistrict(decodedData.get(6));
scannedAadharCard.setLandmark(decodedData.get(7));
scannedAadharCard.setHouse(decodedData.get(8));
scannedAadharCard.setLocation(decodedData.get(9));
scannedAadharCard.setPinCode(decodedData.get(10));
scannedAadharCard.setPostOffice(decodedData.get(11));
scannedAadharCard.setState(decodedData.get(12));
scannedAadharCard.setStreet(decodedData.get(13));
scannedAadharCard.setSubDistrict(decodedData.get(14));
scannedAadharCard.setVtc(decodedData.get(15));
}
/**
* ref : https://uidai.gov.in/2-uncategorised/11320-aadhaar-paperless-offline-e-kyc-3.html
* Hashing logic for Email ID :
* Sha256(Sha256(Email+SharePhrase))*number of times last digit of Aadhaar number
* (Ref ID field contains last 4 digits).
*
* Example :
* Email: abc@gm.com
* Aadhaar Number:XXXX XXXX 3632
* Passcode : Lock@487
* Hash : Sha256(Sha256(abc@gm.comLock@487))*2
* In case of Aadhaar number ends with Zero we will hashed one time.
* **********************************************************************
* **********************************************************************
* Hashing logic for Mobile Number :
* Sha256(Sha256(Mobile+SharePhrase))*number of times last digit of Aadhaar number
* (Ref ID field contains last 4 digits).
*
* Example :
* Mobile: 1234567890
* Aadhaar Number:XXXX XXXX 3632
* Passcode : Lock@487
* Hash: Sha256(Sha256(1234567890Lock@487))*2
* In case of Aadhaar number ends with Zero we will hashed one time.
* @param decompressedData
* @throws QrCodeException
*/
protected void decodeMobileEmail(byte[] decompressedData) throws QrCodeException{
int mobileStartIndex = 0,mobileEndIndex = 0,emailStartIndex = 0,emailEndIndex = 0;
switch (emailMobilePresent){
case 3:
// both email mobile present
mobileStartIndex = decompressedData.length - 289; // length -1 -256 -32
mobileEndIndex = decompressedData.length - 257; // length -1 -256
emailStartIndex = decompressedData.length - 322;// length -1 -256 -32 -1 -32
emailEndIndex = decompressedData.length - 290;// length -1 -256 -32 -1
mobile = bytesToHex (Arrays.copyOfRange(decompressedData,mobileStartIndex,mobileEndIndex+1));
email = bytesToHex (Arrays.copyOfRange(decompressedData,emailStartIndex,emailEndIndex+1));
// set image end index, it will be used to extract image data
imageEndIndex = decompressedData.length - 323;
break;
case 2:
// only mobile
email = "";
mobileStartIndex = decompressedData.length - 289; // length -1 -256 -32
mobileEndIndex = decompressedData.length - 257; // length -1 -256
mobile = bytesToHex (Arrays.copyOfRange(decompressedData,mobileStartIndex,mobileEndIndex+1));
// set image end index, it will be used to extract image data
imageEndIndex = decompressedData.length - 290;
break;
case 1:
// only email
mobile = "";
emailStartIndex = decompressedData.length - 289; // length -1 -256 -32
emailEndIndex = decompressedData.length - 257; // length -1 -256
email = bytesToHex (Arrays.copyOfRange(decompressedData,emailStartIndex,emailEndIndex+1));
// set image end index, it will be used to extract image data
imageEndIndex = decompressedData.length - 290;
break;
default:
// no mobile or email
mobile = "";
email = "";
// set image end index, it will be used to extract image data
imageEndIndex = decompressedData.length - 257;
}
}
protected void decodeImage(byte[] decompressedData) throws QrCodeException{
// image start and end indexes are calculated in functions : separateData and decodeMobileEmail
byte[] imageBytes = Arrays.copyOfRange(decompressedData,imageStartIndex,imageEndIndex+1);
// Bitmap bmp = new JP2Decoder(imageBytes).decode();
// scannedAadharCard.setImage(bmp);
}
protected void decodeSignature(byte[] decompressedData) throws QrCodeException{
// extract 256 bytes from the end of the byte array
int startIndex = decompressedData.length - 257,
noOfBytes = 256;
try {
signature = new String (decompressedData,startIndex,noOfBytes,"ISO-8859-1");
} catch (UnsupportedEncodingException e) {
Log.e("Exception", "Decoding Signature of QRcode, ISO-8859-1 not supported: " + e.toString());
throw new QrCodeException("Decoding Signature of QRcode, ISO-8859-1 not supported",e);
}
}
public AadharCard getScannedAadharCard(){
return scannedAadharCard;
}
/**
* Convert byte array to hex string
* @param bytes
* @return
*/
public static String bytesToHex(byte[] bytes) {
final char[] hexArray = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}

View File

@@ -1,128 +0,0 @@
package com.example.hpos.presentation
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.hardware.usb.UsbManager
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import androidx.lifecycle.ViewModelProvider
import com.example.hpos.R
import com.example.hpos.data.DataHolder
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.model.test.TestType
import com.example.hpos.databinding.ActivityMainBinding
import com.example.hpos.util.MyViewModelFactory
import com.hoho.android.usbserial.driver.UsbSerialProber
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: MainViewModel
private var myMenu: Menu? = null
private val TAG = "MainActivity"
private var mUsbReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val action = intent.action
if (UsbManager.ACTION_USB_DEVICE_DETACHED == action) {
DataHolder.usbConnected.value = false
// Toast.makeText(context, "Detached", Toast.LENGTH_SHORT).show()
} else if (UsbManager.ACTION_USB_DEVICE_ATTACHED == action) {
DataHolder.usbConnected.value = true
// Toast.makeText(context, "Attached", Toast.LENGTH_SHORT).show()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel = ViewModelProvider(
this,
MyViewModelFactory()
)[MainViewModel::class.java]
setSupportActionBar(binding.myToolbar)
// supportActionBar?.setDisplayHomeAsUpEnabled(true)
setupListeners()
val filter = IntentFilter()
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED)
registerReceiver(mUsbReceiver, filter)
}
private fun checkAndUpdateUsbConnection() {
val availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(getSystemService(Context.USB_SERVICE) as UsbManager)
if (availableDrivers.isNotEmpty() && availableDrivers[0].device.productId == Constants.DEVICE_PRODUCT_ID && availableDrivers[0].device.vendorId == Constants.DEVICE_VENDOR_ID){
Log.d(TAG, "Device matched -> product = ${availableDrivers[0].device.productId}, vendor = ${availableDrivers[0].device.vendorId}")
DataHolder.usbConnected.value = true
} else if (availableDrivers.isNotEmpty()) {
Log.d(TAG, "Device NOT matched -> product = ${availableDrivers[0].device.productId}, vendor = ${availableDrivers[0].device.vendorId}")
Toast.makeText(this, "Device Not Compatible", Toast.LENGTH_SHORT).show()
DataHolder.usbConnected.value = false
} else {
Log.d(TAG, "Device NOT Connected")
DataHolder.usbConnected.value = false
}
}
private fun setupListeners() {
binding.cvItem1.setOnClickListener {
DataHolder.selectedTestType = TestType.SICKLECERT
// val i = Intent(applicationContext, TestRightActivity::class.java)
// startActivity(i)
val i = Intent(applicationContext, KitScanActivity::class.java)
startActivity(i)
}
binding.cvItem2.setOnClickListener {
DataHolder.selectedTestType = TestType.SICKLEFIND
// val i = Intent(applicationContext, TestRightActivity::class.java)
// startActivity(i)
val i = Intent(applicationContext, KitScanActivity::class.java)
startActivity(i)
}
DataHolder.usbConnected.observe(this){
// Log.d(TAG, "usbConnected observer called with value -> $it")
if (it){
myMenu?.get(0)?.icon = ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
} else {
// Log.d(TAG, "into no block -> $it")
myMenu?.get(0)?.icon = ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
}
}
// binding.cvItem3.setOnClickListener {
// val i = Intent(applicationContext, TestRightActivity::class.java)
// startActivity(i)
// }
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
myMenu = menu
// Todo: Uncomment this
checkAndUpdateUsbConnection()
return true
}
}

View File

@@ -1,128 +0,0 @@
package com.example.hpos.presentation
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.hpos.R
import com.example.hpos.data.model.test.Status
import com.example.hpos.data.model.test.TestDetails
import com.example.hpos.presentation.dashboard.ItemClickListener
class RVAdapter : RecyclerView.Adapter<RVAdapter.ViewHolder>() {
// private lateinit var binding: TableItemBinding
private val dataset = ArrayList<TestDetails>()
var itemClickListener: ItemClickListener? = null
companion object {var selectedPosition = -1}
// private var lastChecked: CheckBox? = null
// private var lastCheckedPos = 0
// This keeps track of the currently selected position
// var selectedPosition by Delegates.observable(-1) { property, oldPos, newPos ->
// if (newPos in dataset.indices) {
// notifyItemChanged(oldPos)
// notifyItemChanged(newPos)
// }
// }
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val tvId: TextView
val tvName: TextView
val tvStatus: TextView
val radioButton: RadioButton
val radioGroup: RadioGroup
init {
tvId = view.findViewById(R.id.tv_id)
tvName = view.findViewById(R.id.tv_name)
tvStatus = view.findViewById(R.id.tv_status)
radioButton = view.findViewById(R.id.radioButton)
radioGroup = view.findViewById(R.id.radio_group)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.table_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
Log.d("RVAdapter", "onBindViewHolder called() : pos = ${position}")
val idString = "ID: " + dataset[position].patientID
holder.tvId.text = idString
holder.tvName.text = dataset[position].patientName
holder.tvStatus.text = dataset[position].testStatus.toString()
holder.radioGroup.clearCheck()
if (dataset[position].testStatus == Status.PENDING) {
holder.radioButton.isChecked = (position == selectedPosition)
} else {
holder.radioButton.isEnabled = false
}
holder.radioButton.setOnCheckedChangeListener { compoundButton, b ->
Log.d("RVAdapter", "setOnCheckedChangeListener called() : pos = ${position}")
// check condition
if (b) {
Log.d("RVAdapter", "setOnCheckedChangeListener called() -> b true : pos = ${position}")
// When checked update selected position
selectedPosition = holder.adapterPosition
itemClickListener!!.onClick(position)
}
}
}
override fun getItemCount(): Int {
return dataset.size
}
fun updateDataSet(newDataSet: ArrayList<TestDetails>) {
dataset.clear()
dataset.addAll(newDataSet)
notifyDataSetChanged()
}
// inner class ViewHolder(itemView: TableItemBinding) : RecyclerView.ViewHolder(itemView.root) {
// fun bind(item : TestDetails){
// binding.apply {
// tvId.text = item.patientID
// tvName.text = item.patientName
// tvStatus.text = item.testStatus.toString()
// }
// }
// }
//
// override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
// val inflater =LayoutInflater.from(parent.context)
// binding = TableItemBinding.inflate(inflater,parent,false)
// return ViewHolder(binding)
// }
//
// override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// holder.bind(dataset[position])
// }
//
// override fun getItemCount(): Int {
// return dataset.size
// }
//
// fun updateDataSet(newDataSet: ArrayList<TestDetails>) {
// dataset.clear()
// dataset.addAll(newDataSet)
// notifyDataSetChanged()
// }
}

View File

@@ -1,255 +0,0 @@
package com.example.hpos.presentation
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.example.hpos.MyApplication
import com.example.hpos.data.DataHolder
import com.example.hpos.data.FileUploader
import com.example.hpos.databinding.ActivitySplashBinding
import com.example.hpos.presentation.dashboard.DashboardActivity
import com.example.hpos.util.MyUtils
import com.google.firebase.firestore.FirebaseFirestoreSettings
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
/**
* Splash Activity
* Used for preprocessing of data, permissions
*/
class SplashActivity : AppCompatActivity() {
private val MY_CAMERA_REQUEST_CODE: Int = 100
private lateinit var binding: ActivitySplashBinding
var permissionStorage = false
var permissionLocation = false
var permissionLocation2 = false
var permissionCamera = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySplashBinding.inflate(layoutInflater)
setContentView(binding.root)
setupFirestoreCache()
checkForStoragePermissions()
checkForLocationPermission()
checkForLocationPermission2()
// Keep this in last permission check, as checking all given or not after this
checkForCameraPermission()
// Log.d("surya_permission", "passed first")
checkAllPermissionsGiven()
setupStaticConstants()
startWorker()
// GlobalScope.launch(Dispatchers.IO) {
// FileUploader().uploadFiles(listOf())
// }
}
private fun startWorker() {
if (MyUtils.isInternetConnected()) {
(applicationContext as MyApplication).applicationScope.launch(Dispatchers.IO) {
FileUploader().start()
}
}
}
private fun setupStaticConstants() {
DataHolder.mobileUniqueId = Settings.Secure.getString(applicationContext.contentResolver, Settings.Secure.ANDROID_ID)
}
private fun setupFirestoreCache() {
val settings = FirebaseFirestoreSettings.Builder()
.setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED)
.build()
Firebase.firestore.firestoreSettings = settings
}
private fun checkAllPermissionsGiven() {
// Log.d("surya_permission", "inside checkAllPermissionsGiven")
if (permissionStorage && permissionCamera && permissionLocation && permissionLocation2)
moveToLandingPage()
}
private fun checkForStoragePermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
getPermissionsAboveAndroidR()
} else {
getPermissionsBelowAndroidR()
}
}
@RequiresApi(Build.VERSION_CODES.R)
private fun getPermissionsAboveAndroidR() {
// Checking if permission is already granted or not.
if (!Environment.isExternalStorageManager()) {
val storagePermissionResultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (Environment.isExternalStorageManager()) {
DataHolder.isStoragePermissionGranted = true
// moveToLandingPage()
permissionStorage = true
} else {
DataHolder.isStoragePermissionGranted = false
Toast.makeText(
this,
"You must grant permission to storage to use the app",
Toast.LENGTH_SHORT
).show()
}
}
val intent = Intent()
intent.action = Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
intent.data = Uri.fromParts("package", this.packageName, null)
storagePermissionResultLauncher.launch(intent)
} else {
DataHolder.isStoragePermissionGranted = true
// moveToLandingPage()
permissionStorage = true
}
}
private fun getPermissionsBelowAndroidR() {
val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
DataHolder.isStoragePermissionGranted = true
// moveToLandingPage()
permissionStorage = true
} else {
DataHolder.isStoragePermissionGranted = false
Toast.makeText(
this,
"You must grant permission to storage to use the app",
Toast.LENGTH_SHORT
).show()
}
}
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
} else {
DataHolder.isStoragePermissionGranted = true
// moveToLandingPage()
permissionStorage = true
}
}
private fun checkForCameraPermission() {
if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_DENIED
) {
val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
permissionCamera = true
checkAllPermissionsGiven()
} else {
Toast.makeText(
this,
"You must grant permission to Camera to use the app",
Toast.LENGTH_SHORT
).show()
}
}
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
} else {
permissionCamera = true
checkAllPermissionsGiven()
}
}
private fun checkForLocationPermission() {
if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_DENIED
) {
val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
permissionLocation = true
checkAllPermissionsGiven()
} else {
Toast.makeText(
this,
"You must grant permission to Location to use the app",
Toast.LENGTH_SHORT
).show()
}
}
requestPermissionLauncher.launch(Manifest.permission.ACCESS_COARSE_LOCATION)
} else {
permissionLocation = true
checkAllPermissionsGiven()
}
}
private fun checkForLocationPermission2() {
if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_DENIED
) {
val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
permissionLocation2 = true
checkAllPermissionsGiven()
} else {
Toast.makeText(
this,
"You must grant permission to Location to use the app",
Toast.LENGTH_SHORT
).show()
}
}
requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
} else {
permissionLocation2 = true
checkAllPermissionsGiven()
}
}
private fun moveToLandingPage() {
createAppFolder()
// val i = Intent(applicationContext, MainActivity::class.java)
val i = Intent(applicationContext, DashboardActivity::class.java)
startActivity(i)
}
private fun createAppFolder() {
val folderPath = MyUtils.createAppFolder(applicationContext)
if (folderPath != null) {
DataHolder.isAppFolderCreated = true
DataHolder.appFolderPath = folderPath
}
}
}

View File

@@ -1,124 +0,0 @@
package com.example.hpos.presentation.dashboard
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpos.BuildConfig
import com.example.hpos.data.DataHolder
import com.example.hpos.data.repository.DatabaseRepository
import com.example.hpos.data.model.Response
import com.example.hpos.data.model.AadharCard
import com.example.hpos.data.model.Location
import com.example.hpos.data.model.patient.PatientDetails
import com.example.hpos.data.model.test.Status
import com.example.hpos.data.model.test.TestDetails
import com.example.hpos.util.MyUtils
import com.example.hpos.util.MyUtils.fetchYOBFromDOB
import com.example.hpos.util.MyUtils.mapToGender
import kotlinx.coroutines.launch
import java.util.Calendar
//class DashboardViewModel(val repository: DatabaseRepository) : ViewModel() {
class DashboardViewModel() : ViewModel() {
private val TAG = "DashboardViewModel"
lateinit var aadharCard: AadharCard
lateinit var patientDetails: PatientDetails
lateinit var testDetails: TestDetails
var deviceLocation = Location(null, null)
val repository = DatabaseRepository()
val dataUploadStatus = MutableLiveData<Response<String>>()
// val allTestDetails = MutableLiveData<Response<List<TestDetails>>>()
val allTestDetails = MutableLiveData<List<TestDetails>>()
var temp = 1
fun initializePatientDetails(patient: PatientDetails) {
patientDetails = patient
}
fun mapAadhaarDataToPatient() {
if (patientDetails.name.isNullOrEmpty())
patientDetails.name = aadharCard.name
if (patientDetails.yob == null)
patientDetails.yob = aadharCard.dateOfBirth.fetchYOBFromDOB()
if (patientDetails.gender == null)
patientDetails.gender = aadharCard.gender.mapToGender()
if (patientDetails.mobile.isNullOrEmpty())
patientDetails.mobile = aadharCard.mobile
if (patientDetails.careOf.isNullOrEmpty())
patientDetails.careOf = aadharCard.careOf
if (patientDetails.address == null) {
patientDetails.address = PatientDetails.Address()
patientDetails.address?.house = aadharCard.house
patientDetails.address?.city = aadharCard.location
patientDetails.address?.postOffice = aadharCard.postOffice
patientDetails.address?.district = aadharCard.district
patientDetails.address?.state = aadharCard.state
patientDetails.address?.pinCode = aadharCard.pinCode.toInt()
}
}
fun createTest() {
val mTestId = MyUtils.generateTestIdForPatient(patientDetails.id)
testDetails = TestDetails(
testID = mTestId,
testStatus = Status.PENDING,
patientID = patientDetails.id,
patientName = patientDetails.name!!,
patientAge = patientDetails.yob,
resultRatio = null,
result = null,
reportPath = null,
csvPath = null,
logPath = null,
deviceId = null,
mobileId = DataHolder.mobileUniqueId!!,
kitSerial = null,
location = deviceLocation,
appVersion = BuildConfig.VERSION_CODE.toString(),
registeredTime = Calendar.getInstance().time,
uploadTime = Calendar.getInstance().time
)
pushTestDetailsToDb()
}
// ------- Cloud Actions ------------------------------------------
fun pushPatientDetailsToDb() {
patientDetails.uploadDate = Calendar.getInstance().time
viewModelScope.launch {
val response = repository.addPatientToDatabase(patientDetails)
dataUploadStatus.value = response
}
}
private fun pushTestDetailsToDb() {
testDetails.uploadTime = Calendar.getInstance().time
viewModelScope.launch {
val response = repository.addTestToDatabase(testDetails)
dataUploadStatus.value = response
}
}
fun fetchAllTestData() {
viewModelScope.launch {
val response = repository.getAllTestsFromDatabase()
allTestDetails.postValue(response)
}
}
}

View File

@@ -1,105 +0,0 @@
package com.example.hpos.presentation.dashboard
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE
import com.example.hpos.R
import com.example.hpos.data.DataHolder
import com.example.hpos.data.model.patient.PatientDetails
import com.example.hpos.databinding.FragmentHomeBinding
import com.example.hpos.presentation.RVAdapter
import com.example.hpos.presentation.RecyclerViewAdapter
class HomeFragment : Fragment() {
val TAG = "HomeFragment"
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private val viewModel: DashboardViewModel by activityViewModels()
// private val viewModel: DashboardViewModel by activityViewModels{ MyViewModelFactory() }
// private lateinit var rvAdapter: RVAdapter
private lateinit var rvAdapter: RecyclerViewAdapter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
try {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
DataHolder.selectedTest = null
rvAdapter = RecyclerViewAdapter()
val itemClickListener = object : ItemClickListener {
override fun onClick(pos: Int) {
Log.d(TAG, "onclick called in ItemClickListener")
DataHolder.selectedTest = viewModel.allTestDetails.value?.get(pos)
}
}
rvAdapter.itemClickListener = itemClickListener
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
binding.recyclerView.adapter = rvAdapter
// Toast.makeText(requireActivity(), viewModel.temp, Toast.LENGTH_SHORT).show()
// viewModel.temp++
// Log.d(TAG, "viewmodel temp = ${viewModel.temp}")
return binding.root
} catch (e: Exception){
e.printStackTrace()
Log.e(TAG, "onCreateView", e);
throw e
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupObservers()
viewModel.fetchAllTestData()
binding.btnAdd.setOnClickListener {
viewModel.initializePatientDetails(PatientDetails())
findNavController().navigate(R.id.action_nav_home_to_registerOneScanAbhaFragment)
}
binding.btnTest.setOnClickListener {
if (DataHolder.selectedTest != null) {
findNavController().navigate(R.id.action_nav_home_to_mainActivity)
} else {
Toast.makeText(
requireContext(),
"Select One Record to start testing",
Toast.LENGTH_SHORT
).show()
}
}
}
private fun setupObservers() {
viewModel.allTestDetails.observe(viewLifecycleOwner) {
rvAdapter.updateDataSet(ArrayList(it))
// when(it) {
// is Response.Success -> {
// rvAdapter.updateDataSet(ArrayList(it.data))
// }
// is Response.Error -> {
//
// }
// }
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@@ -1,69 +0,0 @@
package com.example.hpos.presentation.dashboard.register
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.example.hpos.R
import com.example.hpos.data.constant.Constants
import com.example.hpos.databinding.FragmentRegisterOneCreateAbhaBinding
import com.example.hpos.presentation.dashboard.DashboardViewModel
class RegisterOneCreateAbha : Fragment() {
private val TAG = "RegisterOneCreateAbha"
private lateinit var binding: FragmentRegisterOneCreateAbhaBinding
private val viewModel: DashboardViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentRegisterOneCreateAbhaBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnRedirect.setOnClickListener {
redirectApp()
}
binding.tvSkip.setOnClickListener {
// Taking to aadhaar page if ABHA is skipped
findNavController().navigate(R.id.action_registerOneCreateAbha_to_registerTwoAadhaarFragment)
}
}
private fun redirectApp() {
val launchIntent: Intent? = requireActivity().packageManager
.getLaunchIntentForPackage(Constants.ABHA_APP_PACKAGE)
if (launchIntent != null) {
startActivity(launchIntent)
} else {
try {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=${Constants.ABHA_APP_PACKAGE}")))
} catch (e: ActivityNotFoundException) {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=${Constants.ABHA_APP_PACKAGE}")))
}
}
}
// private fun appInstalledOrNot(uri: String): Boolean {
// val pm: PackageManager = requireActivity().packageManager
// try {
// pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES)
// return true
// } catch (e: PackageManager.NameNotFoundException) {
// }
// return false
// }
}

View File

@@ -1,172 +0,0 @@
package com.example.hpos.presentation.dashboard.register
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.example.hpos.R
import com.example.hpos.data.model.patient.PatientDetails
import com.example.hpos.databinding.FragmentRegisterOneScanAbhaBinding
import com.example.hpos.presentation.dashboard.DashboardViewModel
import com.example.hpos.util.MyUtils.fetchYOBFromDOB
import com.example.hpos.util.MyUtils.mapToGender
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions
import com.google.mlkit.vision.codescanner.GmsBarcodeScanning
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions
import org.json.JSONObject
class RegisterOneScanAbhaFragment : Fragment() {
private val TAG = "RegisterOneScanAbha"
private lateinit var binding: FragmentRegisterOneScanAbhaBinding
private val viewModel: DashboardViewModel by activityViewModels()
private val barcodeLauncher = registerForActivityResult(
ScanContract()
) { result: ScanIntentResult ->
if (result.contents == null) {
Toast.makeText(requireContext(), "Cancelled: Unable to scan, Try Again!!", Toast.LENGTH_LONG).show()
} else {
Log.d(TAG, result.contents)
processScannedData(result.contents)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentRegisterOneScanAbhaBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Toast.makeText(requireContext(), viewModel.temp, Toast.LENGTH_SHORT).show()
viewModel.temp++
Log.d(TAG, "viewmodel temp = ${viewModel.temp}")
binding.btnScanNow.setOnClickListener {
startScanningNow()
}
binding.btnGo.setOnClickListener {
val abhaID = validateAndReturnId()
if (abhaID == null) {
Toast.makeText(requireContext(), "Invalid ID Entered", Toast.LENGTH_SHORT).show()
} else {
viewModel.patientDetails.id = abhaID
viewModel.patientDetails.isIdABHA = true
// Scan aadhaar card to get more details
moveToRegisterTwo()
}
}
binding.btnClickHere.setOnClickListener {
findNavController().navigate(R.id.action_registerOneScanAbhaFragment_to_registerOneCreateAbha)
}
}
private fun validateAndReturnId(): String? {
if (binding.nameEditText.text.isNullOrEmpty() || binding.nameEditText.text?.length != 14){
return null
}
return binding.nameEditText.text.toString()
}
private fun startScanningNow() {
val options = ScanOptions()
options.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
options.setPrompt("Scan a barcode")
options.setCameraId(0) // Use a specific camera of the device
options.setBeepEnabled(true)
options.setBarcodeImageEnabled(true)
options.setPrompt("Start Scanning")
options.setOrientationLocked(false)
// options.setTimeout(10000) // in ms
barcodeLauncher.launch(options)
}
private fun processScannedData(contents: String) {
try {
val obj = JSONObject(contents)
// Log.d(TAG, obj.get("hidn").toString())
// Log.d(TAG, obj.get("name").toString())
// Log.d(TAG, obj.get("address").toString())
// Details mapping
viewModel.patientDetails.id = obj.get("hidn").toString().replace("-", "")
viewModel.patientDetails.isIdABHA = true
viewModel.patientDetails.name = obj.get("name").toString()
viewModel.patientDetails.gender = obj.get("gender").toString().mapToGender()
viewModel.patientDetails.yob = obj.get("dob").toString().fetchYOBFromDOB()
viewModel.patientDetails.mobile = obj.get("mobile").toString()
// Address mapping
viewModel.patientDetails.address = PatientDetails.Address()
viewModel.patientDetails.address!!.state = obj.get("state name").toString()
viewModel.patientDetails.address!!.district = obj.get("district_name").toString()
viewModel.patientDetails.address!!.house = obj.get("address").toString()
moveToRegisterThree()
} catch (e: Exception) {
Log.e(TAG, "Unable to parse json")
e.printStackTrace()
}
}
private fun moveToRegisterThree() {
findNavController().navigate(R.id.action_registerOneScanAbhaFragment_to_registerThreeEnterPatientDetails)
}
private fun moveToRegisterTwo() {
findNavController().navigate(R.id.action_registerOneScanAbhaFragment_to_registerTwoAadhaarFragment)
}
// fun String.mapToGender(): PatientDetails.Gender {
// if (this.lowercase() == "m"|| this.lowercase() == "male") {
// return PatientDetails.Gender.MALE
// } else if (this.lowercase() == "f"|| this.lowercase() == "female") {
// return PatientDetails.Gender.FEMALE
// } else {
// return PatientDetails.Gender.OTHER
// }
// }
private fun startScanningNow2() {
val options = GmsBarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
.build()
val scanner = GmsBarcodeScanning.getClient(requireActivity(), options)
scanner.startScan()
.addOnSuccessListener { barcode ->
Log.d(TAG, barcode.rawValue!!)
}
.addOnCanceledListener {
// Task canceled
Log.d(TAG, "cancelled")
}
.addOnFailureListener { e ->
Log.d(TAG, "failed")
e.printStackTrace()
}
}
}

View File

@@ -1,314 +0,0 @@
package com.example.hpos.presentation.dashboard.register
import android.Manifest
import android.content.pm.PackageManager
import android.location.Location
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.example.hpos.R
import com.example.hpos.data.model.Response
import com.example.hpos.data.model.patient.PatientDetails
import com.example.hpos.databinding.FragmentRegisterThreeEnterPatientDetailsBinding
import com.example.hpos.presentation.dashboard.DashboardViewModel
import com.example.hpos.util.MyUtils.mapToCategory
import com.example.hpos.util.MyUtils.mapToGender
import com.example.hpos.util.MyUtils.mapYesNoStringToBool
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import java.util.Calendar
class RegisterThreeEnterPatientDetails : Fragment() {
private val TAG = "RegisterThreeEnterPat"
private lateinit var binding: FragmentRegisterThreeEnterPatientDetailsBinding
private val viewModel: DashboardViewModel by activityViewModels()
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var locationCallback: LocationCallback
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity())
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
locationResult.lastLocation?.let { location ->
viewModel.deviceLocation = com.example.hpos.data.model.Location(location.latitude, location.longitude)
}
}
}
getLocation()
binding =
FragmentRegisterThreeEnterPatientDetailsBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
prefillTexts()
setupObservers()
binding.btnSubmit.setOnClickListener {
val mPatient = validateAndReturnPatientData()
if (mPatient != null) {
viewModel.patientDetails = mPatient
viewModel.pushPatientDetailsToDb()
viewModel.createTest()
moveToNextPage()
} else {
Toast.makeText(requireContext(), "Fields can't be empty", Toast.LENGTH_SHORT).show()
}
}
}
private fun setupObservers() {
viewModel.dataUploadStatus.observe(viewLifecycleOwner) {
when (it) {
is Response.Success -> {
Log.d(TAG, "Patient details pushed to DB successfully")
// Directly pushing because of limitation of offline
// Toast.makeText(
// requireContext(),
// "Patient Details Added successfully",
// Toast.LENGTH_SHORT
// ).show()
//
// viewModel.createTest(requireContext())
}
is Response.Error -> {
it.exception.printStackTrace()
Toast.makeText(
requireContext(),
"Failed to add Patient Details, please try again.",
Toast.LENGTH_LONG
).show()
}
}
}
}
private fun moveToNextPage() {
findNavController().navigate(R.id.action_registerThreeEnterPatientDetails_to_nav_home)
}
private fun prefillTexts() {
viewModel.patientDetails.name?.let { binding.etName.setText(it) }
viewModel.patientDetails.yob?.let { binding.etYob.setText(it.toString()) }
viewModel.patientDetails.gender?.let { binding.etGenderBlock.setText(it.toString(), false) }
viewModel.patientDetails.mobile?.let { binding.etMobile.setText(it) }
viewModel.patientDetails.address?.house?.let { binding.etHouse.setText(it) }
viewModel.patientDetails.address?.district?.let { binding.etDistrict.setText(it) }
viewModel.patientDetails.address?.state?.let { binding.etState.setText(it) }
viewModel.patientDetails.address?.pinCode?.let { binding.etPincode.setText(it.toString()) }
}
private fun validateAndReturnPatientData(): PatientDetails? {
if (viewModel.patientDetails.id.isEmpty()) {
Toast.makeText(
requireContext(),
"Unable to get \"ABHA ID\" or \"AADHAAR NO\", please try again",
Toast.LENGTH_LONG
).show()
}
if (viewModel.patientDetails.address == null) {
viewModel.patientDetails.address = PatientDetails.Address()
}
if (binding.etName.text.isNullOrEmpty()) {
binding.etName.error = getString(R.string.name_error)
return null
} else {
viewModel.patientDetails.name = binding.etName.text.toString()
}
if (binding.etYob.text.isNullOrEmpty()) {
binding.etYob.error = getString(R.string.yob_error)
return null
} else if (binding.etYob.text.toString().toInt() <= 1900 || binding.etYob.text.toString()
.toInt() > 2023
) {
binding.etYob.error = getString(R.string.yob_error_2)
return null
} else {
viewModel.patientDetails.yob = binding.etYob.text.toString().toInt()
}
if (binding.etGenderBlock.text.isNullOrEmpty()) {
binding.etGenderBlock.error = getString(R.string.gender_error)
return null
} else {
viewModel.patientDetails.gender = binding.etGenderBlock.text.toString().mapToGender()
}
if (binding.etMobile.text.isNullOrEmpty()) {
binding.etMobile.error = getString(R.string.mobile_error)
return null
} else if (binding.etMobile.text.toString().length != 10) {
binding.etMobile.error = getString(R.string.mobile_error)
return null
}else {
viewModel.patientDetails.mobile = binding.etMobile.text.toString()
}
if (binding.etCareof.text.isNullOrEmpty()) {
binding.etCareof.error = getString(R.string.this_error)
return null
} else {
viewModel.patientDetails.careOf = binding.etCareof.text.toString()
}
if (binding.etIsMarried.text.isNullOrEmpty()) {
binding.etIsMarried.error = getString(R.string.this_error)
return null
} else {
viewModel.patientDetails.isMarried =
binding.etIsMarried.text.toString().mapYesNoStringToBool()
}
if (binding.etCategory.text.isNullOrEmpty()) {
binding.etCategory.error = getString(R.string.this_error)
return null
} else {
viewModel.patientDetails.category = binding.etCategory.text.toString().mapToCategory()
}
if (binding.etHouse.text.isNullOrEmpty()) {
binding.etHouse.error = getString(R.string.this_error)
return null
} else {
viewModel.patientDetails.address?.house = binding.etHouse.text.toString()
}
if (binding.etCity.text.isNullOrEmpty()) {
binding.etCity.error = getString(R.string.this_error)
return null
} else {
viewModel.patientDetails.address?.city = binding.etCity.text.toString()
}
if (binding.etState.text.isNullOrEmpty()) {
binding.etState.error = getString(R.string.this_error)
return null
} else {
viewModel.patientDetails.address?.state = binding.etState.text.toString()
}
if (binding.etPincode.text.isNullOrEmpty() || binding.etPincode.text?.length != 6) {
binding.etPincode.error = getString(R.string.this_error)
return null
} else {
viewModel.patientDetails.address?.pinCode = binding.etPincode.text.toString().toInt()
}
if (binding.etBloodGroup.text.isNullOrEmpty()) {
binding.etBloodGroup.error = getString(R.string.this_error)
return null
} else {
viewModel.patientDetails.bloodGroup = binding.etBloodGroup.text.toString()
}
viewModel.patientDetails.isUnderMedication = binding.cbItem1.isChecked
viewModel.patientDetails.isUnderTransfusion = binding.cbItem2.isChecked
viewModel.patientDetails.registerDate = Calendar.getInstance().time
return viewModel.patientDetails
}
// private fun getLocation() {
// locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager
// if ((ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
// ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), locationPermissionCode)
// }
// locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 5f, this)
// }
// private fun getLocation() {
// fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity())
// locationCallback = object : LocationCallback() {
// override fun onLocationResult(locationResult: LocationResult) {
// locationResult.lastLocation?.let { location ->
// val latitude = location.latitude
// val longitude = location.longitude
// }
// }
// }
// }
private fun requestLocationUpdates() {
val locationRequest = LocationRequest.create().apply {
interval = 10000 // Interval for receiving location updates (in milliseconds)
fastestInterval = 5000 // Fastest interval for location updates (in milliseconds)
priority = LocationRequest.PRIORITY_HIGH_ACCURACY // Location accuracy priority
}
if (ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
}
private fun getLocation() {
if (ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// Handle location permission request if needed
Toast.makeText(requireContext(), "Please enable location services", Toast.LENGTH_SHORT).show()
return
}
fusedLocationClient.lastLocation
.addOnSuccessListener { location: Location? ->
location?.let {
viewModel.deviceLocation = com.example.hpos.data.model.Location(it.latitude, it.longitude)
} ?: run {
requestLocationUpdates()
}
}
.addOnFailureListener { exception: Exception ->
exception.printStackTrace()
}
}
private fun stopLocationUpdates() {
fusedLocationClient.removeLocationUpdates(locationCallback)
}
override fun onResume() {
super.onResume()
getLocation()
}
override fun onPause() {
super.onPause()
stopLocationUpdates()
}
}

View File

@@ -1,124 +0,0 @@
package com.example.hpos.presentation.dashboard.register
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.example.hpos.R
import com.example.hpos.databinding.FragmentRegisterTwoAadhaarBinding
import com.example.hpos.domain.AadhaarScanner.QrCodeException
import com.example.hpos.domain.AadhaarScanner.SecureQrCode
import com.example.hpos.presentation.dashboard.DashboardViewModel
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions
class RegisterTwoAadhaarFragment : Fragment() {
private val TAG = "RegisterTwoAadhaarFrag"
private lateinit var binding: FragmentRegisterTwoAadhaarBinding
private val viewModel: DashboardViewModel by activityViewModels()
private val barcodeLauncher = registerForActivityResult(
ScanContract()
) { result: ScanIntentResult ->
if (result.contents == null) {
Toast.makeText(requireContext(), "Cancelled: Unable to scan, Try Again!!", Toast.LENGTH_LONG).show()
} else {
Log.d(TAG, result.contents)
processScannedData(result.contents)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentRegisterTwoAadhaarBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnScanNow.setOnClickListener {
startScanningNow()
}
binding.btnGo.setOnClickListener {
val aadhaarId = validateAndReturnId()
if (aadhaarId == null) {
binding.etAbhaId.error = getString(R.string.please_enter_aadhaar)
Toast.makeText(requireContext(), "Invalid ID Entered", Toast.LENGTH_SHORT).show()
} else {
viewModel.patientDetails.id = aadhaarId
viewModel.patientDetails.isIdABHA = false
checkForIdThenMove()
}
}
binding.etAbhaId.setOnClickListener { binding.etAbhaId.isErrorEnabled = false }
}
private fun validateAndReturnId(): String? {
if (binding.nameEditText.text.isNullOrEmpty() || binding.nameEditText.text?.length != 12){
return null
}
return binding.nameEditText.text.toString()
}
private fun startScanningNow() {
val options = ScanOptions()
options.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
options.setPrompt("Scan a barcode")
options.setCameraId(0) // Use a specific camera of the device
options.setBeepEnabled(true)
options.setBarcodeImageEnabled(true)
options.setPrompt("Start Scanning")
options.setOrientationLocked(false)
// options.setTimeout(10000) // in ms
barcodeLauncher.launch(options)
}
private fun processScannedData(scanData: String) {
try {
val decodedData = SecureQrCode(requireActivity(), scanData)
viewModel.aadharCard = decodedData.scannedAadharCard
Toast.makeText(requireContext(), "Scanned Aadhar Card Successfully", Toast.LENGTH_SHORT).show()
Log.d(TAG, viewModel.aadharCard.toString())
viewModel.mapAadhaarDataToPatient()
checkForIdThenMove()
} catch (e: QrCodeException) {
e.printStackTrace()
Toast.makeText(requireContext(), "Unable to Fetch data, please scan again or enter manually!!", Toast.LENGTH_LONG).show()
}
}
private fun checkForIdThenMove() {
Log.d(TAG, "Inside: checkForIdThenMove()")
Log.d(TAG, "ID is ${viewModel.patientDetails.id}")
if (viewModel.patientDetails.id.isNullOrEmpty()){
binding.etAbhaId.error = getString(R.string.please_enter_aadhaar)
binding.btnScanNow.alpha = 0.2f
binding.btnScanNow.isEnabled = false
} else {
moveToRegisterThree()
}
}
private fun moveToRegisterThree() {
findNavController().navigate(R.id.action_registerTwoAadhaarFragment_to_registerThreeEnterPatientDetails)
}
}

View File

@@ -1,29 +0,0 @@
package com.example.hpos.util
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.hpos.data.repository.DatabaseRepository
import com.example.hpos.data.repository.LocalFileRepository
import com.example.hpos.data.datasource.LocalFileDataSource
import com.example.hpos.domain.SaveRawData
import com.example.hpos.domain.SaveRawDataTest
import com.example.hpos.presentation.MainViewModel
import com.example.hpos.presentation.dashboard.DashboardViewModel
import com.example.hpos.presentation.testRight.TestRightViewModel
class MyViewModelFactory : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(MainViewModel::class.java))
return MainViewModel() as T
else if (modelClass.isAssignableFrom(TestRightViewModel::class.java)) {
val repository = LocalFileRepository(LocalFileDataSource())
return TestRightViewModel(SaveRawData(repository), SaveRawDataTest(repository), DatabaseRepository()) as T
} else if (modelClass.isAssignableFrom(DashboardViewModel::class.java)) {
// val repository = LocalFileRepository(LocalFileDataSource())
// return DashboardViewModel(DatabaseRepository()) as T
return DashboardViewModel() as T
} else
throw IllegalArgumentException("Unknown ViewModel class");
}
}

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@HiltAndroidApp
class HPOSTestingApplication: Application() {
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
}

View File

@@ -1,9 +1,9 @@
package com.example.hpos.data
package com.example.hpostesting.data
import androidx.lifecycle.MutableLiveData
import com.example.hpos.data.model.test.TestDetails
import com.example.hpos.data.model.test.TestRightDeviceConstants
import com.example.hpos.data.model.test.TestType
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestRightDeviceConstants
import com.example.hpostesting.data.model.test.TestType
object DataHolder {
@@ -28,7 +28,9 @@ object DataHolder {
/* (For reference/baseline) Contains pixel no. -> Intensity of light falling on that pixel */
val intensityReferenceArray = ArrayList<Double>()
var selectedTest: TestDetails? = null
var selectedTest: UserData? = null
var location: UserData.Location? = null
var testExp: Boolean = true
}

View File

@@ -1,12 +1,11 @@
package com.example.hpos.data
package com.example.hpostesting.data
import android.util.Log
import com.example.hpos.data.model.Response
import com.example.hpos.data.repository.DatabaseRepository
import com.example.hpos.util.MyUtils
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.util.MyUtils
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.lang.Thread.sleep
class FileUploader {

View File

@@ -0,0 +1,62 @@
package com.example.hpostesting.data
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.lifecycle.LiveData
class NetworkStatusLiveData(context: Context) : LiveData<Boolean>() {
private val connectivityManager: ConnectivityManager =
context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
postValue(true)
}
override fun onLost(network: Network) {
postValue(false)
}
}
@RequiresApi(Build.VERSION_CODES.M)
override fun onActive() {
super.onActive()
postValue(isNetworkAvailable())
registerNetworkCallback()
}
override fun onInactive() {
super.onInactive()
unregisterNetworkCallback()
}
private fun registerNetworkCallback() {
val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.build()
connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
}
private fun unregisterNetworkCallback() {
connectivityManager.unregisterNetworkCallback(networkCallback)
}
@RequiresApi(Build.VERSION_CODES.M)
private fun isNetworkAvailable(): Boolean {
val network = connectivityManager.activeNetwork
val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
return networkCapabilities != null &&
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
}

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data
package com.example.hpostesting.data
import android.content.Context
import android.content.SharedPreferences

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.constant
package com.example.hpostesting.data.constant
object Constants {
const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION"

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.constant
package com.example.hpostesting.data.constant
enum class TestRightCommands(val command: String) {
led2Set50("led2 50\r"),

View File

@@ -0,0 +1,27 @@
package com.example.hpostesting.data.dao
import androidx.room.TypeConverter
import com.example.hpostesting.data.model.patient.UserData
import com.google.gson.Gson
class Converters {
private val gson = Gson()
@TypeConverter
fun fromString(value: String?): UserData.Location? {
return if (value != null) {
gson.fromJson(value, UserData.Location::class.java)
} else {
null
}
}
@TypeConverter
fun toString(location: UserData.Location?): String? {
return if (location != null) {
gson.toJson(location)
} else {
null
}
}
}

View File

@@ -0,0 +1,12 @@
package com.example.hpostesting.data.dao
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import com.example.hpostesting.data.model.patient.UserData
@Database(entities = [UserData::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}

View File

@@ -0,0 +1,23 @@
package com.example.hpostesting.data.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.hpostesting.data.model.patient.UserData
@Dao
interface UserDao {
@Query("SELECT * from user_table")
fun getAll(): LiveData<List<UserData>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(userData: UserData)
@Query("SELECT * FROM user_table WHERE _id = :id")
suspend fun getUserByID(id: String): UserData
@Query("DELETE FROM user_table WHERE _id = :id")
suspend fun deleteById(id: String)
}

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.datasource
package com.example.hpostesting.data.datasource
import com.opencsv.CSVWriter
import java.io.File

View File

@@ -0,0 +1,21 @@
package com.example.hpostesting.data.model
class AadharCard {
var name = ""
var dateOfBirth = ""
var gender = ""
var careOf = ""
var district = ""
var landmark = ""
var house = ""
var location = ""
var pinCode = ""
var postOffice = ""
var state = ""
var street = ""
var subDistrict = ""
var vtc = ""
var mobile = ""
}

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model
package com.example.hpostesting.data.model
data class CalculationVariableForTest(
var pixelNo: Int,

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model
package com.example.hpostesting.data.model
data class ErrorMessage (
val message: String,

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model
package com.example.hpostesting.data.model
data class Location(
var latitude: Double?,

View File

@@ -1,6 +1,6 @@
package com.example.hpos.data.model
package com.example.hpostesting.data.model
import com.example.hpos.data.model.test.TestRightResultType
import com.example.hpostesting.data.model.test.TestRightResultType
data class PatientData(
val name: String,

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model
package com.example.hpostesting.data.model
import java.util.Calendar
import java.util.Date

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model
package com.example.hpostesting.data.model
sealed class Response<out R> {
data class Success<out T>(val data: T) : Response<T>()

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model.patient
package com.example.hpostesting.data.model.patient
import java.util.Date

View File

@@ -0,0 +1,53 @@
package com.example.hpostesting.data.model.patient
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.example.hpostesting.data.model.test.TestRightResultType
@Entity(tableName = "user_table")
data class UserData(
@PrimaryKey
var _id: String = "",
var AbhaId: String = "",
var AadharId: String = "",
var name: String = "",
var birthYear: String = "",
var gender: String = "",
var phoneNumber: String = "",
var careOf: String = "",
var maritalStatus: String = "",
var caste: String = "",
var subCaste: String = "",
var house: String = "",
var city: String = "",
var district: String = "",
var state: String = "",
var pinCode: String = "",
var bloodGroup: String = "",
var isUnderMedication: Boolean? = false,
var isUnderTransfusion: Boolean? = false,
var sickleCellHistory: String? = "",
var userImage: String = "",
var location: Location? = null,
var uploadTime: String? = "",
var testTime: String? = "",
var testStatus: Boolean? = false,
var mobileId: String = "",
var deviceId: String = "",
var kitSerial: String = "",
var csvPath: String = "",
var reportPath: String = "",
var result: TestRightResultType? = null,
var resultRatio: Double? = null,
){
enum class Gender {
MALE,
FEMALE,
OTHER
}
data class Location(
var latitude: Double? = null,
var longitude: Double? = null
)
}

View File

@@ -1,6 +1,6 @@
package com.example.hpos.data.model.test
package com.example.hpostesting.data.model.test
import com.example.hpos.data.model.Location
import com.example.hpostesting.data.model.Location
import java.util.Date
data class TestDetails(

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model.test
package com.example.hpostesting.data.model.test
data class TestInfo(
val value: String,

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model.test
package com.example.hpostesting.data.model.test
data class TestRightCalculationData(
var absorbanceOne: Double?,

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model.test
package com.example.hpostesting.data.model.test
data class TestRightDeviceConstants(
var a: String,

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model.test
package com.example.hpostesting.data.model.test
enum class TestRightResultType {
NORMAL,

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.model.test
package com.example.hpostesting.data.model.test
enum class TestType {
SICKLECERT,

View File

@@ -0,0 +1,90 @@
package com.example.hpostesting.data.repository
import android.net.Uri
import com.example.hpostesting.data.model.PendingUploads
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.UserData
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.ktx.storage
import kotlinx.coroutines.tasks.await
import java.io.File
class DatabaseRepository : Repository {
private val db: FirebaseFirestore = Firebase.firestore
private val storage = Firebase.storage
suspend fun addTestToDatabase(data: UserData): Response<String> {
return try {
val userdata = db.collection("patientData").whereEqualTo("_id", data._id).get().await()
if (userdata.documents.isNotEmpty()) {
userdata.documents.forEach {
db.collection("patientData").document(it.id).update("testStatus", true)
}
}
db.collection("testData").add(data).await()
Response.Success(data._id)
} catch (e: Exception) {
Response.Error(e)
}
}
suspend fun uploadFileToStorage(patientID: String, filePath: String): Response<Boolean> {
try {
val file = Uri.fromFile(File(filePath))
val riversRef = storage.reference.child("$patientID/${file.lastPathSegment}")
riversRef.putFile(file).await()
return Response.Success(true)
} catch (e: Exception) {
e.printStackTrace()
return Response.Error(e)
}
}
suspend fun addToPendingQueue(pendingUploads: PendingUploads): Response<Boolean> {
return try {
db.collection("pendingUploads").document(pendingUploads.pendingId).set(pendingUploads)
.await()
Response.Success(true)
} catch (e: Exception) {
e.printStackTrace()
Response.Error(e)
}
}
suspend fun getAllFromPendingQueue(): List<PendingUploads> {
val pendingList = mutableListOf<PendingUploads>()
return try {
val querySnapshot = db.collection("pendingUploads").orderBy("timeAdded").get().await()
for (doc in querySnapshot.documents) {
val pendingFile = doc.toObject(PendingUploads::class.java)
pendingFile?.let {
pendingList.add(it)
}
}
pendingList
} catch (e: Exception) {
e.printStackTrace()
pendingList
}
}
suspend fun removeFromPendingQueue(fileName: String): Response<Boolean> {
return try {
db.collection("pendingUploads").document(fileName).delete().await()
Response.Success(true)
} catch (e: Exception) {
e.printStackTrace()
Response.Error(e)
}
}
}

View File

@@ -1,6 +1,6 @@
package com.example.hpos.data.repository
package com.example.hpostesting.data.repository
import com.example.hpos.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.datasource.LocalFileDataSource
class LocalFileRepository(private val localFileDataSource: LocalFileDataSource) {
fun saveCsvToDisk(filepath: String, contents: ArrayList<Array<String>>) =

View File

@@ -1,4 +1,4 @@
package com.example.hpos.data.repository
package com.example.hpostesting.data.repository
interface Repository {
// suspend fun addToDatabase(data: PatientDetails)

View File

@@ -1,8 +1,8 @@
package com.example.hpos.domain
package com.example.hpostesting.domain
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.model.test.TestRightCalculationData
import com.example.hpos.data.model.test.TestRightResultType
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.test.TestRightCalculationData
import com.example.hpostesting.data.model.test.TestRightResultType
class ResultCalculationWithAvgImpl : TestRightResultCalculation {

View File

@@ -1,8 +1,8 @@
package com.example.hpos.domain
package com.example.hpostesting.domain
import android.util.Log
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.model.test.TestRightResultType
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.test.TestRightResultType
import kotlin.math.log10
class ResultCalculationWithFirstImpl {

View File

@@ -1,8 +1,8 @@
package com.example.hpos.domain
package com.example.hpostesting.domain
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.model.test.TestRightCalculationData
import com.example.hpos.data.model.test.TestRightResultType
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.test.TestRightCalculationData
import com.example.hpostesting.data.model.test.TestRightResultType
class ResultCalculationWithMaxImpl : TestRightResultCalculation {

View File

@@ -1,10 +1,10 @@
package com.example.hpos.domain
package com.example.hpostesting.domain
import android.util.Log
import com.example.hpos.data.repository.LocalFileRepository
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.model.test.TestDetails
import com.example.hpos.data.model.test.TestRightCalculationData
import com.example.hpostesting.data.repository.LocalFileRepository
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestRightCalculationData
import java.util.Collections.sort
class SaveRawData(private val localFileRepository: LocalFileRepository) {
@@ -98,7 +98,7 @@ class SaveRawData(private val localFileRepository: LocalFileRepository) {
folderPath: String,
fileName: String,
calculationData: TestRightCalculationData,
testDetails: TestDetails?
testDetails: UserData?
) {
// val fileObj = File(folderPath, fileName)
// val writer = FileWriter(fileObj)
@@ -116,11 +116,11 @@ class SaveRawData(private val localFileRepository: LocalFileRepository) {
private fun getLogStringFromObjWithPatientData(
calculationData: TestRightCalculationData,
testDetails: TestDetails?
testDetails: UserData?
): String {
var outputString = "Test calculation logs ==>\n"
outputString += "Name = ${testDetails?.patientName}\n"
outputString += "ID = ${testDetails?.patientID}\n"
outputString += "Name = ${testDetails?.name}\n"
outputString += "ID = ${testDetails?._id}\n"
// outputString += "Gender = ${patientData.gender}\n"
outputString += "Absorbance one = ${
String.format(

View File

@@ -1,7 +1,7 @@
package com.example.hpos.domain
package com.example.hpostesting.domain
import com.example.hpos.data.repository.LocalFileRepository
import com.example.hpos.data.model.CalculationVariableForTest
import com.example.hpostesting.data.repository.LocalFileRepository
import com.example.hpostesting.data.model.CalculationVariableForTest
class SaveRawDataTest(private val localFileRepository: LocalFileRepository) {

View File

@@ -1,8 +1,8 @@
package com.example.hpos.domain
package com.example.hpostesting.domain
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.model.test.TestRightCalculationData
import com.example.hpos.data.model.test.TestRightResultType
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.test.TestRightCalculationData
import com.example.hpostesting.data.model.test.TestRightResultType
class SickleFindResultCaluculationWithMaxImpl : TestRightResultCalculation{

View File

@@ -1,6 +1,6 @@
package com.example.hpos.domain
package com.example.hpostesting.domain
import com.example.hpos.data.model.test.TestRightCalculationData
import com.example.hpostesting.data.model.test.TestRightCalculationData
interface TestRightResultCalculation {
fun getResults(

View File

@@ -0,0 +1,63 @@
package com.example.hpostesting.domain.di
import android.app.Application
import android.content.Context
import androidx.room.Room
import com.example.hpostesting.data.dao.MyDatabase
import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.datasource.LocalFileDataSource
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.data.repository.LocalFileRepository
import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase {
return Room.databaseBuilder(
context, MyDatabase::class.java, "my_database"
).build()
}
@Provides
@Singleton
fun provideMyDao(myDatabase: MyDatabase): UserDao {
return myDatabase.userDao()
}
@Provides
@Singleton
fun provideContext(application: Application): Context {
return application.applicationContext
}
@Provides
@Singleton
fun provideSaveRawData(): SaveRawData {
val repository = LocalFileRepository(LocalFileDataSource())
return SaveRawData(repository)
}
@Provides
@Singleton
fun provideSaveRawDataTest(): SaveRawDataTest {
val repository = LocalFileRepository(LocalFileDataSource())
return SaveRawDataTest(repository)
}
@Provides
@Singleton
fun provideDatabaseRepository(): DatabaseRepository {
return DatabaseRepository()
}
}

View File

@@ -1,19 +1,19 @@
package com.example.hpos.presentation
package com.example.hpostesting.presentation
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.hpos.R
import com.example.hpos.data.DataHolder
import com.example.hpos.data.constant.Constants
import com.example.hpos.databinding.ActivityKitScanBinding
import com.example.hpos.presentation.dashboard.DashboardActivity
import com.example.hpos.presentation.testRight.TestRightActivity
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.presentation.testRight.TestRightActivity
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityKitScanBinding
class KitScanActivity : AppCompatActivity() {
@@ -51,6 +51,7 @@ class KitScanActivity : AppCompatActivity() {
startScanningNow()
}
binding.btnGo.setOnClickListener {
val serialNumber = binding.nameEditText.text.toString().trim()
if (serialNumber.isNotEmpty() && checkDataNotNull() && isSerialValid(serialNumber)) {
@@ -92,7 +93,7 @@ class KitScanActivity : AppCompatActivity() {
}
private fun checkDataNotNull(): Boolean {
return if (DataHolder.selectedTest == null) {
return if (DataHolder.selectedTest?._id == null) {
Toast.makeText(
applicationContext,
"Please Select patient before starting test",

View File

@@ -0,0 +1,255 @@
package com.example.hpostesting.presentation
import android.Manifest
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.hardware.usb.UsbManager
import android.location.Location
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.get
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestType
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.hoho.android.usbserial.driver.UsbSerialProber
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var myMenu: Menu? = null
private val TAG = "MainActivity"
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var locationCallback: LocationCallback
private var mUsbReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val action = intent.action
if (UsbManager.ACTION_USB_DEVICE_DETACHED == action) {
DataHolder.usbConnected.value = false
} else if (UsbManager.ACTION_USB_DEVICE_ATTACHED == action) {
DataHolder.usbConnected.value = true
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.myToolbar)
setupListeners()
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
getLocation()
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
locationResult.lastLocation?.let { location ->
DataHolder.location = UserData.Location(location.latitude, location.longitude)
Log.i("Location", DataHolder.location.toString())
}
}
}
val filter = IntentFilter().apply {
addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED)
}
registerReceiver(mUsbReceiver, filter)
}
private fun checkAndUpdateUsbConnection() {
val availableDrivers = UsbSerialProber.getDefaultProber()
.findAllDrivers(getSystemService(Context.USB_SERVICE) as UsbManager)
if (availableDrivers.isNotEmpty() && availableDrivers[0].device.productId == Constants.DEVICE_PRODUCT_ID && availableDrivers[0].device.vendorId == Constants.DEVICE_VENDOR_ID) {
Log.d(TAG, "Device matched -> product = ${availableDrivers[0].device.productId}, vendor = ${availableDrivers[0].device.vendorId}")
DataHolder.usbConnected.value = true
} else if (availableDrivers.isNotEmpty()) {
Log.d(TAG, "Device NOT matched -> product = ${availableDrivers[0].device.productId}, vendor = ${availableDrivers[0].device.vendorId}")
Toast.makeText(this, "Device Not Compatible", Toast.LENGTH_SHORT).show()
DataHolder.usbConnected.value = false
} else {
Log.d(TAG, "Device NOT Connected")
DataHolder.usbConnected.value = false
}
}
private fun setupListeners() {
binding.cvItem1.setOnClickListener {
DataHolder.selectedTestType = TestType.SICKLECERT
val i = Intent(applicationContext, KitScanActivity::class.java)
startActivity(i)
}
binding.cvItem2.setOnClickListener {
DataHolder.selectedTestType = TestType.SICKLEFIND
val i = Intent(applicationContext, KitScanActivity::class.java)
startActivity(i)
}
DataHolder.usbConnected.observe(this) {
if (it) {
myMenu?.get(0)?.icon = ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_24)
} else {
myMenu?.get(0)?.icon = ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24)
}
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.my_menu, menu)
myMenu = menu
checkAndUpdateUsbConnection()
return true
}
private fun requestCoarseLocationPermission() {
val coarseLocationPermission = Manifest.permission.ACCESS_COARSE_LOCATION
val coarseLocationPermissionRequestCode = 101
if (ContextCompat.checkSelfPermission(
this,
coarseLocationPermission
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(coarseLocationPermission),
coarseLocationPermissionRequestCode
)
} else {
getLocation()
}
}
private fun requestFineLocationPermission() {
val fineLocationPermission = Manifest.permission.ACCESS_FINE_LOCATION
val fineLocationPermissionRequestCode = 102
if (ContextCompat.checkSelfPermission(
this,
fineLocationPermission
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(fineLocationPermission),
fineLocationPermissionRequestCode
)
} else {
getLocation()
}
}
private fun getLocation() {
val coarseLocationPermission = Manifest.permission.ACCESS_COARSE_LOCATION
val fineLocationPermission = Manifest.permission.ACCESS_FINE_LOCATION
if (ActivityCompat.checkSelfPermission(
this,
coarseLocationPermission
) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(
this,
fineLocationPermission
) != PackageManager.PERMISSION_GRANTED
) {
// Handle location permission request if needed
Toast.makeText(this, "Please enable location services", Toast.LENGTH_SHORT).show()
requestCoarseLocationPermission()
requestFineLocationPermission()
return
}
fusedLocationClient.lastLocation
.addOnSuccessListener { location: Location? ->
location?.let {
DataHolder.location = UserData.Location(location.latitude, location.longitude)
Log.i("Location", DataHolder.location.toString())
} ?: run {
requestLocationUpdates()
}
}
.addOnFailureListener { exception: Exception ->
exception.printStackTrace()
}
}
private fun requestLocationUpdates() {
val locationRequest = LocationRequest.create().apply {
interval = 10000 // Interval for receiving location updates (in milliseconds)
fastestInterval = 5000 // Fastest interval for location updates (in milliseconds)
priority = LocationRequest.PRIORITY_HIGH_ACCURACY // Location accuracy priority
}
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
}
private fun stopLocationUpdates() {
fusedLocationClient.removeLocationUpdates(locationCallback)
}
override fun onPause() {
super.onPause()
stopLocationUpdates()
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
101 -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Coarse location permission granted
requestFineLocationPermission()
} else {
// Coarse location permission denied
Toast.makeText(this, "Coarse location permission denied", Toast.LENGTH_SHORT).show()
}
}
102 -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Fine location permission granted
getLocation()
} else {
// Fine location permission denied
Toast.makeText(this, "Fine location permission denied", Toast.LENGTH_SHORT).show()
}
}
}
}
}

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation
package com.example.hpostesting.presentation
import androidx.lifecycle.ViewModel

View File

@@ -0,0 +1,161 @@
package com.example.hpostesting.presentation
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.util.MyUtils
import com.google.firebase.firestore.FirebaseFirestoreSettings
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import `in`.sminnovations.hpostesting.databinding.ActivitySplashBinding
class SplashActivity : AppCompatActivity() {
private lateinit var binding: ActivitySplashBinding
private val requiredPermissions = listOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
private var allPermissionsGranted = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySplashBinding.inflate(layoutInflater)
setContentView(binding.root)
setupFirestoreCache()
setupStaticConstants()
requestPermissions()
}
private fun setupStaticConstants() {
DataHolder.mobileUniqueId =
Settings.Secure.getString(applicationContext.contentResolver, Settings.Secure.ANDROID_ID)
}
private fun setupFirestoreCache() {
val settings = FirebaseFirestoreSettings.Builder()
.setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED)
.build()
Firebase.firestore.firestoreSettings = settings
}
private fun requestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
requestPermissionsAboveAndroidR()
} else {
requestPermissionsBelowAndroidR()
}
}
@RequiresApi(Build.VERSION_CODES.R)
private fun requestPermissionsAboveAndroidR() {
if (Environment.isExternalStorageManager()) {
handlePermissionsResult(true)
} else {
val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (Environment.isExternalStorageManager()) {
handlePermissionsResult(true)
} else {
Toast.makeText(
this,
"You must grant permission to access all files to use the app",
Toast.LENGTH_SHORT
).show()
finish()
}
}
val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
requestPermissionLauncher.launch(intent)
}
}
private fun requestPermissionsBelowAndroidR() {
val permissionsToRequest = requiredPermissions
.filterNot { permission ->
ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
.toTypedArray()
if (permissionsToRequest.isNotEmpty()) {
requestPermissionLauncher.launch(permissionsToRequest)
} else {
checkLocationAndCameraPermissions()
}
}
private fun checkLocationAndCameraPermissions() {
val fineLocationPermission = Manifest.permission.ACCESS_FINE_LOCATION
val coarseLocationPermission = Manifest.permission.ACCESS_COARSE_LOCATION
val cameraPermission = Manifest.permission.CAMERA
val locationPermissionsGranted =
ContextCompat.checkSelfPermission(this, fineLocationPermission) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(this, coarseLocationPermission) == PackageManager.PERMISSION_GRANTED
val cameraPermissionGranted = ContextCompat.checkSelfPermission(this, cameraPermission) == PackageManager.PERMISSION_GRANTED
if (locationPermissionsGranted && cameraPermissionGranted) {
handlePermissionsResult(true)
} else {
val permissionsToRequest = mutableListOf<String>()
if (!locationPermissionsGranted) {
permissionsToRequest.add(fineLocationPermission)
permissionsToRequest.add(coarseLocationPermission)
}
if (!cameraPermissionGranted) {
permissionsToRequest.add(cameraPermission)
}
requestPermissionLauncher.launch(permissionsToRequest.toTypedArray())
}
}
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
val grantedPermissions = permissions.entries.filter { it.value }.map { it.key }
handlePermissionsResult(grantedPermissions.size == requiredPermissions.size)
}
private fun handlePermissionsResult(allGranted: Boolean) {
allPermissionsGranted = allGranted
if (allGranted) {
moveToLandingPage()
} else {
Toast.makeText(this, "All permissions are required to use the app.", Toast.LENGTH_SHORT).show()
finish()
}
}
private fun moveToLandingPage() {
createAppFolder()
val intent = Intent(applicationContext, DashboardActivity::class.java)
startActivity(intent)
finish()
}
private fun createAppFolder() {
val folderPath = MyUtils.createAppFolder(applicationContext)
if (folderPath != null) {
DataHolder.isAppFolderCreated = true
DataHolder.appFolderPath = folderPath
}
}
}

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation
package com.example.hpostesting.presentation
interface UsbServiceListener {
fun onUsbRead(data: ByteArray?)

View File

@@ -0,0 +1,57 @@
package com.example.hpostesting.presentation.adapter
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.model.patient.UserData
import com.firebase.ui.firestore.FirestoreRecyclerAdapter
import com.firebase.ui.firestore.FirestoreRecyclerOptions
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.UserItemViewBinding
class UserListAdapter(options: FirestoreRecyclerOptions<UserData>, private val view: View) :
FirestoreRecyclerAdapter<UserData, UserListAdapter.OrderItemViewHolder>(options) {
class OrderItemViewHolder(val binding: UserItemViewBinding) :
RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OrderItemViewHolder {
return OrderItemViewHolder(
UserItemViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: OrderItemViewHolder, position: Int, model: UserData) {
holder.binding.apply {
userName.text = model.name
userId.text = model._id
Glide.with(view).load(model.userImage).into(userImage)
if (model.testStatus != null) {
if (model.testStatus!!) {
userCard.setCardBackgroundColor(view.resources.getColor(R.color.gray))
}
}
userCard.setOnClickListener {
if (model.testStatus != null) {
if (model.testStatus!!) {
Toast.makeText(
view.context,
"Test has been already conducted for this user",
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = model
view.findNavController().navigate(R.id.action_nav_home_to_mainActivity)
}
}
}
}
}
}

View File

@@ -1,27 +1,24 @@
package com.example.hpos.presentation.dashboard
package com.example.hpostesting.presentation.dashboard
import android.os.Bundle
import android.view.Menu
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.example.hpos.R
import com.example.hpos.databinding.ActivityDashboardBinding
import com.example.hpos.util.MyUtils
import com.example.hpos.util.MyViewModelFactory
import com.google.android.material.navigation.NavigationView
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding
@AndroidEntryPoint
class DashboardActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityDashboardBinding
private lateinit var viewModel: DashboardViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -43,10 +40,6 @@ class DashboardActivity : AppCompatActivity() {
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
viewModel = ViewModelProvider(
this,
MyViewModelFactory()
)[DashboardViewModel::class.java]
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.dashboard
package com.example.hpostesting.presentation.dashboard
import android.os.Bundle
import android.view.LayoutInflater
@@ -6,8 +6,8 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.example.hpos.databinding.FragmentGalleryBinding
import com.example.hpos.presentation.dashboard.ui.gallery.GalleryViewModel
import com.example.hpostesting.presentation.dashboard.ui.gallery.GalleryViewModel
import `in`.sminnovations.hpostesting.databinding.FragmentGalleryBinding
class GalleryFragment : Fragment() {

View File

@@ -0,0 +1,199 @@
package com.example.hpostesting.presentation.dashboard
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import java.util.Locale
@AndroidEntryPoint
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private val viewModel: TestRightViewModel by activityViewModels()
private lateinit var rvAdapter: UserListAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
DataHolder.selectedTest = null
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.allUserData.observe(viewLifecycleOwner) { userData ->
deleteIncompleteRegistrations(userData)
}
viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) {
binding.internetAvailableCL.visibility = View.VISIBLE
binding.internetNotAvailableCL.visibility = View.GONE
loadUserData()
setSearch()
checkForLocalDBData()
} else {
binding.internetAvailableCL.visibility = View.GONE
binding.internetNotAvailableCL.visibility = View.VISIBLE
setUserId()
}
}
binding.uploadData.setOnClickListener {
showUploadDialog(requireContext())
}
}
private fun setUserId() {
binding.btnSubmit.setOnClickListener {
val userId = binding.userId.text.toString()
if (userId.length >= 18) {
val userData = UserData(_id = userId)
DataHolder.selectedTest = userData
findNavController().navigate(R.id.action_nav_home_to_mainActivity)
} else {
val errorMessage = getString(R.string.user_id_error_message)
Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_SHORT).show()
binding.userId.error = errorMessage
}
}
}
private fun loadUserData() {
val query = Firebase.firestore.collection("patientData")
val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build()
rvAdapter = UserListAdapter(recyclerViewOptions, binding.root)
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
}
private fun getData(search: String?, field: String) {
val capitalizedSearch =
search?.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
Log.i("Capital", capitalizedSearch.toString())
val query = Firebase.firestore.collection("patientData")
.orderBy(field)
.whereArrayContainsAny(field, listOf(capitalizedSearch))
val recyclerViewOptions =
FirestoreRecyclerOptions.Builder<UserData>().setQuery(query, UserData::class.java)
.build()
rvAdapter = UserListAdapter(recyclerViewOptions, binding.root)
binding.rvOrder.adapter = rvAdapter
rvAdapter.startListening()
}
private fun setSearch() {
binding.searchProduct.setOnQueryTextListener(object :
androidx.appcompat.widget.SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return if (!query.isNullOrEmpty()) {
val field = when {
binding.userIdRadioButton.isChecked -> "_id"
binding.abhaIdRadioButton.isChecked -> "abhaId"
binding.aadharIdRadioButton.isChecked -> "aadharId"
else -> null
}
field?.let { getData(query, it) }
false
} else {
loadUserData()
false
}
}
override fun onQueryTextChange(query: String?): Boolean {
return if (!query.isNullOrEmpty()) {
val field = when {
binding.userIdRadioButton.isChecked -> "_id"
binding.abhaIdRadioButton.isChecked -> "abhaId"
binding.aadharIdRadioButton.isChecked -> "aadharId"
else -> null
}
field?.let { getData(query, it) }
false
} else {
loadUserData()
false
}
}
})
}
private fun checkForLocalDBData() {
viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
val uploadDataVisibility = if (userDataList.isEmpty()) View.GONE else View.VISIBLE
binding.uploadData.visibility = uploadDataVisibility
}
}
private fun showUploadDialog(context: Context) {
val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.upload_db_registration_title)
builder.setMessage(R.string.upload_db_registration_message)
builder.setPositiveButton(R.string.upload) { dialog, _ ->
uploadLocalDBData(dialog)
}
builder.setNegativeButton(R.string.cancel) { dialog, _ ->
dialog.dismiss()
}
val dialog = builder.create()
dialog.show()
}
private fun uploadLocalDBData(dialog: DialogInterface) {
viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
if (userDataList.isEmpty()) {
dialog.dismiss()
} else {
userDataList.forEach { userData ->
viewModel.bulkUploadResultToDatabase(userData)
viewModel.deleteById(userData._id)
}
dialog.dismiss()
Toast.makeText(requireContext(), R.string.upload_success_message, Toast.LENGTH_SHORT).show()
}
}
}
private fun deleteIncompleteRegistrations(userDataList: List<UserData>) {
userDataList.forEach { userData ->
if (userData._id.isEmpty()) {
viewModel.deleteById(userData._id)
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.dashboard
package com.example.hpostesting.presentation.dashboard
interface ItemClickListener {
fun onClick(pos: Int)

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.dashboard
package com.example.hpostesting.presentation.dashboard
import android.os.Bundle
import android.view.LayoutInflater
@@ -6,8 +6,8 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.example.hpos.databinding.FragmentSlideshowBinding
import com.example.hpos.presentation.dashboard.ui.slideshow.SlideshowViewModel
import com.example.hpostesting.presentation.dashboard.ui.slideshow.SlideshowViewModel
import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
class SlideshowFragment : Fragment() {

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.dashboard.ui.gallery
package com.example.hpostesting.presentation.dashboard.ui.gallery
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.dashboard.ui.home
package com.example.hpostesting.presentation.dashboard.ui.home
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.dashboard.ui.slideshow
package com.example.hpostesting.presentation.dashboard.ui.slideshow
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.testRight
package com.example.hpostesting.presentation.testRight
class InputData {
val inputRead = "0,1.69989422e-06,1.60642711e-01,3.85754470e+02,0,0,1,0,FFF-EEEE-PPPP-WW-YY-NNNN\nOK [0]"

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.testRight
package com.example.hpostesting.presentation.testRight
import android.app.PendingIntent
import android.content.BroadcastReceiver
@@ -15,23 +15,24 @@ import android.os.IBinder
import android.util.Log
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.get
import androidx.lifecycle.ViewModelProvider
import com.example.hpos.R
import com.example.hpos.data.DataHolder
import com.example.hpos.data.constant.Constants
import com.example.hpos.databinding.ActivityTestRightBinding
import com.example.hpos.util.MyViewModelFactory
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialProber
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.ActivityTestRightBinding
@AndroidEntryPoint
class TestRightActivity : AppCompatActivity() {
private lateinit var binding: ActivityTestRightBinding
private lateinit var viewModel: TestRightViewModel
private val viewModel by viewModels<TestRightViewModel>()
private var myMenu: Menu? = null
private lateinit var mDriver: UsbSerialDriver
@@ -78,10 +79,6 @@ class TestRightActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
binding = ActivityTestRightBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel = ViewModelProvider(
this,
MyViewModelFactory()
)[TestRightViewModel::class.java]
setSupportActionBar(binding.myToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.testRight
package com.example.hpostesting.presentation.testRight
import android.os.Bundle
import android.os.Handler
@@ -10,17 +10,19 @@ import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import com.example.hpos.R
import com.example.hpos.data.DataHolder
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.constant.TestRightCommands
import com.example.hpos.data.model.ErrorMessage
import com.example.hpos.databinding.FragmentTestRightExpReferenceBinding
import com.example.hpos.presentation.UsbServiceListener
import com.example.hpos.presentation.utils.MyDialogListener
import com.example.hpos.presentation.utils.UIUtils
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.TestRightCommands
import com.example.hpostesting.data.model.ErrorMessage
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentTestRightExpReferenceBinding
@AndroidEntryPoint
class TestRightExpReference : Fragment() {
private lateinit var binding: FragmentTestRightExpReferenceBinding

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.testRight
package com.example.hpostesting.presentation.testRight
import android.content.Intent
import android.os.Bundle
@@ -10,19 +10,20 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import com.example.hpos.R
import com.example.hpos.data.DataHolder
import com.example.hpos.data.PreferenceUtility
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.constant.TestRightCommands
import com.example.hpos.data.model.ErrorMessage
import com.example.hpos.data.model.test.TestType
import com.example.hpos.databinding.FragmentTestRightExpSampleBinding
import com.example.hpos.presentation.MainActivity
import com.example.hpos.presentation.UsbServiceListener
import com.example.hpos.presentation.utils.MyDialogListener
import com.example.hpos.presentation.utils.UIUtils
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.TestRightCommands
import com.example.hpostesting.data.model.ErrorMessage
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.MainActivity
import com.example.hpostesting.presentation.UsbServiceListener
import com.example.hpostesting.presentation.utils.MyDialogListener
import com.example.hpostesting.presentation.utils.UIUtils
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentTestRightExpSampleBinding
@AndroidEntryPoint
class TestRightExpSample : Fragment() {
private lateinit var binding: FragmentTestRightExpSampleBinding
@@ -256,11 +257,9 @@ class TestRightExpSample : Fragment() {
// val fileNameCsv = prefixCsv + id + fileExtensionCsv
// NEW ------------------------------
viewModel.saveCsv(requireContext().applicationContext, viewModel.getCSVFileName())
viewModel.saveCsvForTesting(requireContext().applicationContext, viewModel.getDetailedCSVFileName())
// viewModel.saveCsvForTesting(requireContext().applicationContext, viewModel.getDetailedCSVFileName())
viewModel.saveLogWithPatient(requireContext().applicationContext, viewModel.getLogFileName())
}

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.testRight
package com.example.hpostesting.presentation.testRight
import android.content.Intent
import android.os.Bundle
@@ -9,32 +9,35 @@ import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import com.example.hpos.R
import com.example.hpos.data.DataHolder
import com.example.hpos.data.PreferenceUtility
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.model.test.TestRightResultType
import com.example.hpos.data.model.test.TestType
import com.example.hpos.databinding.FragmentTestRightResultsBinding
import com.example.hpos.presentation.dashboard.DashboardActivity
import com.example.hpos.util.MyUtils
import com.example.hpos.util.MyUtils.calculateAgeFromYOB
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.model.test.TestRightResultType
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.presentation.dashboard.DashboardActivity
import com.example.hpostesting.util.MyUtils.calculateAgeFromYOB
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentTestRightResultsBinding
import java.text.SimpleDateFormat
import java.util.Date
@AndroidEntryPoint
class TestRightResults : Fragment() {
private lateinit var binding: FragmentTestRightResultsBinding
private val viewModel: TestRightViewModel by activityViewModels()
private val TAG = "TestRightResults"
private var isOnline = false
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
binding = FragmentTestRightResultsBinding.inflate(inflater, container, false)
viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isNetworkAvailable ->
isOnline = isNetworkAvailable
}
return binding.root
}
@@ -43,14 +46,13 @@ class TestRightResults : Fragment() {
setupListeners()
updateResults()
viewModel.addResultTestToDb()
// This is to add files to the pending queue
viewModel.addFilesToQueue(requireContext())
// Uploading to cloud storage and deleting the from the pending queue when uploaded
if (MyUtils.isInternetConnected()) {
viewModel.addFilesToCloud(requireContext())
viewModel.fireBaseUpload.observe(viewLifecycleOwner) {
if (it == "Success") {
Toast.makeText(
requireContext(), "Test Results Upload Successfully", Toast.LENGTH_SHORT
).show()
}
binding.progressBar.visibility = View.GONE
}
}
@@ -68,35 +70,49 @@ class TestRightResults : Fragment() {
}
private fun updateResults() {
binding.tvName.text = getString(R.string.name_in_textview, viewModel.testDetails?.patientName)
binding.tvAge.text =
getString(R.string.age_in_textview, viewModel.testDetails?.patientAge?.calculateAgeFromYOB().toString())
if (viewModel.testDetails?.name == "" && viewModel.testDetails?.birthYear == "") {
binding.tvName.visibility = View.GONE
binding.tvAge.visibility = View.GONE
} else {
binding.tvName.text = getString(R.string.name_in_textview, viewModel.testDetails?.name)
binding.tvAge.text = getString(
R.string.age_in_textview,
viewModel.testDetails?.birthYear?.toInt()?.calculateAgeFromYOB().toString()
)
}
binding.tvId.text = getString(R.string.patient_id_in_tv, viewModel.testDetails?.patientID)
binding.tvId.text = getString(R.string.patient_id_in_tv, viewModel.testDetails?._id)
if (DataHolder.selectedTestType == TestType.SICKLECERT){
if (DataHolder.selectedTestType == TestType.SICKLECERT) {
when (viewModel.testDetails?.result) {
TestRightResultType.NORMAL -> {
binding.resultNormal.visibility = View.VISIBLE
}
TestRightResultType.SICKLECELLDISEASE -> {
binding.resultDisease.visibility = View.VISIBLE
}
TestRightResultType.SICKLECELLTRAIT -> {
binding.resultTrait.visibility = View.VISIBLE
}
TestRightResultType.POSITIVEBORDERLINE -> {
binding.resultPositiveBorderline.visibility = View.VISIBLE
binding.tvRecommended.visibility = View.VISIBLE
}
TestRightResultType.NEGATIVEBORDERLINE -> {
binding.resultNegativeBorderline.visibility = View.VISIBLE
binding.tvRecommended.visibility = View.VISIBLE
}
else -> {
// binding.resultUndefined.visibility = View.VISIBLE
Toast.makeText(requireContext().applicationContext, "Please Test Again", Toast.LENGTH_LONG).show()
Toast.makeText(
requireContext().applicationContext, "Please Test Again", Toast.LENGTH_LONG
).show()
moveToSamplePage()
}
}
@@ -106,20 +122,31 @@ class TestRightResults : Fragment() {
binding.resultDisease.visibility = View.VISIBLE
binding.resultDisease.text = "Positive"
}
TestRightResultType.NORMAL -> {
binding.resultNormal.visibility = View.VISIBLE
binding.resultNormal.text = "Negative"
}
else -> {
Toast.makeText(requireContext().applicationContext, "Please Test Again", Toast.LENGTH_LONG).show()
Toast.makeText(
requireContext().applicationContext, "Please Test Again", Toast.LENGTH_LONG
).show()
moveToSamplePage()
}
}
}
// if (viewModel.patientDetails.age < 5) {
// binding.tvRecommended.visibility = View.VISIBLE
// binding.tvRecommended.text = getString(R.string.recommended_age)
// }
if (isOnline) {
viewModel.uploadResultToDatabase(requireContext(), true)
binding.progressBar.visibility = View.VISIBLE
} else {
viewModel.uploadResultToDatabase(requireContext(), false)
Toast.makeText(
requireContext(),
"Internet not available, Test Data added to Local DB",
Toast.LENGTH_SHORT
).show()
}
}
@@ -127,8 +154,7 @@ class TestRightResults : Fragment() {
if (DataHolder.sampleReadCounter > Constants.MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE) {
DataHolder.sampleReadCounter = 0
DataHolder.isReferenceTaken = false
parentFragmentManager.beginTransaction()
.replace(R.id.fl_main, TestRightExpReference())
parentFragmentManager.beginTransaction().replace(R.id.fl_main, TestRightExpReference())
.commit()
} else {
parentFragmentManager.beginTransaction().replace(R.id.fl_main, TestRightExpSample())
@@ -144,55 +170,6 @@ class TestRightResults : Fragment() {
viewModel.saveLog(requireContext().applicationContext, fileName)
// if (!DataHolder.isAppFolderCreated) {
// val folderPath = MyUtils.createAppFolder(requireContext().applicationContext)
// if (folderPath != null) {
// DataHolder.isAppFolderCreated = true
// DataHolder.appFolderPath = folderPath
// viewModel.saveLog(DataHolder.appFolderPath, fileName)
// }
// } else {
// viewModel.saveLog(DataHolder.appFolderPath, fileName)
// }
}
// private fun saveCsv() {
// Log.d(TAG, "saveCsv() called")
//
// val sdfDate = SimpleDateFormat("ddMMyyyy HHmmss")
// val fileName: String = sdfDate.format(Date()) + ".csv"
//
// if (!DataHolder.isAppFolderCreated) {
// val folderPath = MyUtils.createAppFolder(requireContext().applicationContext)
// if (folderPath != null) {
// DataHolder.isAppFolderCreated = true
// DataHolder.appFolderPath = folderPath
// viewModel.saveCsv(DataHolder.appFolderPath, fileName)
//
// viewModel.saveCsvForTesting(DataHolder.appFolderPath, "testing$fileName")
// }
// } else {
// viewModel.saveCsv(DataHolder.appFolderPath, fileName)
//
// viewModel.saveCsvForTesting(DataHolder.appFolderPath, "testing$fileName")
// }
//
// }
private fun saveCsv() {
Log.d(TAG, "saveCsv() called")
// val sdfDate = SimpleDateFormat("ddMMyyyy HHmmss")
// val fileName: String = sdfDate.format(Date()) + ".csv"
val prefix = "HPOSSC_${DataHolder.deviceSerialNumber}_"
val fileExtension = ".csv"
val fileName = PreferenceUtility.generateId(requireContext(), prefix) + fileExtension
viewModel.saveCsv(requireContext().applicationContext, fileName)
viewModel.saveCsvForTesting(requireContext().applicationContext, "testing$fileName")
}
}

View File

@@ -1,56 +1,67 @@
package com.example.hpos.presentation.testRight
package com.example.hpostesting.presentation.testRight
import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.hpos.data.DataHolder
import com.example.hpos.data.repository.DatabaseRepository
import com.example.hpos.data.model.Response
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.model.CalculationVariableForTest
import com.example.hpos.data.model.ErrorMessage
import com.example.hpos.data.model.PendingUploads
import com.example.hpos.data.model.test.Status
import com.example.hpos.data.model.test.TestRightCalculationData
import com.example.hpos.data.model.test.TestRightDeviceConstants
import com.example.hpos.data.model.test.TestType
import com.example.hpos.domain.ResultCalculationWithMaxImpl
import com.example.hpos.domain.SaveRawData
import com.example.hpos.domain.SaveRawDataTest
import com.example.hpos.domain.SickleFindResultCaluculationWithMaxImpl
import com.example.hpos.domain.TestRightResultCalculation
import com.example.hpos.util.MyUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import com.example.hpostesting.data.DataHolder
import com.example.hpostesting.data.NetworkStatusLiveData
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.dao.UserDao
import com.example.hpostesting.data.model.CalculationVariableForTest
import com.example.hpostesting.data.model.ErrorMessage
import com.example.hpostesting.data.model.Response
import com.example.hpostesting.data.model.patient.UserData
import com.example.hpostesting.data.model.test.TestRightCalculationData
import com.example.hpostesting.data.model.test.TestRightDeviceConstants
import com.example.hpostesting.data.model.test.TestType
import com.example.hpostesting.data.repository.DatabaseRepository
import com.example.hpostesting.domain.ResultCalculationWithMaxImpl
import com.example.hpostesting.domain.SaveRawData
import com.example.hpostesting.domain.SaveRawDataTest
import com.example.hpostesting.domain.SickleFindResultCaluculationWithMaxImpl
import com.example.hpostesting.domain.TestRightResultCalculation
import com.example.hpostesting.util.MyUtils
import com.google.firebase.storage.FirebaseStorage
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await
import java.io.File
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import javax.inject.Inject
import kotlin.math.log10
import kotlin.math.pow
class TestRightViewModel(
@HiltViewModel
class TestRightViewModel @Inject constructor(
private val saveRawData: SaveRawData,
private val saveRawDataTest: SaveRawDataTest,
private val repository: DatabaseRepository
private val repository: DatabaseRepository,
private val userDao: UserDao,
context: Context
) : ViewModel() {
private val TAG = "TestRightViewModel"
var isServiceConnected = false
val progressBar = MutableLiveData(false)
// val errorTriggered = MutableLiveData<String>("")
val errorTriggered = MutableLiveData<ErrorMessage>()
var numberOfSampleRun = 0
// lateinit var patientDetails: PatientData
val fireBaseUpload = MutableLiveData<String>()
val testDetails = DataHolder.selectedTest
// var deviceConstant: TestRightDeviceConstants? = null
private val _networkStatusLiveData = NetworkStatusLiveData(context)
val networkStatusLiveData: LiveData<Boolean>
get() = _networkStatusLiveData
val allUserData = userDao.getAll()
private lateinit var calculationData: TestRightCalculationData
/* (For exp sample) Contains pixel no. -> Intensity of light falling on that pixel */
@@ -79,8 +90,7 @@ class TestRightViewModel(
// "Error 201: In processing the data from device"
errorTriggered.postValue(
ErrorMessage(
"Error 201: In processing the data from device",
Constants.ERROR_NORMAL
"Error 201: In processing the data from device", Constants.ERROR_NORMAL
)
)
}
@@ -89,8 +99,7 @@ class TestRightViewModel(
// "Error 202: Unable to fetch data from device."
errorTriggered.postValue(
ErrorMessage(
"Error 202: Unable to fetch data from device.",
Constants.ERROR_NORMAL
"Error 202: Unable to fetch data from device.", Constants.ERROR_NORMAL
)
)
}
@@ -103,13 +112,9 @@ class TestRightViewModel(
if (DataHolder.deviceConstant != null) {
for (x in 1..Constants.TEST_RIGHT_TOTAL_PIXEL) {
// val index = x - 1
val wavelength: Double =
(DataHolder.deviceConstant!!.a.toDouble() * (x.toDouble()
.pow((3).toDouble()))) +
(DataHolder.deviceConstant!!.b.toDouble() * (x.toDouble()
.pow((2).toDouble()))) +
(DataHolder.deviceConstant!!.c.toDouble() * x) +
(DataHolder.deviceConstant!!.d.toDouble())
val wavelength: Double = (DataHolder.deviceConstant!!.a.toDouble() * (x.toDouble()
.pow((3).toDouble()))) + (DataHolder.deviceConstant!!.b.toDouble() * (x.toDouble()
.pow((2).toDouble()))) + (DataHolder.deviceConstant!!.c.toDouble() * x) + (DataHolder.deviceConstant!!.d.toDouble())
DataHolder.wavelengthToPixelArray.add(wavelength)
}
@@ -118,8 +123,7 @@ class TestRightViewModel(
// "Error 203: Unable to fetch data from device."
errorTriggered.postValue(
ErrorMessage(
"Error 203: Unable to fetch data from device.",
Constants.ERROR_NORMAL
"Error 203: Unable to fetch data from device.", Constants.ERROR_NORMAL
)
)
@@ -136,22 +140,17 @@ class TestRightViewModel(
val listOfString = fullString.split("\n")
for (line in listOfString) {
if ("Buf" in line) {
/* Removing trailing spaces and "Buf" from the string then taking lhs & rhs of ':' */
val numbers = line.trim()
.substring(3).split(":")
if ("Buf" in line) {/* Removing trailing spaces and "Buf" from the string then taking lhs & rhs of ':' */
val numbers = line.trim().substring(3).split(":")
if (numbers.size >= 2) {
if (isReference)
DataHolder.intensityReferenceArray.add(numbers[1].toDouble())
else
intensitySampleArray.add(numbers[1].toDouble())
if (isReference) DataHolder.intensityReferenceArray.add(numbers[1].toDouble())
else intensitySampleArray.add(numbers[1].toDouble())
} else {
// "Error 204: Unable to fetch data from device."
errorTriggered.postValue(
ErrorMessage(
"Error 204: Unable to fetch data from device.",
Constants.ERROR_NORMAL
"Error 204: Unable to fetch data from device.", Constants.ERROR_NORMAL
)
)
@@ -265,7 +264,7 @@ class TestRightViewModel(
testDetails?.result = calculationData.result
testDetails?.resultRatio = calculationData.ratioValue
testDetails?.testStatus = Status.COMPLETED
testDetails?.testStatus = true
}
@@ -275,7 +274,7 @@ class TestRightViewModel(
SickleFindResultCaluculationWithMaxImpl()
calculationData = resultCalculation.getResults(wavelengthToAbsorbance)
testDetails?.result = calculationData.result
testDetails?.testStatus = Status.COMPLETED
testDetails?.testStatus = true
}
@@ -369,10 +368,7 @@ class TestRightViewModel(
if (DataHolder.isAppFolderCreated) {
// SaveRawData().saveLogWithPatientData(
saveRawData.saveLogWithPatientData(
folderPath!!,
fileName,
calculationData,
testDetails
folderPath!!, fileName, calculationData, testDetails
)
} else {
folderPath = MyUtils.createAppFolder(appContext)
@@ -381,10 +377,7 @@ class TestRightViewModel(
DataHolder.appFolderPath = folderPath
// SaveRawData().saveLogWithPatientData(
saveRawData.saveLogWithPatientData(
folderPath,
fileName,
calculationData,
testDetails
folderPath, fileName, calculationData, testDetails
)
} else {
// errorTriggered.postValue("Unable to save Log, Please try again")
@@ -427,129 +420,112 @@ class TestRightViewModel(
}
fun getCSVFileName(): String {
val prefixCsv: String = if (DataHolder.selectedTestType == TestType.SICKLECERT)
"HPOSSC_${testDetails?.testID}"
else
"HPOSSF_${testDetails?.testID}"
val prefixCsv: String =
if (DataHolder.selectedTestType == TestType.SICKLECERT) "HPOSSC_${testDetails?._id}"
else "HPOSSF_${testDetails?._id}"
val fileExtensionCsv = ".csv"
return prefixCsv + fileExtensionCsv
}
fun getDetailedCSVFileName(): String {
return "detailed_" + getCSVFileName()
}
fun getLogFileName(): String {
val prefixTxt = "log_${testDetails?.testID}"
val prefixTxt = "log_${testDetails?._id}"
val fileExtensionTxt = ".txt"
return prefixTxt + fileExtensionTxt
}
fun addResultTestToDb() {
private fun addResultTestToDb() {
testDetails?.location = DataHolder.location
testDetails?.testTime = Calendar.getInstance().time.toString()
viewModelScope.launch {
testDetails!!.uploadTime = Calendar.getInstance().time
repository.addTestToDatabase(testDetails)
testDetails!!.uploadTime = Calendar.getInstance().time.toString()
when (repository.addTestToDatabase(testDetails)) {
is Response.Success -> {
fireBaseUpload.postValue("Success")
}
else -> {}
}
}
}
fun addFilesToQueue(context: Context) {
viewModelScope.launch {
val csvFilePath = MyUtils.getAppFolderPath(context) + getCSVFileName()
val pendingId = getCSVFileName().split(".")[0]
repository.addToPendingQueue(
PendingUploads(
pendingId,
DataHolder.mobileUniqueId!!,
testDetails!!.patientID,
csvFilePath,
Calendar.getInstance().time
)
)
}
viewModelScope.launch {
val detailedCsvFilePath = MyUtils.getAppFolderPath(context) + getDetailedCSVFileName()
val pendingId = getDetailedCSVFileName().split(".")[0]
repository.addToPendingQueue(
PendingUploads(
pendingId,
DataHolder.mobileUniqueId!!,
testDetails!!.patientID,
detailedCsvFilePath,
Calendar.getInstance().time
)
)
}
viewModelScope.launch {
val logTxtFilePath = MyUtils.getAppFolderPath(context) + getLogFileName()
val pendingId = getLogFileName().split(".")[0]
repository.addToPendingQueue(
PendingUploads(
pendingId,
DataHolder.mobileUniqueId!!,
testDetails!!.patientID,
logTxtFilePath,
Calendar.getInstance().time
)
)
fun uploadResultToDatabase(context: Context, isOnline: Boolean) = viewModelScope.launch {
val csvFilePath = MyUtils.getAppFolderPath(context) + getCSVFileName()
val logTxtFilePath = MyUtils.getAppFolderPath(context) + getLogFileName()
testDetails?.csvPath = csvFilePath
testDetails?.reportPath = logTxtFilePath
if (isOnline) {
val storageRef = FirebaseStorage.getInstance().reference
val storageTestDetailsRef = storageRef.child("${testDetails?._id}/")
try {
val csvFileUri = Uri.fromFile(File(csvFilePath))
val logTxtFileUri = Uri.fromFile(File(logTxtFilePath))
val csvUploadTask =
storageTestDetailsRef.child(csvFileUri.lastPathSegment!!).putFile(csvFileUri)
.await()
val logUploadTask = storageTestDetailsRef.child(logTxtFileUri.lastPathSegment!!)
.putFile(logTxtFileUri).await()
val csvUri = csvUploadTask.storage.downloadUrl.await().toString()
val logUri = logUploadTask.storage.downloadUrl.await().toString()
testDetails?.csvPath = csvUri
testDetails?.reportPath = logUri
addResultTestToDb()
} catch (exception: Exception) {
// Handle the exception appropriately (e.g., log the error, display an error message)
}
} else {
testDetails?.testTime = Calendar.getInstance().time.toString()
userDao.insertAll(testDetails!!)
}
}
fun addFilesToCloud(context: Context) {
GlobalScope.launch(Dispatchers.IO) {
val csvFilePath = MyUtils.getAppFolderPath(context) + getCSVFileName()
val fileName = getCSVFileName().split(".")[0]
val response = repository.uploadFileToStorage(testDetails!!.patientID, csvFilePath)
fun bulkUploadResultToDatabase(userData: UserData) = viewModelScope.launch {
val storageRef = FirebaseStorage.getInstance().reference
val storageTestDetailsRef = storageRef.child("${testDetails?._id}/")
try {
val csvFileUri = Uri.fromFile(File(userData.csvPath))
val logTxtFileUri = Uri.fromFile(File(userData.reportPath))
when (response) {
val csvUploadTask =
storageTestDetailsRef.child(csvFileUri.lastPathSegment!!).putFile(csvFileUri)
.await()
val logUploadTask =
storageTestDetailsRef.child(logTxtFileUri.lastPathSegment!!).putFile(logTxtFileUri)
.await()
val csvUri = csvUploadTask.storage.downloadUrl.await().toString()
val logUri = logUploadTask.storage.downloadUrl.await().toString()
userData.csvPath = csvUri
userData.reportPath = logUri
bulkAddResultTestToDb(userData)
} catch (exception: Exception) {
// Handle the exception appropriately (e.g., log the error, display an error message)
}
}
private fun bulkAddResultTestToDb(userData: UserData) {
userData.location = DataHolder.location
viewModelScope.launch {
userData.uploadTime = Calendar.getInstance().time.toString()
when (repository.addTestToDatabase(userData)) {
is Response.Success -> {
Log.d(TAG, "Uploaded $csvFilePath")
repository.removeFromPendingQueue(fileName)
}
is Response.Error -> {
Log.d(TAG, response.exception.toString())
fireBaseUpload.postValue("Success")
}
else -> {}
}
}
}
GlobalScope.launch(Dispatchers.IO) {
val detailedCsvFilePath =
MyUtils.getAppFolderPath(context) + getDetailedCSVFileName()
val fileName = getDetailedCSVFileName().split(".")[0]
val response =
repository.uploadFileToStorage(testDetails!!.patientID, detailedCsvFilePath)
when (response) {
is Response.Success -> {
Log.d(TAG, "Uploaded $detailedCsvFilePath")
repository.removeFromPendingQueue(fileName)
}
is Response.Error -> {
Log.d(TAG, response.exception.toString())
}
}
}
GlobalScope.launch(Dispatchers.IO) {
val logTxtFilePath = MyUtils.getAppFolderPath(context) + getLogFileName()
val fileName = getLogFileName().split(".")[0]
val response =
repository.uploadFileToStorage(testDetails!!.patientID, logTxtFilePath)
when (response) {
is Response.Success -> {
Log.d(TAG, "Uploaded $logTxtFilePath")
repository.removeFromPendingQueue(fileName)
}
is Response.Error -> {
Log.d(TAG, response.exception.toString())
}
}
}
fun deleteById(userId: String) = viewModelScope.launch {
userDao.deleteById(id = userId)
}

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.testRight
package com.example.hpostesting.presentation.testRight
import android.app.Service
import android.content.Intent
@@ -6,10 +6,9 @@ import android.hardware.usb.UsbDeviceConnection
import android.os.Binder
import android.os.IBinder
import android.util.Log
import com.example.hpos.data.DataHolder
import com.example.hpos.data.constant.Constants
import com.example.hpos.data.constant.TestRightCommands
import com.example.hpos.presentation.UsbServiceListener
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.TestRightCommands
import com.example.hpostesting.presentation.UsbServiceListener
import com.hoho.android.usbserial.driver.UsbSerialDriver
import com.hoho.android.usbserial.driver.UsbSerialPort
import com.hoho.android.usbserial.util.SerialInputOutputManager

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.utils
package com.example.hpostesting.presentation.utils
interface MyDialogListener {
fun onClickNegativeButton()

View File

@@ -1,4 +1,4 @@
package com.example.hpos.presentation.utils
package com.example.hpostesting.presentation.utils
import android.content.Context
import android.widget.Toast

View File

@@ -1,4 +1,4 @@
package com.example.hpos
package com.example.hpostesting
import java.text.SimpleDateFormat
import java.util.Date

View File

@@ -1,12 +1,11 @@
package com.example.hpos.util
package com.example.hpostesting.util
import android.content.Context
import android.os.Environment
import com.example.hpos.R
import com.example.hpos.data.model.patient.PatientDetails
import com.example.hpostesting.data.model.patient.PatientDetails
import `in`.sminnovations.hpostesting.R
import java.io.File
import java.io.IOException
import java.net.InetAddress
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="20dp"/>
<solid android:color="@color/white"/>
<stroke android:color="@color/gray"
android:width="1dp"/>
</shape>

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="@color/primary"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/primary" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM14,13v4h-4v-4H7l5,-5 5,5h-3z"/>
</vector>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="name=Inter&amp;weight=700"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs">
</font-family>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="name=Inter&amp;weight=500"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs">
</font-family>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="name=Inter&amp;weight=600"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs">
</font-family>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="Poppins">
</font-family>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="name=Poppins&amp;weight=500"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs">
</font-family>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="name=Poppins&amp;weight=600"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs">
</font-family>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="Roboto"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs">
</font-family>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="name=Roboto&amp;weight=500"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs">
</font-family>

View File

@@ -30,7 +30,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/my_toolbar" />
<com.google.android.material.card.MaterialCardView
<androidx.cardview.widget.CardView
android:id="@+id/cv_item1"
android:layout_width="128dp"
android:layout_height="128dp"
@@ -70,9 +70,9 @@
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.cardview.widget.CardView>
<com.google.android.material.card.MaterialCardView
<androidx.cardview.widget.CardView
android:id="@+id/cv_item2"
android:layout_width="128dp"
android:layout_height="128dp"
@@ -113,9 +113,9 @@
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.cardview.widget.CardView>
<com.google.android.material.card.MaterialCardView
<androidx.cardview.widget.CardView
android:id="@+id/cv_item3"
android:layout_width="128dp"
android:layout_height="128dp"
@@ -155,10 +155,10 @@
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.cardview.widget.CardView>
<com.google.android.material.card.MaterialCardView
<androidx.cardview.widget.CardView
android:id="@+id/cv_item4"
android:layout_width="128dp"
android:layout_height="128dp"
@@ -199,7 +199,7 @@
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,23 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/internetNotAvailableCL"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:visibility="gone"
android:padding="24dp">
<TextView
android:id="@+id/tv_title_no_internet"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/internet_not_available_please_enter_the_user_id_manually"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_name"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginHorizontal="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title_no_internet">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/userId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="18"
android:inputType="textCapCharacters"
android:hint="@string/user_id" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:text="@string/submit"
app:cornerRadius="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/internetAvailableCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
android:padding="24dp">
<TextView
android:id="@+id/tv_title"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:text="@string/list_of_patients"
android:text="@string/user_list"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/uploadData"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/upload_data"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/tv_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_title" />
<TextView
android:id="@+id/tv_not_available"
style="@style/title1_1"
@@ -32,43 +99,82 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
<androidx.cardview.widget.CardView
android:id="@+id/cardView4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="0dp"
app:layout_constraintTop_toBottomOf="@+id/tv_title"
tools:layout_editor_absoluteX="24dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.SearchView
android:id="@+id/search_product"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/edit_text_background"
android:inputType="text"
app:iconifiedByDefault="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<requestFocus />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="0dp"
android:orientation="horizontal"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cardView4">
<RadioButton
android:id="@+id/userIdRadioButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/user_id" />
<RadioButton
android:id="@+id/abhaIdRadioButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/abha_id"
app:layout_constraintTop_toBottomOf="@id/userIdRadioButton" />
<RadioButton
android:id="@+id/aadharIdRadioButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/aadhar_id"
app:layout_constraintTop_toBottomOf="@id/abhaIdRadioButton" />
</RadioGroup>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_order"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="16dp"
android:scrollbars="vertical"
app:layout_constraintBottom_toTopOf="@id/btn_add"
app:layout_constraintTop_toBottomOf="@id/tv_title"
tools:listitem="@layout/table_item" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:drawableLeft="@drawable/baseline_add_24"
android:text="@string/add"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:drawableLeft="@drawable/test_tube"
android:text="@string/test"
android:textColor="@color/white"
app:cornerRadius="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/radioGroup"
tools:listitem="@layout/user_item_view"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -253,7 +253,7 @@
app:layout_constraintTop_toBottomOf="@id/cv_sample_details" />
<TextView
style="@style/title3"
style="@style/title2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/home"
@@ -277,7 +277,7 @@
app:layout_constraintTop_toBottomOf="@id/cv_sample_details" />
<TextView
style="@style/title3"
style="@style/title2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/new_test"
@@ -289,8 +289,9 @@
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/gray"
android:layout_centerInParent="true"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/progressbar_drawable"

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:id="@+id/userCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:cardBackgroundColor="@color/primary_light"
app:cardCornerRadius="25dp"
app:cardElevation="0dp"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp">
<ImageView
android:id="@+id/userImage"
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/userName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_bold"
android:layout_marginTop="16dp"
android:gravity="center"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImage" />
<TextView
android:id="@+id/userId"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_bold"
android:layout_marginTop="16dp"
android:gravity="center"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userName" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

Some files were not shown because too many files have changed in this diff Show More