Quality-Control-Android-App/app/src/main/java/com/utopiaindustries/qualitycontrol/fragments/StitchingFragment.java

515 lines
21 KiB
Java

package com.utopiaindustries.qualitycontrol.fragments;
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.utopiaindustries.qualitycontrol.R;
import com.utopiaindustries.qualitycontrol.activities.HomeActivity;
import com.utopiaindustries.qualitycontrol.adapters.ImageAdapter;
import com.utopiaindustries.qualitycontrol.adapters.ItemStepsAdapter;
import com.utopiaindustries.qualitycontrol.helper.Helper;
import com.utopiaindustries.qualitycontrol.models.Item;
import com.utopiaindustries.qualitycontrol.utils.ImageSelectionListener;
import com.utopiaindustries.qualitycontrol.utils.QualityControlViewModel;
import com.utopiaindustries.qualitycontrol.viewmodels.ItemModel;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.AppSettingsDialog;
import pub.devrel.easypermissions.EasyPermissions;
public class StitchingFragment extends Fragment implements EasyPermissions.PermissionCallbacks,
ImageSelectionListener {
RecyclerView recyclerView, imageRecyclerView;
ImageAdapter imageAdapter;
String filePath = "no_pic";
private static final int CAMERA_REQUEST = 103;
private static final int GALLERY_REQUEST = 203;
Button nextButton;
ImageButton imagePicker, deleteImage;
ArrayList<byte[]> imageList = new ArrayList<>();
EditText etPercentage, etRemarks;
List<ItemModel> itemModelList = new ArrayList<>();
ItemStepsAdapter adapter;
private int selectedPosition = -1;
private int deletePosition = -1;
// Activity Result Launcher for Gallery
private final ActivityResultLauncher<Intent> imagePickerLauncher =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == requireActivity().RESULT_OK && result.getData() != null) {
Uri selectedImage = result.getData().getData();
if (selectedPosition != -1 && selectedImage != null) {
//imageView.setImageURI(selectedImage);
//Log.e("Selected-Image: ", "" + selectedImage);
uriToByteArrayAsync(
getContext(),
selectedImage,
100, // Target size in KB
compressedImage -> {
// Handle the compressed image here, e.g., display it
requireActivity().runOnUiThread(() -> {
itemModelList.get(selectedPosition).setImageUri(compressedImage);
List<byte[]> tempList = new ArrayList<>();
tempList.add(compressedImage);
itemModelList.get(selectedPosition).setImageArrayList(tempList);
adapter.notifyItemChanged(selectedPosition);
});
},
error -> {
// Handle any errors
requireActivity().runOnUiThread(() -> {
Toast.makeText(getContext(), "Error compressing image: " + error.getMessage(), Toast.LENGTH_SHORT).show();
});
}
);
}
}
});
// Activity Result Launcher for Camera
private final ActivityResultLauncher<Intent> cameraLauncher =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
Uri contentUri = Uri.fromFile(new File((filePath)));
uriToByteArrayAsync(
getContext(),
contentUri,
100, // Target size in KB
compressedImage -> {
// Handle the compressed image here, e.g., display it
requireActivity().runOnUiThread(() -> {
itemModelList.get(selectedPosition).setImageUri(compressedImage);
List<byte[]> tempList = new ArrayList<>();
tempList.add(compressedImage);
itemModelList.get(selectedPosition).setImageArrayList(tempList);
adapter.notifyItemChanged(selectedPosition);
});
},
error -> {
// Handle any errors
requireActivity().runOnUiThread(() -> {
Toast.makeText(getContext(), "Error compressing image: " + error.getMessage(), Toast.LENGTH_SHORT).show();
});
}
);
//Log.e("contentUri: ", "" + contentUri);
if (result.getResultCode() == requireActivity().RESULT_OK && result.getData() != null) {
Uri selectedImage = result.getData().getData();
if (selectedImage != null) {
//imageView.setImageURI(selectedImage);
//Log.e("Selected-Image: ", "" + selectedImage);
}
}
});
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_stitching, container, false);
initializeLayout(view);
// Set up RecyclerView
/*ItemStitchingAdapter adapter = new ItemStitchingAdapter(getActivity(), itemList, sharedViewModel);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(adapter);*/
//New Implemented------------------
if (Helper.getArrayList(Helper.listStitching, getActivity()) != null) {
itemModelList.clear();
itemModelList.addAll(Helper.getArrayList(Helper.listStitching, getActivity()));
//Log.e("itemModelList-size: ",""+itemModelList.size());
if (itemModelList != null) {
adapter = new ItemStepsAdapter(getActivity(), itemModelList, this);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(adapter);
}
else {
for (int i = 1; i < 7; i++) {
itemModelList.add(new ItemModel(2,i,0,"0","",0,null, null));
}
adapter = new ItemStepsAdapter(getActivity(), itemModelList,this);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(adapter);
}
}
else {
for (int i = 1; i < 7; i++) {
itemModelList.add(new ItemModel(2,i,0,"0","",0, null, null));
}
adapter = new ItemStepsAdapter(getActivity(), itemModelList, this);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(adapter);
}
//----------------------------------
imageAdapter = new ImageAdapter(imageList, getActivity());
imageRecyclerView.setAdapter(imageAdapter);
imagePicker.setOnClickListener(v -> {
showAlertDialog(view);
});
deleteImage.setOnClickListener(v -> {
if (!imageList.isEmpty()) {
imageList.remove(imageList.size() - 1);
} else {
System.out.println("The list is empty");
}
imageAdapter.notifyDataSetChanged();
});
nextButton.setOnClickListener(v -> {
if (getActivity() instanceof HomeActivity) {
List<ItemModel> updatedItemList = itemModelList; // Or adapter.getItemList()
/*for (ItemModel item : updatedItemList) {
Log.e("AdapterData", "ProcessId: " + item.getProcessId() +
", StepId: " + item.getStepId() +
", SpinnerSelection: " + item.getSelectedOption() +
", Rating: " + item.getRating() +
", Percentage: " + item.getPercentage() +
", Remarks: " + item.getRemarks() +
", ImageList: " + item.getImageArrayList());
}*/
Helper.saveArrayList(itemModelList, Helper.listStitching,getActivity());
//List<ItemModel> updatedItemListP = new ArrayList<>(Helper.getArrayList("ListStitching", getActivity()));
/*if (etRemarks.getText().toString().isEmpty()) {
Toast.makeText(getActivity(), "Please enter remarks", Toast.LENGTH_SHORT).show();
}
else {*/
/* sharedViewModel.setStitchingPercentage(etPercentage.getText().toString());
sharedViewModel.setStitchingRemarks(etRemarks.getText().toString());
if (!imageList.isEmpty()) {
sharedViewModel.setStitchingImageList(imageList);
}*/
((HomeActivity) getActivity()).navigateToFragment(new CheckingFragment(), true);
// }
}
});
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
private void initializeLayout(View view) {
//viewModel = new ViewModelProvider(requireActivity()).get(QualityControlViewModel.class);
etPercentage = view.findViewById(R.id.et_percentage);
etRemarks = view.findViewById(R.id.et_remarks);
imagePicker = view.findViewById(R.id.image_picker);
deleteImage = view.findViewById(R.id.delete_image);
nextButton = view.findViewById(R.id.btn_next);
recyclerView = view.findViewById(R.id.recycler_view_stitching);
imageRecyclerView = view.findViewById(R.id.imageRecyclerView);
imageRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false));
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// EasyPermissions handles the request result.
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
new AppSettingsDialog.Builder(this).build().show();
}
}
public void uriToByteArrayAsync(
Context context,
Uri uri,
int targetSizeInKB,
Consumer<byte[]> onSuccess,
Consumer<Exception> onError
) {
new Thread(() -> {
try {
int targetSizeInBytes = targetSizeInKB * 1024;
// Load the image as a Bitmap without scaling
Bitmap bitmap;
try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) {
bitmap = BitmapFactory.decodeStream(inputStream);
}
if (bitmap == null) {
throw new IOException("Failed to decode image from URI.");
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int minQuality = 10;
int maxQuality = 100;
int quality = maxQuality;
// Binary search for the best quality that meets the target size
while (minQuality <= maxQuality) {
byteArrayOutputStream.reset();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream);
int byteSize = byteArrayOutputStream.size();
if (byteSize > targetSizeInBytes) {
maxQuality = quality - 1;
} else {
minQuality = quality + 1;
}
quality = (minQuality + maxQuality) / 2;
}
onSuccess.accept(byteArrayOutputStream.toByteArray());
} catch (IOException e) {
onError.accept(e);
}
}).start();
}
private boolean hasGalleryPermission() {
String[] perms = {};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
perms = new String[]{Manifest.permission.READ_MEDIA_IMAGES};
} else {
perms = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
}
return EasyPermissions.hasPermissions(requireActivity(), perms);
}
private boolean hasCameraPermission() {
String[] perms = {};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
//Log.e("TIRAMISU: ","***");
perms = new String[]{Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.CAMERA};
} else {
//Log.e("Not-TIRAMISU: ","***");
perms = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
}
//Log.e("perms: ",""+perms);
return EasyPermissions.hasPermissions(requireActivity(), perms);
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = requireActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
filePath = image.getAbsolutePath();
return image;
}
public void showAlertDialog(View view) {
ViewGroup viewGroup = view.findViewById(android.R.id.content);
TextView txt_camera, txt_gallery, txt_cancel;
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
View view1 = LayoutInflater.from(getActivity()).inflate(R.layout.custom_layout, viewGroup, false);
builder.setCancelable(false);
builder.setView(view1);
txt_camera = view1.findViewById(R.id.txt_camera);
txt_gallery = view1.findViewById(R.id.txt_gallery);
txt_cancel = view1.findViewById(R.id.txt_cancel);
AlertDialog alertDialog = builder.create();
Objects.requireNonNull(alertDialog.getWindow()).setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
txt_camera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
alertDialog.dismiss();
openCamera();
}
});
txt_gallery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
alertDialog.dismiss();
openGallery();
}
});
txt_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
alertDialog.dismiss();
}
});
alertDialog.show();
}
@AfterPermissionGranted(CAMERA_REQUEST)
public void openCamera() {
if (hasCameraPermission()) {
try {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(requireActivity(),
"com.utopiaindustries.qualitycontrol",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
//startActivityForResult(takePictureIntent, CAMERA_REQUEST);
cameraLauncher.launch(takePictureIntent);
}
} catch (ActivityNotFoundException e) {
Toast.makeText(getContext(), "Camera app not found", Toast.LENGTH_SHORT).show();
}
} else {
// Ask for one permission
String[] perms = {};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
perms = new String[]{Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.CAMERA};
} else {
perms = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
}
EasyPermissions.requestPermissions(this, getString(R.string.rationale_camera), CAMERA_REQUEST, perms);
}
}
@AfterPermissionGranted(GALLERY_REQUEST)
public void openGallery() {
if (hasGalleryPermission()) {
// Have permission, do the thing!
Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// Start the Intent
//startActivityForResult(galleryIntent, GALLERY_REQUEST);
imagePickerLauncher.launch(galleryIntent);
} else {
// Ask for one permission
String[] perms = {};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
perms = new String[]{Manifest.permission.READ_MEDIA_IMAGES};
} else {
perms = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
}
EasyPermissions.requestPermissions(this, getString(R.string.rationale_camera), GALLERY_REQUEST, perms);
}
}
@Override
public void onSelectImage(int position) {
selectedPosition = position;
// Show dialog to choose between camera and gallery
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
builder.setTitle("Select Image")
.setItems(new String[]{"Camera", "Gallery"}, (dialog, which) -> {
if (which == 0) { // Camera
openCamera();
} else { // Gallery
openGallery();
}
})
.show();
}
@Override
public void onDeleteImage(int position) {
deletePosition = position;
if (itemModelList.get(deletePosition).getImageArrayList() != null && !itemModelList.get(deletePosition).getImageArrayList().isEmpty()) {
itemModelList.get(deletePosition).setImageArrayList(null);
itemModelList.get(deletePosition).setImageUri(null);
adapter.notifyItemChanged(deletePosition);
}
}
}