- bug fixed after testing

main
saif 2024-06-03 16:25:49 +05:00
parent 360ce2dd24
commit 30526b3dab
8 changed files with 308 additions and 86 deletions

View File

@ -4,6 +4,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <!-- If your app needs to access network state --> <uses-permission android:name="android.permission.INTERNET" /> <!-- If your app needs to access network state -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.CAMERA"/>

View File

@ -3,6 +3,9 @@ package com.utopiaindustries.qualitychecker.apiservice;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.gson.GsonConverterFactory;
@ -19,8 +22,15 @@ public class RetrofitClient {
.create(); .create();
if ( retrofit == null ) { 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() retrofit = new Retrofit.Builder()
.baseUrl( BASE_URL ) .baseUrl( BASE_URL )
.client( okHttpClient )
.addConverterFactory( GsonConverterFactory.create( gson ) ) .addConverterFactory( GsonConverterFactory.create( gson ) )
.build(); .build();
} }

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -16,6 +16,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.logging.Handler;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -85,41 +86,85 @@ public class InspectionReportService {
this.reportResult = reportResult; this.reportResult = reportResult;
} }
private void populateDefectsInBackground(InspectionReport inspectionReport) {
for (InspectionItemCheckPoint itemCp : inspectionReport.getItems().get(0).getCheckPoints()) {
List<InspectionItemDefect> defectList = getInspectionItemDefects(itemCp);
itemCp.setDefects(defectList);
}
}
private void saveReportInBackground(final InspectionReport inspectionReport, final SaveReportCallback callback) {
// Post object
apiService.saveInspectionReport(inspectionReport).enqueue(
new Callback<Map<String, String>>() {
@Override
public void onResponse(Call<Map<String, String>> call,
Response<Map<String, String>> 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<Map<String, String>> call, Throwable t) {
System.out.println(t);
callback.onFailure(t);
}
}
);
}
public void saveReport(InspectionReport inspectionReport , SaveReportCallback callback){ public void saveReport(InspectionReport inspectionReport , SaveReportCallback callback){
if( Objects.nonNull( inspectionReport ) && inspectionReport.getItems().get(0).getSku() != null && inspectionReport.getItems() != null && if( Objects.nonNull( inspectionReport ) && inspectionReport.getItems().get(0).getSku() != null && inspectionReport.getItems() != null &&
! inspectionReport.getItems().isEmpty() && ! inspectionReport.getItems().isEmpty() &&
! inspectionReport.getItems().get(0).getCheckPoints().isEmpty() ){ ! inspectionReport.getItems().get(0).getCheckPoints().isEmpty() ){
new Thread(() -> {
populateDefectsInBackground( inspectionReport );
//post report
saveReportInBackground( inspectionReport , callback );
}).start();
// populate defects in cp // populate defects in cp
for( InspectionItemCheckPoint itemCp : inspectionReport.getItems().get(0).getCheckPoints() ){ // for( InspectionItemCheckPoint itemCp : inspectionReport.getItems().get(0).getCheckPoints() ){
List<InspectionItemDefect> defectList = getInspectionItemDefects(itemCp); // List<InspectionItemDefect> defectList = getInspectionItemDefects(itemCp);
itemCp.setDefects( defectList ); // itemCp.setDefects( defectList );
} // }
// post object // post object
apiService.saveInspectionReport( inspectionReport ).enqueue( // apiService.saveInspectionReport( inspectionReport ).enqueue(
new Callback<Map<String,String>>() { // new Callback<Map<String,String>>() {
@Override // @Override
public void onResponse(Call<Map<String,String>> call, // public void onResponse(Call<Map<String,String>> call,
Response<Map<String,String>> response) { // Response<Map<String,String>> response) {
if ( response.isSuccessful() ) { // if ( response.isSuccessful() ) {
System.out.println( response.body() ); // System.out.println( response.body() );
if( response.body().get("result").equalsIgnoreCase("success")){ // if( response.body().get("result").equalsIgnoreCase("success")){
callback.onSuccess(); // callback.onSuccess();
} // }
else { // else {
callback.onFailure(new Exception( "Error on submitting report" )); // callback.onFailure(new Exception( "Error on submitting report" ));
} // }
} else { // } else {
callback.onFailure(new Exception("API call failed with status code: " + response.code())); // callback.onFailure(new Exception("API call failed with status code: " + response.code()));
} // }
} // }
@Override // @Override
public void onFailure(Call<Map<String,String>> call, Throwable t) { // public void onFailure(Call<Map<String,String>> call, Throwable t) {
System.out.println( t ); // System.out.println( t );
callback.onFailure( t ); // callback.onFailure( t );
} // }
} // }
); // );
} else { } else {
callback.onFailure( new Exception("Please Fill the required Fields..") ); callback.onFailure( new Exception("Please Fill the required Fields..") );
} }

View File

@ -32,6 +32,7 @@ import com.bumptech.glide.Glide;
import com.utopiaindustries.qualitychecker.R; import com.utopiaindustries.qualitychecker.R;
import com.utopiaindustries.qualitychecker.apiservice.ApiService; import com.utopiaindustries.qualitychecker.apiservice.ApiService;
import com.utopiaindustries.qualitychecker.apiservice.ApiServiceFactory; import com.utopiaindustries.qualitychecker.apiservice.ApiServiceFactory;
import com.utopiaindustries.qualitychecker.async.ImageProcessor;
import com.utopiaindustries.qualitychecker.models.InspectionCheckPoint; import com.utopiaindustries.qualitychecker.models.InspectionCheckPoint;
import com.utopiaindustries.qualitychecker.models.InspectionDefect; import com.utopiaindustries.qualitychecker.models.InspectionDefect;
import com.utopiaindustries.qualitychecker.service.InspectionReportService; import com.utopiaindustries.qualitychecker.service.InspectionReportService;
@ -44,6 +45,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Future;
public class SecondStepFragment extends Fragment public class SecondStepFragment extends Fragment
@ -133,63 +135,72 @@ public class SecondStepFragment extends Fragment
public void onImagePickerResult(int requestCode, int resultCode, Intent data) { public void onImagePickerResult(int requestCode, int resultCode, Intent data) {
if ( resultCode == RESULT_OK && data != null ) { if ( resultCode == RESULT_OK && data != null ) {
try { try {
ImageProcessor imageProcessor = new ImageProcessor();
Uri selectedImageUri = data.getData(); Uri selectedImageUri = data.getData();
assert selectedImageUri != null; assert selectedImageUri != null;
String imagePath = selectedImageUri.getPath(); String imagePath = selectedImageUri.getPath();
store.getReport().getItems().get( 0 ).getCheckPoints().get( requestCode ).setImagePath( imagePath ); 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);
}
}
}
private byte[] getBytesFromUri(Context context, Uri uri) { imageProcessor.compressImageFromUriAsync(getContext(), selectedImageUri, 200, compressedData -> {
if( uri != null ) { if (compressedData != null) {
try { store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setFile(compressedData);
InputStream inputStream = context.getContentResolver().openInputStream(uri); } else {
if (inputStream != null) { store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setFile(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(); adapter.notifyItemChanged( requestCode );
return byteBuffer.toByteArray(); });
} } catch ( Exception e ){
} catch (IOException e) { e.printStackTrace();
System.out.println(e.getMessage());
return null;
} }
// store.getReport().getItems().get( 0 ).getCheckPoints().get( requestCode ).setFile(
// compressImageToMaxSize( getBytesFromUri( getContext(), selectedImageUri ), 200 )
// );
} }
return null;
} }
public byte[] compressImageToMaxSize(byte[] imageData, // private byte[] getBytesFromUri(Context context, Uri uri) {
int maxSizeKB) { // if( uri != null ) {
int quality = 100; // Start with highest quality // try {
byte[] compressedBytes = compressImage(imageData, quality); // InputStream inputStream = context.getContentResolver().openInputStream(uri);
// Loop to reduce quality until the image is within the max size // if (inputStream != null) {
while (compressedBytes.length > maxSizeKB * 1024 && quality > 0) { // ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
quality -= 5; // byte[] buffer = new byte[1024];
compressedBytes = compressImage(imageData, quality); // int len;
} // while ((len = inputStream.read(buffer)) != -1) {
// byteBuffer.write(buffer, 0, len);
return compressedBytes; // }
} // inputStream.close();
// return byteBuffer.toByteArray();
private byte[] compressImage(byte[] imageData, // }
int quality) { // } catch (IOException e) {
if( imageData != null && imageData.length > 0 ) { // System.out.println(e.getMessage());
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length); // return null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // }
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream); // }
return outputStream.toByteArray(); // 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;
// }
} }

View File

@ -32,11 +32,11 @@ import com.utopiaindustries.qualitychecker.R;
import com.utopiaindustries.qualitychecker.apiservice.ApiService; import com.utopiaindustries.qualitychecker.apiservice.ApiService;
import com.utopiaindustries.qualitychecker.apiservice.ApiServiceFactory; import com.utopiaindustries.qualitychecker.apiservice.ApiServiceFactory;
import com.utopiaindustries.qualitychecker.models.InspectionItemCheckPoint; import com.utopiaindustries.qualitychecker.models.InspectionItemCheckPoint;
import com.utopiaindustries.qualitychecker.models.InspectionItemDefect;
import com.utopiaindustries.qualitychecker.models.InspectionItemDimension; import com.utopiaindustries.qualitychecker.models.InspectionItemDimension;
import com.utopiaindustries.qualitychecker.models.InspectionReport; import com.utopiaindustries.qualitychecker.models.InspectionReport;
import com.utopiaindustries.qualitychecker.models.SaveReportCallback; import com.utopiaindustries.qualitychecker.models.SaveReportCallback;
import com.utopiaindustries.qualitychecker.models.VoiceOfCustomer; import com.utopiaindustries.qualitychecker.models.VoiceOfCustomer;
import com.utopiaindustries.qualitychecker.notification.NotificationHelper;
import com.utopiaindustries.qualitychecker.service.InspectionReportService; import com.utopiaindustries.qualitychecker.service.InspectionReportService;
import com.utopiaindustries.qualitychecker.store.Store; import com.utopiaindustries.qualitychecker.store.Store;
import com.utopiaindustries.qualitychecker.ui.adapter.DimensionAdapter; 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); View dialogView = inflater.inflate( R.layout.save_report_dialog, null);
// progress bar // progress bar
ProgressBar progressBar = dialogView.findViewById( R.id.save_report_progress ); ProgressBar progressBar = dialogView.findViewById( R.id.save_report_progress );
AlertDialog.Builder builder = new AlertDialog.Builder( Objects.requireNonNull(getContext()) ); AlertDialog.Builder builder = new AlertDialog.Builder( Objects.requireNonNull(getContext()) );
builder.setView( dialogView ) builder.setView( dialogView )
.setTitle("So you want to save report?") .setTitle("So you want to save report?")
.setPositiveButton( "Save",(dialog, which) -> { .setPositiveButton( "Save",(dialog, which) -> {
progressBar.setVisibility( View.VISIBLE ); progressBar.setVisibility( View.VISIBLE );
NotificationHelper.showNotification( Objects.requireNonNull(getContext()),
"Utopia QA App",
"Report is uploading keep patience...");
inspectionReportService.saveReport(store.getReport(), new SaveReportCallback() { inspectionReportService.saveReport(store.getReport(), new SaveReportCallback() {
@Override @Override
public void onSuccess() { public void onSuccess() {
Toast.makeText( getContext(), "Report saved Successfully", Toast.LENGTH_LONG ).show(); Toast.makeText( getContext(), "Report saved Successfully", Toast.LENGTH_LONG ).show();
progressBar.setVisibility( View.INVISIBLE ); progressBar.setVisibility( View.INVISIBLE );
Objects.requireNonNull( getActivity() ).finish(); Objects.requireNonNull( getActivity() ).finish();
NotificationHelper.showNotification( Objects.requireNonNull(getContext()),
"Utopia QA App",
"Report is uploaded successfully");
} }
@Override @Override
public void onFailure(Throwable throwable) { public void onFailure(Throwable throwable) {
Toast.makeText( getContext(), throwable.getMessage(), Toast.LENGTH_LONG ).show(); Toast.makeText( getContext(), throwable.getMessage(), Toast.LENGTH_LONG ).show();
progressBar.setVisibility( View.INVISIBLE ); 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 // Show the dialog
AlertDialog dialog = builder.create(); AlertDialog dialog = builder.create();
progressBar.setVisibility( View.GONE );
dialog.show(); dialog.show();
} }
private void openDimensionDialog() { private void openDimensionDialog() {
@ -265,10 +278,18 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
int major = 0; int major = 0;
int crirical = 0; int crirical = 0;
for (InspectionItemCheckPoint itemCp : inspectionReport.getItems().get(0).getCheckPoints()) { for (InspectionItemCheckPoint itemCp : inspectionReport.getItems().get(0).getCheckPoints()) {
for( String status : itemCp.getDefectSeverites() ){ for( int i = 0 ; i< itemCp.getDefectSeverites().size() ; i++ ){
if( status.equalsIgnoreCase("minor") ) minor++; String status = itemCp.getDefectSeverites().get( i );
if( status.equalsIgnoreCase("major") ) major++; float quantity = itemCp.getQuantities().get(i);
if( status.equalsIgnoreCase("critical") ) crirical++; if( status.equalsIgnoreCase("minor") ){
minor += (int) quantity;
} ;
if( status.equalsIgnoreCase("major") ){
major += (int) quantity;
}
if( status.equalsIgnoreCase("critical") ) {
crirical += (int) quantity;
}
} }
} }

View File

@ -7,9 +7,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp" android:layout_margin="16dp"
android:id="@+id/save_report_progress" android:id="@+id/save_report_progress">
android:visibility="invisible"
>
</ProgressBar> </ProgressBar>