تحميل قائمة بجميع الرسائل المرسله من المستخدم الى مستخدم اخر
في اي تطبيق محادثة سواء واتساب او ماسنجر او غيره يظهر في واجهة التطبيق الاشخاص الذين قمت بعمل محادثة معهم من قبل وليس جميع مستخدمي التطبيق اليس كذلك ؟ في مقالة اليوم سوف نعمل على هذه القائمه ونساعدكم على اظهار جميع المحادثات التي يقوم بها المستخدم مع مستخدم اخر في واجهة التطبيق .
لغه جافا من اكثر اللغات التي عليها طلب سواء في التعلم او في سوق العمل , والسبب يرجع في انه يمكنك من خلالها تطوير تطبيقات الاندرويد و عمل برامج سطح المكتب من خلال هذه اللغه ايضا اغلب الجامعات تقوم بتدريس هذه اللغه وهي لغه تعد من اللغات الصعبه وليست من اللغات السهله ولكن اذا اتقنت هذه اللغه بشكل جيد سوف اخبرك انه يمكنك تعلم اي لغه برمجه اخرى جديده لان java لغه من اللغات الصعبه وايضا بها تفاصيل كثيره جدا عكس اللغات التي تظهر جديده وتقدم مميزات معينه مثل لغة دارت الخاصه بفلاتر وهي بيئة تطوير تطبيقات الاندرويد والايفون وسطح المكتب بكود واحد .
لغه python وهي من اللغات المطلوبه جدا في الذكاء الاصطناعي في سوق العمل هذة اللغه قوية في مجالها ولكنها غير قويه مثل الجافا او بمعنى اخر ليس بصعوبة الجافا . ويقصد بذلك اه يمكنك تعلم هذه اللغه ولكن سوف يصعب عليك تعلم الجافا بعدها لذلك حاول البدء بالجوبا او c++ او اي لغات البرمجه الصعبه لكي تستطيع فهم اي لغه تظهر بعد ذلك ونحن في موقعنا نقدم لكم الكثير والكثير من الاكواد البرمجيه المختلفه والمتنوعه. في لغه البايثون و في لغه الجافا وغيرها من اللغات الكثيره يحتوي الموقع الخاص بنا على العديد من البرامج والادوات والاكواد الخاصه للمطورين ويهدف موقعنا الى نشر ثقافه البرمجه لدي المحتوى العربي وذلك لان هذا المحتوى تقريبا مظلوم في هذا المجال و لا يوجد به الكثير من االاكواد والشروحات لذلك نعمل بكل جهدنا على توفير لكم كل ما تحتاجونه في مختلف لغات البرمجه وفي الشروحات و في تطوير تطبيقات الهواتف الذكيه.
إضافة ProgressBar في تطبيقك لتحميل الرسائل
في البداية سوف ننتقل الى التصميم لعمل ProgressBar في الواجهه يظهر عندما تقوم بفتح التطبيق ويختفي عندما يتم تحميل البيانات الخاصه بك من السيرفر
تصميم لمظهر عرض بيانات المستخدم
حفظ بيانات الرسائل داخل Constants
الان سوف ننتقل الى ملف Constants لكي نقوم بعمل بعض المتغيرات التي سوف نحفظ الرسائل بداخلها
عمل onClick للRecyclerView الخاصة بالدردشة في الصفحة الرئيسية
هنا نقوم بعمل انترفيس وعندما يتم النقر عليه ينقل المستخدم الى محتوى الرساله وهنا فقط نقوم بتمرير كلاس المستخدم بداخل النقره .
public interface ConversionListener {
void onConversionClick(User user);
}
عرض الرسائل في collection بشكل منظم وتحديث البيانات
الان في مرحلة عرض الرسائل سوف نقوم بعمل مجموعة من الmethodes وهي الاولى لرفع البيانات على الفايربيز والثانيه لتحديث البيانات من قواعد البيانات اي عندما يتم عمل محادثة مع اي طرف يتم تحديثها بشكل مستمر لكي تظهر بعد ذلك اذا لم تكن البيانات تساوي 0 قم بحفظها داخل shared باسم userid بمعنى يقوم بإحضار الرسائل من هذه الميثود التي اسفلها checkForConversionRemotely ويحفظها اذا لم تكن فارغه لكي يتم عرضها في الواجهه ايضا .
ChatActivity.class
// ميثود لرفع البيانات على الفايربيز
private void addConversion(HashMap<String , Object> conversion){
firebaseFirestore.collection(Constants.KEY_COLLECTION_CONVERSATION).add(conversion).addOnSuccessListener(documentReference -> conversionId = documentReference.getId());
}
// ميثود لتحديث البيانات على الفايربيز لعدم تكرار كثرة المحادثات
private void updateConversion(String message) {
DocumentReference documentReference =
firebaseFirestore.collection(Constants.KEY_COLLECTION_CONVERSATION).document(conversionId);
documentReference.update(Constants.KEY_LAST_MESSAGE , message,
Constants.KEY_TIMESTAMP , new Date());
}
//
private void checkForConversion() {
if (chatMessageList.size() != 0) {
checkForConversionRemotely(
preferenceManager.getString(Constants.KEY_USER_ID),receiverUser.id );
checkForConversionRemotely(
receiverUser.id , preferenceManager.getString(Constants.KEY_USER_ID)
);
}
}
// هنا يتم عرض البيانات الخاص بالمستخدم مع المستخدمين الذين قام بالمحادثة معهم من قبل
private void checkForConversionRemotely (String senderId , String receiverId) {
firebaseFirestore.collection(Constants.KEY_COLLECTION_CONVERSATION).whereEqualTo(Constants.KEY_SENDER , senderId)
.whereEqualTo(Constants.KEY_RECEIVER , receiverId).get().addOnCompleteListener(completionListener);
}
private final OnCompleteListener<QuerySnapshot> completionListener = task -> {
if (task.isSuccessful() && task.getResult() != null && task.getResult().getDocuments().size() > 0){
DocumentSnapshot documentSnapshot = task.getResult().getDocuments().get(0);
conversionId = documentSnapshot.getId();
}
};
كلاس لتخزين البيانات وتمريرها من مكان لاخر
قم بإضافة هذة البيانات داخل كلاس الشات بين الطرفين الاول والثاني .
ChatMessage.class
public class ChatMessage {
public String senderId, receiverId , message , dataTime;
public Date dataObject;
public String conversionId , conversionName , conversionImage ;
}
عمل Adapter للرسائل المرسلة من طرف الى الاخر وعرضها في الشاشة الرئيسيه
في هذا الجزء سوف نقوم بعمل Adapter للرسائل بين الطرف الاول والاخر ويتم عرضها في الشاشة الرئيسية وهيا الMain .
public class AdapterRecentConversations extends RecyclerView.Adapter<AdapterRecentConversations.ConversionHolder> {
private final List<ChatMessage> chatMessageList;
private final ConversionListener conversionListener;
public AdapterRecentConversations(List<ChatMessage> chatMessageList , ConversionListener conversionListener) {
this.chatMessageList = chatMessageList;
this.conversionListener = conversionListener;
}
@NonNull
@Override
public ConversionHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ConversionHolder(ItemContainerRecentConversionBinding.inflate(LayoutInflater.from(parent.getContext()) , parent , false));
}
@Override
public void onBindViewHolder(@NonNull ConversionHolder holder, int position) {
holder.setData(chatMessageList.get(position));
}
@Override
public int getItemCount() {
return chatMessageList.size();
}
// كلاس الهولد وتعريف المتغيرات بداخله
class ConversionHolder extends RecyclerView.ViewHolder {
ItemContainerRecentConversionBinding binding ;
ConversionHolder(ItemContainerRecentConversionBinding itemContainerRecentConversionBinding) {
super(itemContainerRecentConversionBinding.getRoot());
binding = itemContainerRecentConversionBinding;
}
void setData(ChatMessage chatMessage) {
binding.imageProfile.setImageBitmap(getConversionImage(chatMessage.conversionImage));
binding.textName.setText(chatMessage.conversionName);
binding.textRecentMessage.setText(chatMessage.message);
binding.getRoot().setOnClickListener(v -> {
User user = new User();
user.id = chatMessage.conversionId;
user.name = chatMessage.conversionName;
user.image = chatMessage.conversionImage;
conversionListener.onConversionClick(user);
});
}
}
// عرض الصورة والتعامل معها
private Bitmap getConversionImage(String encodeImage){
byte [] bytes = Base64.decode(encodeImage , Base64.DEFAULT);
return BitmapFactory.decodeByteArray(bytes , 0 , bytes.length);
}
}
عرض البيانات في الصفحة الرئيسية للتطبيق
في النهاية انتقل الى الMainActivity او الكلاس الذي يعمل في بداية التطبيق لكي نقوم بإظهار الرسائل التي تحدث بين المستخدم مع المستخدمين الاخرين في الواجهه وكل ميثود يوجد كومنت توضيحي للوظيفة التي تقوم بها .
MainActivity.class
public class MainActivity extends AppCompatActivity implements ConversionListener {
private ActivityMainBinding binding;
private PreferenceManager preferenceManager;
private List<ChatMessage> conversations ;
private AdapterRecentConversations adapter;
private FirebaseFirestore firestore;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
preferenceManager = new PreferenceManager(getApplicationContext());
loadUserData();
get_token();
listener();
init();
listenConversation();
}
// تعريف المتغيرات
private void init() {
conversations = new ArrayList<>();
adapter = new AdapterRecentConversations(conversations , MainActivity.this);
binding.conversationRecyclerview.setAdapter(adapter);
firestore = FirebaseFirestore.getInstance();
}
// الازرار والانتقالات داخل الصفحة
private void listener() {
binding.imageSignOut.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loading(true);
sign_out();
}
});
binding.faNewChat.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext() , UserActivity.class));
}
});
}
// عرض اسم المستخدم
private void loadUserData() {
binding.tvName.setText(preferenceManager.getString(Constants.KEY_NAME));
get_image_from_preference();
}
// الحصول على البينات من eventListener اذا كانت تطابق بيانات المستخدم الحالي للمرسل والمستقبل
private void listenConversation() {
firestore.collection(Constants.KEY_COLLECTION_CONVERSATION).
whereEqualTo(Constants.KEY_SENDER , preferenceManager.getString(Constants.KEY_USER_ID))
.addSnapshotListener(eventListener);
firestore.collection(Constants.KEY_COLLECTION_CONVERSATION)
.whereEqualTo(Constants.KEY_RECEIVER , preferenceManager.getString(Constants.KEY_USER_ID))
.addSnapshotListener(eventListener);
}
// عرض الاشخاص الذين تمت المحادثة معهم واظهار اخر رسالة تمت بينكم
private final EventListener<QuerySnapshot> eventListener = (value , error) -> {
if (error != null) {
return;
}
if (value != null) {
for (DocumentChange documentChange : value.getDocumentChanges()) {
if (documentChange.getType() == DocumentChange.Type.ADDED) {
String senderId = documentChange.getDocument().getString(Constants.KEY_SENDER);
String receiverId = documentChange.getDocument().getString(Constants.KEY_RECEIVER);
ChatMessage chatMessage = new ChatMessage();
chatMessage.senderId = senderId;
chatMessage.receiverId = receiverId;
if (preferenceManager.getString(Constants.KEY_USER_ID).equals(senderId)) {
chatMessage.conversionImage = documentChange.getDocument().getString(Constants.KEY_RECEIVER_IMAGE);
chatMessage.conversionName = documentChange.getDocument().getString(Constants.KEY_RECEIVER_NAME);
chatMessage.conversionId = documentChange.getDocument().getString(Constants.KEY_RECEIVER);
} else {
chatMessage.conversionImage = documentChange.getDocument().getString(Constants.KEY_SENDER_IMAGE);
chatMessage.conversionName = documentChange.getDocument().getString(Constants.KEY_SENDER_NAME);
chatMessage.conversionId = documentChange.getDocument().getString(Constants.KEY_SENDER);
}
chatMessage.message = documentChange.getDocument().getString(Constants.KEY_LAST_MESSAGE);
chatMessage.dataObject = documentChange.getDocument().getDate(Constants.KEY_TIMESTAMP);
conversations.add(chatMessage);
} else if (documentChange.getType() == DocumentChange.Type.MODIFIED) {
for (int i = 0; i < conversations.size(); i++) {
String senderId = documentChange.getDocument().getString(Constants.KEY_SENDER);
String receiverId = documentChange.getDocument().getString(Constants.KEY_RECEIVER);
if (conversations.get(i).senderId.equals(senderId) && conversations.get(i).receiverId.equals(receiverId)) {
conversations.get(i).message = documentChange.getDocument().getString(Constants.KEY_LAST_MESSAGE);
conversations.get(i).dataObject = documentChange.getDocument().getDate(Constants.KEY_TIMESTAMP);
break;
}
}
}
}
Collections.sort(conversations, (obj1 , obj2) -> obj2.dataObject.compareTo(obj1.dataObject));
adapter.notifyDataSetChanged();
binding.conversationRecyclerview.smoothScrollToPosition(0);
binding.conversationRecyclerview.setVisibility(View.VISIBLE);
binding.progressBar.setVisibility(View.GONE);
}
};
// الحصول على توكن المستخدم
private void get_token() {
FirebaseMessaging.getInstance().getToken().addOnSuccessListener(this::updateToken);
}
// عرض صورة المستخدم من الفايربيز وحفظها في الشيرد
private void get_image_from_preference () {
byte[] bytes = android.util.Base64.decode(preferenceManager.getString(Constants.KEY_IMAGE) , android.util.Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes , 0 , bytes.length);
binding.imageProfile.setImageBitmap(bitmap);
}
// ميثود لعرض التوست message
private void toast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
// تحديث التوكن عند عملية تسجيل الدخول
private void updateToken(String token) {
FirebaseFirestore firestore = FirebaseFirestore.getInstance();
DocumentReference documentReference = firestore.collection(Constants.KEY_COLLECTION_USERS).document(preferenceManager.getString(Constants.KEY_USER_ID));
documentReference.update(Constants.KEY_FCM_TOKEN , token).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
toast(getString(R.string.token_updated_successfully));
}
}) .addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
toast(e.getLocalizedMessage());
}
});
}
// تسجيل الخروج وحذف التوكن من الفايربيز
private void sign_out() {
toast(getString(R.string.Sign_out_successful));
FirebaseFirestore firestore = FirebaseFirestore.getInstance();
DocumentReference documentReference = firestore.collection(Constants.KEY_COLLECTION_USERS).document(preferenceManager.getString(Constants.KEY_USER_ID));
HashMap<String , Object> update = new HashMap<>();
update.put(Constants.KEY_FCM_TOKEN , FieldValue.delete());
documentReference.update(update).addOnSuccessListener( unused-> {
preferenceManager.clear();
onBackPressed();
finish();
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
toast(e.getLocalizedMessage());
}
});
}
// تاثير التحميل
protected void loading (Boolean isLoading) {
if (isLoading) {
binding.progressbar.setVisibility(View.VISIBLE);
} else {
binding.progressbar.setVisibility(View.INVISIBLE);
}
}
@Override
public void onConversionClick(User user) {
Intent intent = new Intent(getApplicationContext() , ChatActivity.class);
intent.putExtra(Constants.KEY_USER , user);
startActivity(intent);
}
}