Add dimension images

main
saad.siddiq 2025-03-26 15:53:51 +05:00
parent be84a9409e
commit c4da9adde9
10 changed files with 369 additions and 88 deletions

View File

@ -10,7 +10,7 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <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" />
<application <application
android:allowBackup="false" android:allowBackup="false"
@ -27,12 +27,13 @@
<activity <activity
android:name="com.google.zxing.client.android.CaptureActivity" android:name="com.google.zxing.client.android.CaptureActivity"
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait"
android:exported="true" android:exported="true"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:windowSoftInputMode="stateAlwaysHidden" > android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter> <intent-filter>
<action android:name="com.google.zxing.client.android.SCAN" /> <action android:name="com.google.zxing.client.android.SCAN" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
@ -40,33 +41,35 @@
android:name=".ui.activities.MainActivity" android:name=".ui.activities.MainActivity"
android:exported="true" android:exported="true"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden|adjustPan"> android:windowSoftInputMode="stateHidden|adjustPan"></activity>
</activity>
<activity <activity
android:name=".ui.activities.HomeActivity" android:name=".ui.activities.HomeActivity"
android:exported="true" android:exported="true"
android:theme="@style/AppTheme"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan|adjustResize"> android:theme="@style/AppTheme"
</activity> android:windowSoftInputMode="adjustPan|adjustResize"></activity>
<activity <activity
android:name=".ui.activities.LoginActivity" android:name=".ui.activities.LoginActivity"
android:exported="true" android:exported="true"
android:theme="@style/AppTheme"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustPan|adjustResize"> android:windowSoftInputMode="adjustPan|adjustResize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name=".service.NetworkService"
android:exported="false"/> <service
android:name=".service.NetworkService"
android:exported="false" />
<receiver <receiver
android:name=".receiver.NetworkReceiver" android:name=".receiver.NetworkReceiver"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter> </intent-filter>
</receiver> </receiver>
@ -79,7 +82,6 @@
android:name="android.support.FILE_PROVIDER_PATHS" android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" /> android:resource="@xml/file_paths" />
</provider> </provider>
</application> </application>
</manifest> </manifest>

View File

