From 30526b3dabc9be1748ac2182cef514500a71f45c Mon Sep 17 00:00:00 2001 From: saif Date: Mon, 3 Jun 2024 16:25:49 +0500 Subject: [PATCH] - bug fixed after testing --- app/src/main/AndroidManifest.xml | 1 + .../apiservice/RetrofitClient.java | 10 ++ .../qualitychecker/async/ImageProcessor.java | 99 ++++++++++++++++ .../notification/NotificationHelper.java | 37 ++++++ .../service/InspectionReportService.java | 101 +++++++++++----- .../ui/fragments/SecondStepFragment.java | 111 ++++++++++-------- .../ui/fragments/ThirdStepFragment.java | 31 ++++- .../main/res/layout/save_report_dialog.xml | 4 +- 8 files changed, 308 insertions(+), 86 deletions(-) create mode 100644 app/src/main/java/com/utopiaindustries/qualitychecker/async/ImageProcessor.java create mode 100644 app/src/main/java/com/utopiaindustries/qualitychecker/notification/NotificationHelper.java 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>() { + @Override + public void onResponse(Call> call, + Response> response) { + if (response.isSuccessful()) { + System.out.println(response.body()); + if (response.body().get("result").equalsIgnoreCase("success")) { + callback.onSuccess(); + } else { + callback.onFailure(new Exception("Error on submitting report")); + } + } else { + callback.onFailure(new Exception("API call failed with status code: " + response.code())); + } + } + + @Override + public void onFailure(Call> call, Throwable t) { + System.out.println(t); + callback.onFailure(t); + } + } + ); + } + + public void saveReport(InspectionReport inspectionReport , SaveReportCallback callback){ if( Objects.nonNull( inspectionReport ) && inspectionReport.getItems().get(0).getSku() != null && inspectionReport.getItems() != null && ! inspectionReport.getItems().isEmpty() && ! inspectionReport.getItems().get(0).getCheckPoints().isEmpty() ){ + new Thread(() -> { + populateDefectsInBackground( inspectionReport ); + //post report + saveReportInBackground( inspectionReport , callback ); + }).start(); + + // populate defects in cp - for( InspectionItemCheckPoint itemCp : inspectionReport.getItems().get(0).getCheckPoints() ){ - List defectList = getInspectionItemDefects(itemCp); - itemCp.setDefects( defectList ); - } +// for( InspectionItemCheckPoint itemCp : inspectionReport.getItems().get(0).getCheckPoints() ){ +// List defectList = getInspectionItemDefects(itemCp); +// itemCp.setDefects( defectList ); +// } // post object - apiService.saveInspectionReport( inspectionReport ).enqueue( - new Callback>() { - @Override - public void onResponse(Call> call, - Response> response) { - if ( response.isSuccessful() ) { - System.out.println( response.body() ); - if( response.body().get("result").equalsIgnoreCase("success")){ - callback.onSuccess(); - } - else { - callback.onFailure(new Exception( "Error on submitting report" )); - } - } else { - callback.onFailure(new Exception("API call failed with status code: " + response.code())); - } - } - @Override - public void onFailure(Call> call, Throwable t) { - System.out.println( t ); - callback.onFailure( t ); - } - } - ); +// apiService.saveInspectionReport( inspectionReport ).enqueue( +// new Callback>() { +// @Override +// public void onResponse(Call> call, +// Response> response) { +// if ( response.isSuccessful() ) { +// System.out.println( response.body() ); +// if( response.body().get("result").equalsIgnoreCase("success")){ +// callback.onSuccess(); +// } +// else { +// callback.onFailure(new Exception( "Error on submitting report" )); +// } +// } else { +// callback.onFailure(new Exception("API call failed with status code: " + response.code())); +// } +// } +// @Override +// public void onFailure(Call> call, Throwable t) { +// System.out.println( t ); +// callback.onFailure( t ); +// } +// } +// ); } else { callback.onFailure( new Exception("Please Fill the required Fields..") ); } diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/SecondStepFragment.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/SecondStepFragment.java index ca8c13a..04cf487 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/SecondStepFragment.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/SecondStepFragment.java @@ -32,6 +32,7 @@ import com.bumptech.glide.Glide; import com.utopiaindustries.qualitychecker.R; import com.utopiaindustries.qualitychecker.apiservice.ApiService; import com.utopiaindustries.qualitychecker.apiservice.ApiServiceFactory; +import com.utopiaindustries.qualitychecker.async.ImageProcessor; import com.utopiaindustries.qualitychecker.models.InspectionCheckPoint; import com.utopiaindustries.qualitychecker.models.InspectionDefect; import com.utopiaindustries.qualitychecker.service.InspectionReportService; @@ -44,6 +45,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Future; public class SecondStepFragment extends Fragment @@ -133,63 +135,72 @@ public class SecondStepFragment extends Fragment public void onImagePickerResult(int requestCode, int resultCode, Intent data) { if ( resultCode == RESULT_OK && data != null ) { try { + ImageProcessor imageProcessor = new ImageProcessor(); Uri selectedImageUri = data.getData(); assert selectedImageUri != null; String imagePath = selectedImageUri.getPath(); - store.getReport().getItems().get( 0 ).getCheckPoints().get( requestCode ).setImagePath( imagePath ); - store.getReport().getItems().get( 0 ).getCheckPoints().get( requestCode ).setFile( - compressImageToMaxSize( getBytesFromUri( getContext(), selectedImageUri ), 200 ) - ); - adapter.notifyItemChanged( requestCode ); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } + store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setImagePath(imagePath); - 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); + imageProcessor.compressImageFromUriAsync(getContext(), selectedImageUri, 200, compressedData -> { + if (compressedData != null) { + store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setFile(compressedData); + } else { + store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setFile(null); } - inputStream.close(); - return byteBuffer.toByteArray(); - } - } catch (IOException e) { - System.out.println(e.getMessage()); - return null; + adapter.notifyItemChanged( requestCode ); + }); + } catch ( Exception e ){ + e.printStackTrace(); } +// store.getReport().getItems().get( 0 ).getCheckPoints().get( requestCode ).setFile( +// compressImageToMaxSize( getBytesFromUri( getContext(), selectedImageUri ), 200 ) + // ); } - return null; } - public byte[] compressImageToMaxSize(byte[] imageData, - int maxSizeKB) { - int quality = 100; // Start with 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; - } +// 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) { +// System.out.println(e.getMessage()); +// return null; +// } +// } +// return null; +// } +// +// public byte[] compressImageToMaxSize(byte[] imageData, +// int maxSizeKB) { +// int quality = 100; // Start with 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; +// } } diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/ThirdStepFragment.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/ThirdStepFragment.java index ee7125b..5fa5e2a 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/ThirdStepFragment.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/ThirdStepFragment.java @@ -32,11 +32,11 @@ import com.utopiaindustries.qualitychecker.R; import com.utopiaindustries.qualitychecker.apiservice.ApiService; import com.utopiaindustries.qualitychecker.apiservice.ApiServiceFactory; import com.utopiaindustries.qualitychecker.models.InspectionItemCheckPoint; -import com.utopiaindustries.qualitychecker.models.InspectionItemDefect; import com.utopiaindustries.qualitychecker.models.InspectionItemDimension; import com.utopiaindustries.qualitychecker.models.InspectionReport; import com.utopiaindustries.qualitychecker.models.SaveReportCallback; import com.utopiaindustries.qualitychecker.models.VoiceOfCustomer; +import com.utopiaindustries.qualitychecker.notification.NotificationHelper; import com.utopiaindustries.qualitychecker.service.InspectionReportService; import com.utopiaindustries.qualitychecker.store.Store; import com.utopiaindustries.qualitychecker.ui.adapter.DimensionAdapter; @@ -145,22 +145,33 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener View dialogView = inflater.inflate( R.layout.save_report_dialog, null); // progress bar ProgressBar progressBar = dialogView.findViewById( R.id.save_report_progress ); + AlertDialog.Builder builder = new AlertDialog.Builder( Objects.requireNonNull(getContext()) ); builder.setView( dialogView ) .setTitle("So you want to save report?") .setPositiveButton( "Save",(dialog, which) -> { progressBar.setVisibility( View.VISIBLE ); + NotificationHelper.showNotification( Objects.requireNonNull(getContext()), + "Utopia QA App", + "Report is uploading keep patience..."); inspectionReportService.saveReport(store.getReport(), new SaveReportCallback() { @Override public void onSuccess() { Toast.makeText( getContext(), "Report saved Successfully", Toast.LENGTH_LONG ).show(); progressBar.setVisibility( View.INVISIBLE ); Objects.requireNonNull( getActivity() ).finish(); + NotificationHelper.showNotification( Objects.requireNonNull(getContext()), + "Utopia QA App", + "Report is uploaded successfully"); + } @Override public void onFailure(Throwable throwable) { Toast.makeText( getContext(), throwable.getMessage(), Toast.LENGTH_LONG ).show(); progressBar.setVisibility( View.INVISIBLE ); + NotificationHelper.showNotification( Objects.requireNonNull(getContext()), + "Utopia QA App", + "Error in uploading report"); } }); }) @@ -170,7 +181,9 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener }); // Show the dialog AlertDialog dialog = builder.create(); + progressBar.setVisibility( View.GONE ); dialog.show(); + } private void openDimensionDialog() { @@ -265,10 +278,18 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener int major = 0; int crirical = 0; for (InspectionItemCheckPoint itemCp : inspectionReport.getItems().get(0).getCheckPoints()) { - for( String status : itemCp.getDefectSeverites() ){ - if( status.equalsIgnoreCase("minor") ) minor++; - if( status.equalsIgnoreCase("major") ) major++; - if( status.equalsIgnoreCase("critical") ) crirical++; + for( int i = 0 ; i< itemCp.getDefectSeverites().size() ; i++ ){ + String status = itemCp.getDefectSeverites().get( i ); + float quantity = itemCp.getQuantities().get(i); + if( status.equalsIgnoreCase("minor") ){ + minor += (int) quantity; + } ; + if( status.equalsIgnoreCase("major") ){ + major += (int) quantity; + } + if( status.equalsIgnoreCase("critical") ) { + crirical += (int) quantity; + } } } diff --git a/app/src/main/res/layout/save_report_dialog.xml b/app/src/main/res/layout/save_report_dialog.xml index 618eb80..4065f35 100644 --- a/app/src/main/res/layout/save_report_dialog.xml +++ b/app/src/main/res/layout/save_report_dialog.xml @@ -7,9 +7,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="16dp" - android:id="@+id/save_report_progress" - android:visibility="invisible" - > + android:id="@+id/save_report_progress">