I have problem, because I can't send images for other side, it duplicates or sends empty message, but normal messages work fine. I've tried many tutorials and changing some classes, but nothing really worked
here's my recycler view class:
public final class ChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<ChatMessage> messages;
private Bitmap profileImage;
private final String senderId;
private static final int VIEW_TYPE_SENT = 1;
private static final int VIEW_TYPE_RECEIVED = 2;
public void setReceiverProfileImage(Bitmap bitmap) {
this.profileImage = bitmap;
}
public ChatAdapter(List<ChatMessage> messages, Bitmap profileImage, String senderId) {
this.messages = messages;
this.profileImage = profileImage;
this.senderId = senderId;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return (viewType == VIEW_TYPE_SENT ? new SentMessageViewHolder(
ItemContainerSentMessageBinding.inflate(
LayoutInflater.from(parent.getContext()),
parent,
false)
) : new ReceivedMessageViewHolder(
ItemContainerReceivedMessageBinding.inflate(
LayoutInflater.from(parent.getContext()),
parent,
false)
));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == VIEW_TYPE_SENT) {
((SentMessageViewHolder) holder).setData(messages.get(position));
} else {
((ReceivedMessageViewHolder) holder).setData(messages.get(position), profileImage);
}
}
@Override
public int getItemCount() {
return messages.size();
}
@Override
public int getItemViewType(int position) {
return (messages.get(position).getSenderId().equals(senderId) ? VIEW_TYPE_SENT : VIEW_TYPE_RECEIVED);
}
public static class SentMessageViewHolder extends RecyclerView.ViewHolder {
private final ItemContainerSentMessageBinding binding;
public SentMessageViewHolder(ItemContainerSentMessageBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
void setData(ChatMessage message) {
binding.textMessage.setText(message.getMessage());
binding.textDateTime.setText(message.getDateTime());
binding.image.setImageBitmap(message.getImage());
}
}
public static class ReceivedMessageViewHolder extends RecyclerView.ViewHolder {
private final ItemContainerReceivedMessageBinding binding;
public ReceivedMessageViewHolder(ItemContainerReceivedMessageBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
void setData(ChatMessage message, Bitmap bitmap) {
binding.textMessage.setText(message.getMessage());
binding.textDateTime.setText(message.getDateTime());
if (bitmap != null) {
binding.imageProfile.setImageBitmap(bitmap);
}
binding.image.setImageBitmap(message.getImage());
}
}
}
Here's received message:
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imageProfile"
android:layout_width="25dp"
android:layout_height="25dp"
android:background="@drawable/background_image"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="@id/textMessage"
app:layout_constraintStart_toStartOf="parent"
app:riv_oval="true"/>
<TextView
android:id="@+id/textMessage"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginLeft="4dp"
android:background="@drawable/background_received_message"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
app:layout_constraintWidth_max="wrap"
android:textColor="@color/white"
android:textSize="13sp"
app:layout_constraintStart_toEndOf="@id/imageProfile"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.75"/>
<ImageView
android:id="@+id/image"
android:background="@drawable/background_sent_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:layout_marginStart="4dp"
android:maxWidth="250dp"
android:maxHeight="250dp"
app:layout_constraintStart_toEndOf="@id/imageProfile"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/textDateTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="@color/secondary_text"
android:textSize="8sp"
app:layout_constraintStart_toStartOf="@id/textMessage"
app:layout_constraintTop_toBottomOf="@id/textMessage"/>
and picking image activity:
private final ActivityResultLauncher<Intent> pickImage = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() != RESULT_OK) return;
if (result.getData() == null) return;
Uri imageUri = result.getData().getData();
try {
InputStream inputStream = getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
this.encodingImage = encodeImage(bitmap);
sendMessage();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
});
and here create ChatMessage object (eventListener):
private final EventListener<QuerySnapshot> eventListener = (value, error) -> {
if (error != null) {
return;
}
if (value != null) {
int count = messages.size();
for (DocumentChange documentChange : value.getDocumentChanges()) {
if (documentChange.getType() == DocumentChange.Type.ADDED) {
ChatMessage chatMessage = new ChatMessage(
documentChange.getDocument().getString(Constants.KEY_SENDER_ID),
documentChange.getDocument().getString(Constants.KEY_RECEIVER_ID),
documentChange.getDocument().getString(Constants.KEY_MESSAGE),
getReadableDateTime(documentChange.getDocument().getDate(Constants.KEY_TIMESTAMP)),
documentChange.getDocument().getDate(Constants.KEY_TIMESTAMP)
);
if (!encodingImage.isEmpty()) {
byte[] decodedString = Base64.decode(encodingImage, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
chatMessage.setImage(decodedByte);
}
messages.add(chatMessage);
}
}
Collections.sort(messages, Comparator.comparing(ChatMessage::getDate));
if (count == 0) {
chatAdapter.notifyDataSetChanged();
} else {
chatAdapter.notifyItemRangeInserted(messages.size(), messages.size());
binding.chatRecyclerView.smoothScrollToPosition(messages.size() - 1);
}
binding.chatRecyclerView.setVisibility(View.VISIBLE);
}
binding.progressBar.setVisibility(View.GONE);
if (conversionId == null) checkForConversion();
};
sendMessage method:
private void sendMessage() {
Map<String, Object> message = new HashMap<>();
message.put(Constants.KEY_SENDER_ID, preferenceManager.getString(Constants.KEY_USER_ID));
message.put(Constants.KEY_RECEIVER_ID, user.getId());
message.put(Constants.KEY_MESSAGE, binding.inputMessage.getText().toString());
if (!encodingImage.isEmpty()) {
message.put(Constants.KEY_IMAGE_MESSAGE, encodingImage);
}
message.put(Constants.KEY_TIMESTAMP, new Date());
db.collection(Constants.KEY_COLLECTION_CHAT).add(message);
if (conversionId != null) {
updateConversion(binding.inputMessage.getText().toString());
} else {
Map<String, Object> conversion = new HashMap<>();
conversion.put(Constants.KEY_SENDER_ID, preferenceManager.getString(Constants.KEY_USER_ID));
conversion.put(Constants.KEY_SENDER_NAME, preferenceManager.getString(Constants.KEY_NAME));
conversion.put(Constants.KEY_SENDER_IMAGE, preferenceManager.getString(Constants.KEY_IMAGE));
conversion.put(Constants.KEY_RECEIVER_ID, user.getId());
conversion.put(Constants.KEY_RECEIVER_NAME, user.getName());
conversion.put(Constants.KEY_RECEIVER_IMAGE, user.getImage());
conversion.put(Constants.KEY_LAST_MESSAGE, binding.inputMessage.getText().toString());
conversion.put(Constants.KEY_TIMESTAMP, new Date());
addConversion(conversion);
}
if (!isReceiverAvaible) {
try {
JSONArray tokens = new JSONArray();
tokens.put(user.getToken());
JSONObject data = new JSONObject();
data.put(Constants.KEY_USER_ID, preferenceManager.getString(Constants.KEY_USER_ID));
data.put(Constants.KEY_NAME, preferenceManager.getString(Constants.KEY_NAME));
data.put(Constants.KEY_FCM_TOKEN, preferenceManager.getString(Constants.KEY_FCM_TOKEN));
data.put(Constants.KEY_MESSAGE, binding.inputMessage.getText().toString());
JSONObject body = new JSONObject();
body.put(Constants.REMOTE_MSG_DATA, data);
body.put(Constants.REMOTE_MSG_REGISTRATION_IDS, tokens);
sendNotification(body.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
binding.inputMessage.setText(null);
}
listenMessages method:
private void listenMessages() {
db.collection(Constants.KEY_COLLECTION_CHAT)
.whereEqualTo(Constants.KEY_SENDER_ID, preferenceManager.getString(Constants.KEY_USER_ID))
.whereEqualTo(Constants.KEY_RECEIVER_ID, user.getId())
.addSnapshotListener(eventListener);
db.collection(Constants.KEY_COLLECTION_CHAT)
.whereEqualTo(Constants.KEY_SENDER_ID, user.getId())
.whereEqualTo(Constants.KEY_RECEIVER_ID, preferenceManager.getString(Constants.KEY_USER_ID))
.addSnapshotListener(eventListener);
}
private String encodeImage(Bitmap bitmap) {
int previewWidth = 300;
int previewHeight = bitmap.getHeight() * previewWidth / bitmap.getWidth();
Bitmap previewBitmap = Bitmap.createScaledBitmap(bitmap, previewWidth, previewHeight, false);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
previewBitmap.compress(Bitmap.CompressFormat.JPEG, 50, byteArrayOutputStream);
return Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT);
}
Please help and thanks!