@ -19,8 +19,8 @@ import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClient { public class RetrofitClient {
private final static String BASE_URL = "https://portal.utopiaindustries.pk/uind/"; //private final static String BASE_URL = "https://portal.utopiaindustries.pk/uind/";
//private final static String BASE_URL = "http://192.168.91.44:8081/uind/";//"http://192.168.91.44:8081/uind/";//"http://192.168.90.27:8080/uind/";//"http://192.168.91.16:8080/uind/"; private final static String BASE_URL = "http://192.168.91.44:8081/uind/";//"http://192.168.91.44:8081/uind/";//"http://192.168.90.27:8080/uind/";//"http://192.168.91.16:8080/uind/";
private static Retrofit retrofit; private static Retrofit retrofit;

View File

@ -2,6 +2,8 @@ package com.utopiaindustries.qualitychecker.models;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class InspectionItemDimension implements Serializable { public class InspectionItemDimension implements Serializable {

View File

@ -3,6 +3,7 @@ package com.utopiaindustries.qualitychecker.models;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class InspectionReportItem implements Serializable { public class InspectionReportItem implements Serializable {
@ -59,6 +60,7 @@ public class InspectionReportItem implements Serializable {
// wrapper // wrapper
private List<InspectionItemCheckPoint> checkPoints; private List<InspectionItemCheckPoint> checkPoints;
private List<InspectionItemDimension> dimensions; private List<InspectionItemDimension> dimensions;
private List<byte[]> dimensionImages = new ArrayList<>();
private String fnsku; private String fnsku;
@ -424,6 +426,14 @@ public void setLevelMinorDefects(int levelMinorDefects) {
this.section = section; this.section = section;
} }
public List<byte[]> getDimensionImages() {
return dimensionImages;
}
public void addDimensionImageList(byte[] image) {
this.dimensionImages.add(image);
}
@Override @Override
public String toString() { public String toString() {
return "InspectionReportItem{" + return "InspectionReportItem{" +
@ -472,6 +482,7 @@ public void setLevelMinorDefects(int levelMinorDefects) {
", section='" + section + '\'' + ", section='" + section + '\'' +
", dimensions=" + dimensions + ", dimensions=" + dimensions +
", fnsku='" + fnsku + '\'' + ", fnsku='" + fnsku + '\'' +
", dimensionImages=" + dimensionImages +
'}'; '}';
} }
} }

View File

@ -31,6 +31,7 @@ import com.utopiaindustries.qualitychecker.ui.fragments.FirstStepFragment;
import com.utopiaindustries.qualitychecker.ui.fragments.SecondStepFragment; import com.utopiaindustries.qualitychecker.ui.fragments.SecondStepFragment;
import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult; import com.google.zxing.integration.android.IntentResult;
import com.utopiaindustries.qualitychecker.ui.fragments.ThirdStepFragment;
import com.utopiaindustries.qualitychecker.utils.FileUtils; import com.utopiaindustries.qualitychecker.utils.FileUtils;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -45,6 +46,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
private String fromClass; private String fromClass;
private String draftReportId; private String draftReportId;
private static final int CAMERA_REQUEST = 10111;
private static final int GALLERY_REQUEST = 20111;
@SuppressLint("SourceLockedOrientationActivity") @SuppressLint("SourceLockedOrientationActivity")
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -118,6 +122,14 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
} }
} }
} }
else if (requestCode == CAMERA_REQUEST) {
ThirdStepFragment thirdStepFragment = ( ThirdStepFragment) getCurrentVisibleFragment();
thirdStepFragment.onImagePickerResult( requestCode, resultCode, data );
}
else if (requestCode == GALLERY_REQUEST) {
ThirdStepFragment thirdStepFragment = ( ThirdStepFragment) getCurrentVisibleFragment();
thirdStepFragment.onImagePickerResult( requestCode, resultCode, data );
}
else if (requestCode != -1 && resultCode == -1 && data == null) { else if (requestCode != -1 && resultCode == -1 && data == null) {
Log.e("camera ","------- camera ***"); Log.e("camera ","------- camera ***");
SecondStepFragment secondStepFragment = ( SecondStepFragment) getCurrentVisibleFragment(); SecondStepFragment secondStepFragment = ( SecondStepFragment) getCurrentVisibleFragment();

View File

@ -36,6 +36,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.utopiaindustries.qualitychecker.R; import com.utopiaindustries.qualitychecker.R;
import com.utopiaindustries.qualitychecker.async.ImageProcessor; import com.utopiaindustries.qualitychecker.async.ImageProcessor;
import com.utopiaindustries.qualitychecker.models.callback.SaveDraftReportCallback; import com.utopiaindustries.qualitychecker.models.callback.SaveDraftReportCallback;
@ -60,7 +61,7 @@ public class SecondStepFragment extends Fragment
implements View.OnClickListener { implements View.OnClickListener {
private NavController navController; private NavController navController;
private Button leftFab, rightFab, draftFab; private Button leftFab, rightFab, draftFab, moveToBottom;
private RecyclerView recyclerView; private RecyclerView recyclerView;
private CheckPointAdapter adapter; private CheckPointAdapter adapter;
private TextView profileName; private TextView profileName;
@ -83,6 +84,7 @@ public class SecondStepFragment extends Fragment
draftFab = view.findViewById(R.id.button_draft_second); draftFab = view.findViewById(R.id.button_draft_second);
leftFab = view.findViewById(R.id.button_left_frag_2); leftFab = view.findViewById(R.id.button_left_frag_2);
rightFab = view.findViewById(R.id.button_right_frag_2); rightFab = view.findViewById(R.id.button_right_frag_2);
moveToBottom = view.findViewById(R.id.button_move_to_bottom);
recyclerView = view.findViewById(R.id.check_point_recycler_view); recyclerView = view.findViewById(R.id.check_point_recycler_view);
profileName = view.findViewById(R.id.second_profile_name); profileName = view.findViewById(R.id.second_profile_name);
profileImage = view.findViewById(R.id.second_step_profile_image); profileImage = view.findViewById(R.id.second_step_profile_image);
@ -128,6 +130,7 @@ public class SecondStepFragment extends Fragment
leftFab.setOnClickListener(this); leftFab.setOnClickListener(this);
rightFab.setOnClickListener(this); rightFab.setOnClickListener(this);
draftFab.setOnClickListener(this); draftFab.setOnClickListener(this);
moveToBottom.setOnClickListener(this);
updateProfileViews(); updateProfileViews();
return view; return view;
} }
@ -186,6 +189,11 @@ public class SecondStepFragment extends Fragment
if (v.getId() == R.id.button_right_frag_2) { if (v.getId() == R.id.button_right_frag_2) {
checkIsRecyclerViewIsCompletelyScrolled(recyclerView); checkIsRecyclerViewIsCompletelyScrolled(recyclerView);
} }
if (v.getId() == R.id.button_move_to_bottom) {
Log.e("Fab-Button","click");
scrollToBottom();
}
} }
public void onImagePickerResult(int requestCode, int resultCode, Intent data) { public void onImagePickerResult(int requestCode, int resultCode, Intent data) {
@ -334,6 +342,12 @@ public class SecondStepFragment extends Fragment
}).start(); }).start();
} }
private void scrollToBottom() {
if (adapter != null && adapter.getItemCount() > 0) {
//recyclerView.scrollToPosition(adapter.getItemCount() - 1); // Scroll to the last item
recyclerView.smoothScrollToPosition(adapter.getItemCount() - 1); // Smooth scroll, if desired.
}
}
private void checkIsRecyclerViewIsCompletelyScrolled(RecyclerView recyclerView) { private void checkIsRecyclerViewIsCompletelyScrolled(RecyclerView recyclerView) {
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) { if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {

View File

@ -1,11 +1,20 @@
package com.utopiaindustries.qualitychecker.ui.fragments; package com.utopiaindustries.qualitychecker.ui.fragments;
import static android.app.Activity.RESULT_OK;
import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.provider.MediaStore;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.Log; import android.util.Log;
@ -17,6 +26,7 @@ import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Spinner; import android.widget.Spinner;
@ -26,7 +36,9 @@ import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.Navigation; import androidx.navigation.Navigation;
@ -48,9 +60,14 @@ 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;
import com.utopiaindustries.qualitychecker.ui.adapter.ImageAdapter;
import com.utopiaindustries.qualitychecker.ui.adapter.ItemDimensionAdapter; import com.utopiaindustries.qualitychecker.ui.adapter.ItemDimensionAdapter;
import com.utopiaindustries.qualitychecker.ui.adapter.VocAdapter; import com.utopiaindustries.qualitychecker.ui.adapter.VocAdapter;
import com.utopiaindustries.qualitychecker.utils.FileUtils;
import com.utopiaindustries.qualitychecker.utils.ImageUriHolder;
import java.io.File;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -62,6 +79,7 @@ import retrofit2.Response;
public class ThirdStepFragment extends Fragment implements View.OnClickListener { public class ThirdStepFragment extends Fragment implements View.OnClickListener {
private NavController navController; private NavController navController;
private Button backBtn,nextBtn,openDimensionDialog, btnDraft; private Button backBtn,nextBtn,openDimensionDialog, btnDraft;
private ImageButton imagePicker, deleteImage ;
private TextView profileName; private TextView profileName;
private ImageView profileImage; private ImageView profileImage;
private InspectionReportService inspectionReportService; private InspectionReportService inspectionReportService;
@ -70,6 +88,15 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
private Spinner resultSpinner, sectionSpinner; private Spinner resultSpinner, sectionSpinner;
private ApiService apiService; private ApiService apiService;
private EditText generalRemarks, etQualityAuditor, etProdRepresentative, etQcRepresentative,etFloor; private EditText generalRemarks, etQualityAuditor, etProdRepresentative, etQcRepresentative,etFloor;
private static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 100;
private static final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 101;
private static final int MY_PERMISSIONS_REQUEST_CAMERA = 102;
private static final int CAMERA_REQUEST = 10111;
private static final int GALLERY_REQUEST = 20111;
private ImageAdapter imageAdapter;
private RecyclerView imageRecyclerView;
private TextView minorCountTv,majorCountTv,criticalCountTv, txtMajor, txtMinor; private TextView minorCountTv,majorCountTv,criticalCountTv, txtMajor, txtMinor;
String[] sectionArray = {"Comforter & Mattress Pad", String[] sectionArray = {"Comforter & Mattress Pad",
@ -89,6 +116,7 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
apiService = ApiServiceFactory.getApiService(); apiService = ApiServiceFactory.getApiService();
initializeViews( view ); initializeViews( view );
checkPermissions();
populateViews(); populateViews();
setOnClickListeners(); setOnClickListeners();
updateProfileViews(); updateProfileViews();
@ -220,9 +248,110 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
} }
}); });
imagePicker.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Choose an Option");
String[] options = {"Gallery", "Camera"};
builder.setItems(options, (dialog, which) -> {
switch (which) {
case 0:
Log.e("Gallery","**********");
Intent intent = new Intent( Intent.ACTION_GET_CONTENT );
intent.addCategory( Intent.CATEGORY_OPENABLE );
intent.setType( "image/*" );
//startActivityForResult( intent, GALLERY_REQUEST );
( ( Activity ) getContext() ).startActivityForResult( intent, GALLERY_REQUEST );
break;
case 1:
Log.e("Camera: ","***********");
Intent camera_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File imageFile = new File(getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES), "captured_image.jpg");
Uri imageUri = FileProvider.getUriForFile(getContext(), getContext().getPackageName() + ".fileprovider", imageFile);
//Log.e("imageUri: ",""+imageUri);
ImageUriHolder.getInstance().setImageUri(imageUri);
camera_intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
//startActivityForResult(camera_intent, CAMERA_REQUEST);
( ( Activity ) getContext() ).startActivityForResult( camera_intent, CAMERA_REQUEST );
break;
}
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss());
AlertDialog dialog = builder.create();
dialog.show();
}
});
deleteImage.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!store.getReport().getItems().get(0).getDimensionImages().isEmpty()) {
store.getReport().getItems().get(0).getDimensionImages().remove(store.getReport().getItems().get(0).getDimensionImages().size() - 1);
updateImageAdapter(store.getReport().getItems().get(0).getDimensionImages());
}
else {
System.out.println("The list is empty");
}
}
});
return view; return view;
} }
public void onImagePickerResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST) {
Uri selectedImageUri = ImageUriHolder.getInstance().getImageUri();
saveImage(selectedImageUri);
}
else if (requestCode == GALLERY_REQUEST) {
Uri selectedImageUri = data.getData();
assert selectedImageUri != null;
saveImage(selectedImageUri);
}
}
private void saveImage(Uri imageUri) {
FileUtils.convertUriToByteArrayAsync(
getContext(),
imageUri,
100, // Target size in KB
compressedImage -> {
// Handle the compressed image here, e.g., display it
requireActivity().runOnUiThread(() -> {
store.getReport().getItems().get(0).addDimensionImageList(compressedImage);
updateImageAdapter(store.getReport().getItems().get(0).getDimensionImages());
//adapter.notifyItemChanged(requestCode);
});
},
error -> {
// Handle any errors
requireActivity().runOnUiThread(() -> {
Toast.makeText(getContext(), "Error compressing image: " + error.getMessage(), Toast.LENGTH_SHORT).show();
});
}
);
}
private void updateImageAdapter(List<byte[]> imgFiles) {
imageRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
imageAdapter = new ImageAdapter(imgFiles, getContext());
imageRecyclerView.setAdapter(imageAdapter);
int position = imgFiles.size();
imageAdapter.notifyItemInserted(position);
}
@Override @Override
public void onClick(View v) { public void onClick(View v) {
navController = Navigation.findNavController( requireView() ); navController = Navigation.findNavController( requireView() );
@ -488,6 +617,11 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
txtMajor.setText(String.format("Major : %s/%d", (int)majorInspection, (int)(majorInspection + 1))); txtMajor.setText(String.format("Major : %s/%d", (int)majorInspection, (int)(majorInspection + 1)));
txtMinor.setText(String.format("Minor : %s/%d", (int)minorInspection, (int)(minorInspection + 1))); txtMinor.setText(String.format("Minor : %s/%d", (int)minorInspection, (int)(minorInspection + 1)));
} }
if (!store.getReport().getItems().get(0).getDimensionImages().isEmpty()) {
updateImageAdapter(store.getReport().getItems().get(0).getDimensionImages());
}
} }
private void calculateDimensions(){ private void calculateDimensions(){
@ -546,6 +680,9 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
backBtn = view.findViewById( R.id.button_left_frag_3 ); backBtn = view.findViewById( R.id.button_left_frag_3 );
nextBtn = view.findViewById( R.id.button_right_frag_3 ); nextBtn = view.findViewById( R.id.button_right_frag_3 );
btnDraft = view.findViewById(R.id.button_draft_third); btnDraft = view.findViewById(R.id.button_draft_third);
imagePicker = view.findViewById(R.id.image_picker);
deleteImage = view.findViewById(R.id.delete_image);
imageRecyclerView = view.findViewById(R.id.imageRecyclerView);
openDimensionDialog = view.findViewById( R.id.button_open_dimension ); openDimensionDialog = view.findViewById( R.id.button_open_dimension );
profileImage = view.findViewById( R.id.third_step_profile_image ); profileImage = view.findViewById( R.id.third_step_profile_image );
profileName = view.findViewById( R.id.third_profile_name ); profileName = view.findViewById( R.id.third_profile_name );
@ -580,4 +717,34 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
.load( store.getProfileImage( ) ) .load( store.getProfileImage( ) )
.into( profileImage ); .into( profileImage );
} }
// PERMISSIONS
private void checkPermissions() {
// Check if permission is not granted
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted, request it
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
}
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
}
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.CAMERA},
MY_PERMISSIONS_REQUEST_CAMERA);
}
}
} }

