The app I am making need to take pictures to send them to a server.
I need to take 6 photos at least. I have a recyclerView in which I am displaying a preview of my photo. It's working perfectly (I am using Picasso as photo library).
I need to be able to delete photos before sending them away (and consequently their preview). With a click on the preview, I remove it from my photo tab and update my recyclerview with notifyDataSetChanged().
The photo disappears.
When I take an other picture, I have its preview but the preview from the deleted picture is coming back.
If I delete three pictures and take a new one, I have the preview of the new one and the preview of the 3 deleted pictures.
Here's part of my adapter where I bind my view
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
mImageView = holder.mPhotoIV;
File mFile = new File(String.valueOf(Uri.parse(mListOfPhotos.get(position))));
int width = mImageView.getLayoutParams().width;
int height = mImageView.getLayoutParams().height;
Picasso.get()
.load(mFile)
.resize(200, 200)
.error(R.drawable.ic_no_photo_foreground)
.into(mImageView, new com.squareup.picasso.Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError(Exception e) {
}
});
}
Here part of my activity where I'm calling my adapter
mTakePhotoFAB.setOnClickListener(view -> {
mDir = new File(getExternalCacheDir(), "PhotosAuthentifier");
boolean success = true;
if (!mDir.exists()) {
success = mDir.mkdir();
}
if (success) {
File mFile = new File(mDir, new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.getDefault()).format(new Date()) + ".jpg");
mImageCapture.takePicture(mFile,
new ImageCapture.OnImageSavedListener() {
#Override
public void onImageSaved(#NonNull File file) {
mListOfPhotos.add(file.getAbsolutePath());
mNumberOfPhotoTV.setText(getResources().getString(R.string.minPhotos, mListOfPhotos.size()));
if (mListOfPhotos.size() >= 6) {
mSendPhotoFAB.setVisibility(View.VISIBLE);
}
mAdapter = new CameraPhotoAdapter(mListOfPhotos, getBaseContext());
mRecyclerView.setAdapter(mAdapter);
}
#Override
public void onError(#NonNull ImageCapture.ImageCaptureError imageCaptureError, #NonNull String message, #Nullable Throwable cause) {
String mMessage = "Photo capture failed: " + message;
Toast.makeText(CameraActivity.this, mMessage, Toast.LENGTH_SHORT).show();
assert cause != null;
cause.printStackTrace();
}
});
}
});
Function (in my adapter) to remove picture
protected void removePhoto(Context context, ArrayList<String> array, int position) {
File mDir = new File(context.getExternalCacheDir(), "PhotosAuthentifier");
File mFile = new File(array.get(position));
if (mDir.exists()) {
File[] mFilesIntoDir = mDir.listFiles();
if (mFilesIntoDir == null) {
return;
} else {
for (int i = 0; i < mFilesIntoDir.length; i++) {
if (mFilesIntoDir[i].getAbsolutePath().equals(mFile.getAbsolutePath())) {
boolean mSuccess = mFilesIntoDir[i].delete();
if (mSuccess) {
Picasso.get().invalidate(mFile.getAbsolutePath());
mListOfPhotos.remove(mFile.getAbsolutePath());
notifyDataSetChanged();
}
}
}
}
}
}
I tried to invalidate Picasso cache but when I take a new picture, instead of the deleted picture reappearing I have the default behavior when I don't have a good url to upload (a black cross)
Could anyone help please :)?
Related
I have a folder with about 10 images which I like to OCR extract text.
That works excellent for 1 picture, but my java skills are not good enough to implement that for multiple images.
I'm really appreciate if someone could show me a clean solution for that.
Thanks a lot
br Lukas
TextView output1;
ArrayList<Bitmap> bitmapArray = new ArrayList<Bitmap>();
TextRecognizer recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS);
private void OCR_list()
{
String path = Environment.getExternalStorageDirectory().toString()+"/folder_with_images";
File directory = new File(path);
File[] files = directory.listFiles();
for (int i = 0; i < files.length; i++) {
output1.setText(output1.getText() + ", " + files[i].getName());
File imgFile = files[i];
if (imgFile.exists()) {
bitmapArray.add(BitmapFactory.decodeFile(imgFile.getAbsolutePath()));
} else {
output1.setText(output1.getText()+"\n Bitmap not found!");
return;
}
}
InputImage image = InputImage.fromBitmap(bitmapArray.get(0), 0);
recognizer.process(image)
.addOnSuccessListener(
new OnSuccessListener<Text>() {
#Override
public void onSuccess(Text texts) {
processTextRecognitionResult(texts);
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
e.printStackTrace();
}
});
Edit:
I solved it now this way, but looks awful:
private void new_Recognition(InputImage image) {
recognizer.process(image)
.addOnSuccessListener(
new OnSuccessListener<Text>() {
#Override
public void onSuccess(Text texts) {
processTextRecognitionResult(texts);
bitmapArray.remove(0);
if (!bitmapArray.isEmpty()) {
InputImage image = InputImage.fromBitmap(bitmapArray.get(0), 0);
new_Recognition(image);
}
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
e.printStackTrace();
}
});
}
You can iterate on inputs directly, and recognition tasks will be queued up and then processed in order internally.
for (Bitmap input : inputs) {
recognizer.process(input)
.addOnSuccessListener(text -> ...)
}
I am trying to set the last element of recyclerview fully visible to the user whenever it takes a photo.
So I used recyclerview.smoothScrollToPosition(recycler.getAdapter().getItemCount() - 1);
But I always see the penultimate photo. Even if I change "- 1" to "+ 1" or "+ 4" or even "+ 15"
My recyclerView first scrolls to the last element and then add a new element to my array. So this way, it never really goes to the last element. It should be the opposite.
Could anyone help, please? Am I missing something?
if (success) {
File mFile = new File(mDir, new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.getDefault()).format(new Date()) + ".jpg");
mImageCapture.takePicture(mFile,
new ImageCapture.OnImageSavedListener() {
#Override
public void onImageSaved(#NonNull File file) {
mListOfPhotos.add(file.getAbsolutePath());
mAdapter.setmListOfPhotos(mListOfPhotos);
mRecyclerView.setAdapter(mAdapter);
actualNumberOfPhoto();
mRecyclerView.smoothScrollToPosition(mRecyclerView.getAdapter().getItemCount() - 1);
mAdapter.notifyDataSetChanged();
}
#Override
public void onError(#NonNull ImageCapture.ImageCaptureError imageCaptureError, #NonNull String message, #Nullable Throwable cause) {
String mMessage = "Photo capture failed: " + message;
Toast.makeText(CameraActivity.this, mMessage, Toast.LENGTH_SHORT).show();
assert cause != null;
cause.printStackTrace();
}
});
}
EDIT:
Code into actualNumberOfPhoto()
private void actualNumberOfPhoto(RecyclerView recyclerView) {
mNumberOfPhotoTV.setText(getResources().getString(R.string.minPhotos, mListOfPhotos.size()));
mIDDemande = mSharedPreferences.getInt(ConstantsClass.EXTRA_ID_APPLICATION, 0);
if (mIDDemande != 0) {
if (mListOfPhotos.size() > 0) {
mSendPhotoFAB.setVisibility(View.VISIBLE);
} else if (mListOfPhotos.size() < 1) {
mSendPhotoFAB.setVisibility(View.GONE);
}
} else if (mListOfPhotos.size() >= 6) {
mSendPhotoFAB.setVisibility(View.VISIBLE);
} else if (mListOfPhotos.size() < 6) {
mSendPhotoFAB.setVisibility(View.GONE);
}
}
Your code should be like this:
#Override
public void onImageSaved(#NonNull File file) {
mListOfPhotos.add(file.getAbsolutePath());
mAdapter.setmListOfPhotos(mListOfPhotos);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.smoothScrollToPosition(mListOfPhotos.size());
//mAdapter.notifyDataSetChanged();
}
I was trying out the new CameraX api to simply take images and every 2nd image(like 1st one is fine, 2nd one is not, 3rd fine, 4th is not) is turning out to be a green background (please see the image above)
private void startCamera() {
CameraX.unbindAll();
int aspRatioW = textureView.getWidth();
int aspRatioH = textureView.getHeight();
Rational asp = new Rational (aspRatioW, aspRatioH);
PreviewConfig previewConfig=new PreviewConfig.Builder()
.setLensFacing(lensFacing)
.build();
preview=new Preview(previewConfig);
preview.setOnPreviewOutputUpdateListener(new Preview.OnPreviewOutputUpdateListener() {
#Override
public void onUpdated(Preview.PreviewOutput output) {
ViewGroup viewGroup=(ViewGroup) textureView.getParent();
viewGroup.removeView(textureView);
viewGroup.addView(textureView, 0);
textureView.setSurfaceTexture(output.getSurfaceTexture());
updateTransform();
}
});
ImageCaptureConfig imageCaptureConfig=new ImageCaptureConfig.Builder()
.setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
.setTargetRotation(getWindowManager().getDefaultDisplay().getRotation())
.setTargetAspectRatio(asp)
.build();
final ImageCapture imgCap=new ImageCapture(imageCaptureConfig);
findViewById(R.id.camera_photoButton).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
File file=new File(Environment.getExternalStorageDirectory()+"/"+"Prixpi_"+System.currentTimeMillis()
+".jpg");
imgCap.takePicture(file, new ImageCapture.OnImageSavedListener() {
#Override
public void onImageSaved(#NonNull File file) {
String path=file.getAbsolutePath();
ScanImagePath obj=new ScanImagePath(path);
Log.d(TAG, "onImageSaved: path="+obj.getImagePath());
mRepo.insertImageTask(obj);
Toast.makeText(CameraActivity.this, "Image captured", Toast.LENGTH_SHORT).show();
}
#Override
public void onError(#NonNull ImageCapture.UseCaseError useCaseError, #NonNull String message, #Nullable Throwable cause) {
String msg = "Photo capture failed: " + message;
Toast.makeText(CameraActivity.this, msg,Toast.LENGTH_LONG).show();
if(cause != null){
cause.printStackTrace();
}
}
});
}
});
CameraX.bindToLifecycle((LifecycleOwner)this, imgCap, preview);
}
Not sure what I'm doing wrong, any help would be appreciated
P.S. the big chat bubbles at the bottom of the screen are an image (just like when you send an image via WhatsApp and other messaging apps)
I'm making a simple chatting app. The problem is, whenever I scroll to the top, the view comes back to the very bottom. Here's my OnBindViewHolder code (some parts are omitted because it's too long):
#Override
public void onBindViewHolder(final MessageViewHolder viewHolder, final int i) {
final ChatMessages c = messageList.get(i);
final String from_user = c.getFrom();
String message_type = c.getType();
if (currentUser.equals(from_user)) {
viewHolder.mydisplayName.setText(dummyright);
} else {
viewHolder.displayName.setText(dummyleft);
}
if (currentUser.equals(from_user)) {
leftLayout.setVisibility(View.VISIBLE);
rightLayout.setVisibility(View.GONE);
person = "leftLayout";
} else {
leftLayout.setVisibility(View.GONE);
rightLayout.setVisibility(View.VISIBLE);
person = "rightLayout";
}
if (message_type.equals("text")) {
//set visibility of TextViews and other elements according to which user is sending the message (left/right)
} else if (message_type.equals("image")) {
if (person.equals("leftLayout")) {
viewHolder.mymessageText.setVisibility(View.GONE);
viewHolder.myview_data.setVisibility(View.GONE);
viewHolder.mymessageImage.setVisibility(View.VISIBLE);
Cursor cursor = null;
final String tempUri = c.getDownload_link();
filename = null;
byte[] decodedString = Base64.decode(c.getMessage(), Base64.DEFAULT);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inSampleSize=512;
decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length,options);
try {
Glide.with(viewHolder.mymessageImage.getContext())
.asBitmap()
.load(decodedString)
.thumbnail(0.5f)
.into(viewHolder.mymessageImage);
decodedString=null;
} catch (Exception e) {
Log.e("chat image right", e.getMessage());
}
File file = null;
if (tempUri != null) {
file = new File(tempUri);
String path = file.getAbsolutePath();
if (tempUri.startsWith("content://")) {
try {
cursor = context.getContentResolver().query(Uri.parse(c.getDownload_link()), null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
cursor.close();
}
} else if (tempUri.startsWith("file://")) {
filename = file.getName();
}
viewHolder.mymessageImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new AlertDialog.Builder(context, android.R.style.Theme_Material_Light_Dialog_Alert);
} else {
builder = new AlertDialog.Builder(context);
}
builder.setTitle("Save Image")
.setMessage("Do you want to save this image?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
startSaveImageToGallery();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
});
} else {
}
} else if (person.equals("rightLayout")) {
//same as above but for the right layout
}
}
}
I've read a lot of questions about this issue and some of the answers said that it's caused by setting visibility inside onBindViewHolder. I don't know where else I would set them because my layouts' visibility are dependent on some data (in this case, who's sending the chats).
Edit: I've just tried my app several times and apparently it only jumps to the bottom when there are pictures being sent, especially when they're 600KB or more in size. I'm loading my images with Glide, they are stored in Base64 and converted to compressed Bitmaps. Do these images cause the messed up scrolling?
1.If the ImageView is wrap_content,set a fixed size value for it.
2.If the OnBindViewHolder method has other asyn operations which are relatived to the UI,deal with them before setData.
3.Check your code,if there are methods such as scroll to
I'm trying to use the library to perform volley download images from my server.
In my activity I add items dynamically and then realize the exchange of image at runtime.
Below is the code of the attempt to get the picture:
public void updateThumbnails(ArrayList<Book> arrBook,ArrayList<View> arrView){
if(arrBook.size()<= 0){
return;
}
if(arrView.size() <= 0){
return;
}
int intBooks = arrView.size();
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
for(int intIndex = 0; intIndex < intBooks; intIndex++){
View _view = arrView.get(intIndex);
final View _viewLoader = _view;
imageLoader.get(Const.START_REQUEST_BOOK_IMAGE + arrBook.get(intIndex).getId().toString() + ".jpg", new ImageLoader.ImageListener() {
#Override
public void onResponse(ImageLoader.ImageContainer imageContainer, boolean b) {
ImageView imgBook = (ImageView) _viewLoader.findViewById(R.id.img_book);
animationChangeImage(imageContainer.getBitmap(),imgBook);
}
#Override
public void onErrorResponse(VolleyError volleyError) {
}
});
TextView txtTitleBook = (TextView) _view.findViewById(R.id.name_book);
txtTitleBook.setVisibility(View.INVISIBLE);
}
}
You need to check that the returned bitmap (imageContainer.getBitmap()) isn't null before going ahead and assigning it.
Try and adding log prints to see if you're getting errors or a null bitmap, which could mean you're performing a bad request or server error, or perhaps the fault is in the animationChangeImage method if the bitmap is received successfully.
Did you try using the ImageRequest class? For example:
ImageRequest irq = new ImageRequest(imgUrl, new Response.Listener<Bitmap>() {
#Override
public void onResponse(Bitmap response) {
imView.setImageBitmap(response);
}
}, 0, 0, null, null);