diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 21d4513..fba3db2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,6 +4,7 @@
+
diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/apiservice/RetrofitClient.java b/app/src/main/java/com/utopiaindustries/qualitychecker/apiservice/RetrofitClient.java
index f19158d..738ff01 100644
--- a/app/src/main/java/com/utopiaindustries/qualitychecker/apiservice/RetrofitClient.java
+++ b/app/src/main/java/com/utopiaindustries/qualitychecker/apiservice/RetrofitClient.java
@@ -3,6 +3,9 @@ package com.utopiaindustries.qualitychecker.apiservice;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
@@ -19,8 +22,15 @@ public class RetrofitClient {
.create();
if ( retrofit == null ) {
+ OkHttpClient okHttpClient = new OkHttpClient.Builder()
+ .connectTimeout(60, TimeUnit.SECONDS)
+ .readTimeout(60, TimeUnit.SECONDS)
+ .writeTimeout(60, TimeUnit.SECONDS)
+ .build();
+
retrofit = new Retrofit.Builder()
.baseUrl( BASE_URL )
+ .client( okHttpClient )
.addConverterFactory( GsonConverterFactory.create( gson ) )
.build();
}
diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/async/ImageProcessor.java b/app/src/main/java/com/utopiaindustries/qualitychecker/async/ImageProcessor.java
new file mode 100644
index 0000000..a41cc9e
--- /dev/null
+++ b/app/src/main/java/com/utopiaindustries/qualitychecker/async/ImageProcessor.java
@@ -0,0 +1,99 @@
+package com.utopiaindustries.qualitychecker.async;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class ImageProcessor {
+
+ private ExecutorService executorService;
+ private Handler backgroundHandler;
+ private Handler mainHandler;
+
+ public ImageProcessor() {
+ executorService = Executors.newSingleThreadExecutor();
+ HandlerThread handlerThread = new HandlerThread("ImageProcessorThread");
+ handlerThread.start();
+ backgroundHandler = new Handler(handlerThread.getLooper());
+ mainHandler = new Handler(Looper.getMainLooper());
+ }
+
+ public void compressImageFromUriAsync(final Context context, final Uri uri, final int maxSizeKB, final OnImageCompressedListener listener) {
+ backgroundHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ byte[] imageData = getBytesFromUri(context, uri);
+ if (imageData != null) {
+ final byte[] compressedData = compressImageToMaxSize(imageData, maxSizeKB);
+ mainHandler.post(() -> listener.onImageCompressed(compressedData));
+ } else {
+ mainHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ listener.onImageCompressed(null);
+ }
+ });
+ }
+ }
+ });
+ }
+
+ private byte[] getBytesFromUri(Context context, Uri uri) {
+ if (uri != null) {
+ try {
+ InputStream inputStream = context.getContentResolver().openInputStream(uri);
+ if (inputStream != null) {
+ ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = inputStream.read(buffer)) != -1) {
+ byteBuffer.write(buffer, 0, len);
+ }
+ inputStream.close();
+ return byteBuffer.toByteArray();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+ private byte[] compressImageToMaxSize(byte[] imageData, int maxSizeKB) {
+ int quality = 100; // Start with the highest quality
+ byte[] compressedBytes = compressImage(imageData, quality);
+ // Loop to reduce quality until the image is within the max size
+ while (compressedBytes.length > maxSizeKB * 1024 && quality > 0) {
+ quality -= 5;
+ compressedBytes = compressImage(imageData, quality);
+ }
+ return compressedBytes;
+ }
+
+ private byte[] compressImage(byte[] imageData, int quality) {
+ if (imageData != null && imageData.length > 0) {
+ Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
+ return outputStream.toByteArray();
+ }
+ return null;
+ }
+
+ public void shutdown() {
+ executorService.shutdown();
+ }
+
+ public interface OnImageCompressedListener {
+ void onImageCompressed(byte[] compressedData);
+ }
+}
diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/notification/NotificationHelper.java b/app/src/main/java/com/utopiaindustries/qualitychecker/notification/NotificationHelper.java
new file mode 100644
index 0000000..d8cc071
--- /dev/null
+++ b/app/src/main/java/com/utopiaindustries/qualitychecker/notification/NotificationHelper.java
@@ -0,0 +1,37 @@
+package com.utopiaindustries.qualitychecker.notification;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Build;
+import androidx.core.app.NotificationCompat;
+
+import com.utopiaindustries.qualitychecker.R;
+
+public class NotificationHelper {
+
+ private static final String CHANNEL_ID = "001122";
+ private static final String CHANNEL_NAME = "QA_App_Channel";
+ private static final String CHANNEL_DESCRIPTION = "Channel_for_qa_app";
+
+ public static void showNotification(Context context, String title, String message) {
+ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ // Create a notification channel for devices running Android Oreo (API 26) and higher
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
+ channel.setDescription(CHANNEL_DESCRIPTION);
+ notificationManager.createNotificationChannel(channel);
+ }
+
+ // Build the notification
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
+ .setSmallIcon(R.drawable.utopia_svg_logo) // Set your notification icon here
+ .setContentTitle(title)
+ .setContentText(message)
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT);
+
+ // Show the notification
+ notificationManager.notify(0, builder.build());
+ }
+}
diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/service/InspectionReportService.java b/app/src/main/java/com/utopiaindustries/qualitychecker/service/InspectionReportService.java
index 9ac00c3..a0e37cc 100644
--- a/app/src/main/java/com/utopiaindustries/qualitychecker/service/InspectionReportService.java
+++ b/app/src/main/java/com/utopiaindustries/qualitychecker/service/InspectionReportService.java
@@ -16,6 +16,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.logging.Handler;
import retrofit2.Call;
import retrofit2.Callback;
@@ -85,41 +86,85 @@ public class InspectionReportService {
this.reportResult = reportResult;
}
+ private void populateDefectsInBackground(InspectionReport inspectionReport) {
+ for (InspectionItemCheckPoint itemCp : inspectionReport.getItems().get(0).getCheckPoints()) {
+ List defectList = getInspectionItemDefects(itemCp);
+ itemCp.setDefects(defectList);
+ }
+ }
+
+
+ private void saveReportInBackground(final InspectionReport inspectionReport, final SaveReportCallback callback) {
+ // Post object
+ apiService.saveInspectionReport(inspectionReport).enqueue(
+ new Callback