View File

@ -3,6 +3,7 @@ package com.utopiaindustries.qualitychecker.utils;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@ -25,7 +26,9 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer;
public class FileUtils { public class FileUtils {
public static String writeFile( Context context , public static String writeFile( Context context ,
@ -154,4 +157,51 @@ public class FileUtils {
dialog.show(); dialog.show();
} }
public static void convertUriToByteArrayAsync(
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();
}
} }

View File

@ -8,6 +8,7 @@
android:id="@+id/fragment_tag"> android:id="@+id/fragment_tag">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout2"
android:layout_width="806dp" android:layout_width="806dp"
android:layout_height="1200dp" android:layout_height="1200dp"
app:layout_constraintBottom_toTopOf="@+id/relativeLayout" app:layout_constraintBottom_toTopOf="@+id/relativeLayout"
@ -81,12 +82,13 @@
android:layout_weight="1" android:layout_weight="1"
android:backgroundTint="@color/light_blue" android:backgroundTint="@color/light_blue"
android:text="STEP 2 Checkpoints" /> android:text="STEP 2 Checkpoints" />
<Button <Button
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:backgroundTint="@color/white" android:backgroundTint="@color/white"
android:text="STEP 3 Dimension"/> android:text="STEP 3 Dimension" />
</LinearLayout> </LinearLayout>
@ -105,6 +107,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -131,12 +134,12 @@
app:layout_constraintTop_toBottomOf="@+id/guide_lne" app:layout_constraintTop_toBottomOf="@+id/guide_lne"
app:layout_constraintVertical_bias="0.008" /> app:layout_constraintVertical_bias="0.008" />
</LinearLayout> </LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/check_point_recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="8dp" android:padding="8dp"></androidx.recyclerview.widget.RecyclerView>
android:id="@+id/check_point_recycler_view">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
@ -169,10 +172,10 @@
android:id="@+id/button_draft_second" android:id="@+id/button_draft_second"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_toStartOf="@id/button_right_frag_2"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
android:layout_toStartOf="@id/button_right_frag_2"
android:text="Draft" /> android:text="Draft" />
<Button <Button
@ -184,13 +187,16 @@
android:layout_toStartOf="@id/button_draft_second" android:layout_toStartOf="@id/button_draft_second"
android:text="Back" /> android:text="Back" />
<!-- <Button--> <Button
<!-- android:id="@+id/button_add_frag_2"--> android:id="@+id/button_move_to_bottom"
<!-- android:layout_width="wrap_content"--> android:layout_width="wrap_content"
<!-- android:layout_height="wrap_content"--> android:layout_height="wrap_content"
<!-- android:layout_alignBaseline="@id/button_right_frag_2"--> android:layout_alignBaseline="@id/button_right_frag_2"
<!-- android:layout_marginEnd="16dp"--> android:layout_marginEnd="16dp"
<!-- android:layout_toStartOf="@id/button_left_frag_2"--> android:layout_toStartOf="@id/button_left_frag_2"
<!-- android:text="Add CheckPoint" />--> android:text="Move to Bottom" />
</RelativeLayout> </RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -137,7 +137,8 @@
<LinearLayout <LinearLayout
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_marginTop="5dp"
android:layout_marginBottom="5dp"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -192,11 +193,44 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/item_dimensions_recyclerview" android:id="@+id/item_dimensions_recyclerview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp" android:layout_height="180dp"
android:layout_margin="20dp"> android:layout_margin="20dp">
</androidx.recyclerview.widget.RecyclerView> </androidx.recyclerview.widget.RecyclerView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_margin="5dp"
android:weightSum="1"
android:background="@drawable/box_border"
android:orientation="horizontal"
android:padding="2dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/imageRecyclerView"
android:layout_width="wrap_content"
android:layout_weight="0.99"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_margin="5dp"/>
<ImageButton
android:id="@+id/image_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/image_picker"
android:background="@null"
android:padding="8dp"/>
<ImageButton
android:id="@+id/delete_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_delete"
android:background="@null"
android:padding="8dp"/>
</LinearLayout>
<!-- <LinearLayout--> <!-- <LinearLayout-->
<!-- android:layout_width="match_parent"--> <!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"--> <!-- android:layout_height="wrap_content"-->
@ -320,45 +354,20 @@
android:padding="10dp"> android:padding="10dp">
<!-- Text Label --> <!-- Text Label -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="1">
<TextView <TextView
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="0.7" android:layout_alignParentStart="true"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
android:layout_alignParentStart="true"
android:text="Status" android:text="Status"
android:textColor="@color/black" android:textColor="@color/black"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.3"
android:layout_marginTop="10dp"
android:layout_alignParentEnd="true"
android:layout_marginBottom="5dp"
android:text="Section"
android:textColor="@color/black"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:weightSum="1"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="10dp"> android:padding="10dp">
@ -405,23 +414,6 @@
android:textStyle="bold" /> android:textStyle="bold" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.3"
android:padding="10dp"
android:orientation="vertical">
<Spinner
android:id="@+id/section_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="@string/section_title" />
</LinearLayout>
</LinearLayout>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -567,7 +559,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:layout_weight="0.6"> android:layout_weight="0.35">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -582,6 +574,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp" android:layout_marginHorizontal="10dp"
android:imeOptions="actionNext"
android:hint="General Remarks" android:hint="General Remarks"
android:inputType="text" /> android:inputType="text" />
</LinearLayout> </LinearLayout>
@ -590,7 +583,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:layout_weight="0.4"> android:layout_weight="0.3">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -610,6 +603,28 @@
android:inputType="text" /> android:inputType="text" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.35"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Section"
android:textColor="@color/black"
android:textStyle="bold" />
<Spinner
android:id="@+id/section_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginHorizontal="10dp"
android:prompt="@string/section_title" />
</LinearLayout>
</LinearLayout> </LinearLayout>
@ -621,7 +636,9 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp" android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_weight="1" android:layout_weight="1"
android:text="Vocs" android:text="Vocs"
android:textColor="@color/black" android:textColor="@color/black"
@ -641,7 +658,7 @@
android:id="@+id/voc_recyclerview" android:id="@+id/voc_recyclerview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="16dp"> android:layout_margin="5dp">
</androidx.recyclerview.widget.RecyclerView> </androidx.recyclerview.widget.RecyclerView>