I am creating an android application for my fyp i have compelete all my code but stuck with firebase push notifications.There are two different users of this application one is customer and other one is shop keeper. I tried to implement push notification in my shop keeper app. In shop keeper app when he accept the order of customer i want to send notification in customer app i tried with this code but unable to send notification. I am using firebase realtime database for this application.
I have tried last 3 days to solve this problem but unable to solve this problem. I also search on youtube and stackover flow but can not get any satisfactory solution.
Code i write to implement firebase push notification is mentioned.
fragmentOrder
public class fragmentOrders extends Fragment {
private View orderView;
private CompositeDisposable compositeDisposable = new CompositeDisposable();
private IFCMService ifcmService;
private DatabaseReference tokenRef;
public fragmentOrders() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
orderView = inflater.inflate(R.layout.fragment_orders, container, false);
ifcmService = RetrofitFCMClient.getInstance().create(IFCMService.class);
tokenRef = FirebaseDatabase.getInstance().getReference(common.TOKEN_REF);
return orderView;
}
#Override
public void onStop() {
super.onStop();
compositeDisposable.clear();
}
private void showOrders() {
FirebaseRecyclerOptions<OrderModel> options = new FirebaseRecyclerOptions.Builder<OrderModel>()
.setQuery(orderRef,OrderModel.class)
.build();
FirebaseRecyclerAdapter<OrderModel,OrderViewHolder> adapter = new FirebaseRecyclerAdapter<OrderModel, OrderViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull OrderViewHolder holder, int position, #NonNull OrderModel model) {
holder.CustomerName.setText(model.getName());
holder.CustomerNumber.setText(model.getNodePhone());
holder.ShippingAddress.setText(model.getAddress());
holder.OrderDateTime.setText(model.getDate() + " , " + model.getTime());
holder.TotalPrice.setText(model.getTotalprice());
holder.btnConfirmOrder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.cancelLayout.setVisibility(View.GONE);
holder.btnConfirmOrder.setText(model.getUid());
confirmOrder(model);
}
});
}
#NonNull
#Override
public OrderViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(getContext()).inflate(R.layout.view_order_items,parent,false);
return new OrderViewHolder(view);
}
};
orderList.setAdapter(adapter);
adapter.startListening();
}
}
});
}
private void confirmOrder(OrderModel model) {
tokenRef.child(model.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
TokenModel tokenModel = dataSnapshot.getValue(TokenModel.class);
Map<String,String> notiData = new HashMap<>();
notiData.put(common.NOTI_TITLE,"Order Confirmed");
notiData.put(common.NOTI_CONTENT,"Your Shopping Order is Confirmed and Shipped");
//ShowNotification(tokenModel,notiData);
FCMSendData sendData = new FCMSendData(tokenModel.getToken(),notiData);
compositeDisposable.add(ifcmService.sendNotification(sendData)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<FCMResponse>() {
#Override
public void accept(FCMResponse fcmResponse) throws Exception {
if (fcmResponse.getSuccess() == 1){
Toast.makeText(getContext(), "Order confirmed success", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(getContext(), "Order confirmed success but faild to send notification", Toast.LENGTH_SHORT).show();
}
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show();
}
})
);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getContext(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public class OrderViewHolder extends RecyclerView.ViewHolder{
TextView CustomerName,CustomerNumber,ShippingAddress,OrderDateTime,TotalPrice;
Button btnViewOrderProducts,btnConfirmOrder,btnCancelOrder,btnCallCustomer;
RelativeLayout cancelLayout;
public OrderViewHolder(#NonNull View itemView) {
super(itemView);
CustomerName = itemView.findViewById(R.id.customer_name);
CustomerNumber = itemView.findViewById(R.id.customer_phone);
ShippingAddress = itemView.findViewById(R.id.customer_shipping_address);
OrderDateTime = itemView.findViewById(R.id.order_date_time);
btnViewOrderProducts = itemView.findViewById(R.id.btn_view_order_product);
TotalPrice = itemView.findViewById(R.id.order_total_price);
btnConfirmOrder = itemView.findViewById(R.id.btn_confirm_order);
btnCancelOrder = itemView.findViewById(R.id.btn_cancel_order);
btnCallCustomer = itemView.findViewById(R.id.btn_call_customer);
cancelLayout = itemView.findViewById(R.id.canel_layout);
}
}
}
common
public class common {
public static final String NOTI_TITLE = "title";
public static final String NOTI_CONTENT = "content";
public static final String TOKEN_REF = "Tokens";
public static void showNotification(Context context, int id, String title, String content, Intent intent) {
PendingIntent pendingIntent = null;
if (intent !=null){
pendingIntent = PendingIntent.getActivity(context,id,intent,PendingIntent.FLAG_UPDATE_CURRENT);
String NOTIFICATION_CHANNEL_ID = "Designer_Club_App";
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID
, "Designer Club", NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.setDescription("Designer Club");
notificationChannel.enableLights(true);
notificationChannel.setVibrationPattern(new long[]{0,1000,500,1000});
notificationChannel.enableVibration(true);
notificationChannel.setLightColor(android.R.color.white);
notificationManager.createNotificationChannel(notificationChannel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle(title)
.setContentText(content)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
if (pendingIntent != null){
builder.setContentIntent(pendingIntent);
Notification notification = builder.build();
notificationManager.notify(id,notification);
}
}
}
}
FCMResponse
import java.util.List;
public class FCMResponse {
private long multicast_id;
private int success,failure,canonical_ids;
private List<FCMResult> results;
private long message_id;
public FCMResponse() {
}
public long getMulticast_id() {
return multicast_id;
}
public void setMulticast_id(long multicast_id) {
this.multicast_id = multicast_id;
}
public int getSuccess() {
return success;
}
public void setSuccess(int success) {
this.success = success;
}
public int getFailure() {
return failure;
}
public void setFailure(int failure) {
this.failure = failure;
}
public int getCanonical_ids() {
return canonical_ids;
}
public void setCanonical_ids(int canonical_ids) {
this.canonical_ids = canonical_ids;
}
public List<FCMResult> getResults() {
return results;
}
public void setResults(List<FCMResult> results) {
this.results = results;
}
public long getMessage_id() {
return message_id;
}
public void setMessage_id(long message_id) {
this.message_id = message_id;
}
}
FCMResult
public class FCMResult {
private String message_id;
public FCMResult() {
}
public String getMessage_id() {
return message_id;
}
public void setMessage_id(String message_id) {
this.message_id = message_id;
}
}
FCMSendData
import java.util.Map;
public class FCMSendData {
private String to;
private Map<String,String> data;
public FCMSendData(String to, Map<String, String> data) {
this.to = to;
this.data = data;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public Map<String, String> getData() {
return data;
}
public void setData(Map<String, String> data) {
this.data = data;
}
}
IFCMService
import io.reactivex.Observable;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;
public interface IFCMService {
#Headers({
"Content-Type:application/json",
"Authorization:key=AAAAzkiH50E:APA91bETfnykxzAHx7Q4g5EFcPqZRHuyWi8S72OlnzFvxY4x_9o5MWl-BuxSB2ZUYt73Im1RJsOb55d7cTe3IPZR4fLIAaoJd_CaH1THCq3lxV4Rs6DfDdTtrC2HgIKNEgON2rD2ICGb"
})
#POST("fcm/send")
Observable<FCMResponse> sendNotification(#Body FCMSendData body);
}
RetrofitFCMClient
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitFCMClient {
private static Retrofit instance;
public static Retrofit getInstance(){
if (instance == null)
instance = new Retrofit.Builder()
.baseUrl("https://fcm.googleapis.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return instance;
}
}
MyFCMService
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFCMService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String,String> dataRecv = remoteMessage.getData();
if (dataRecv != null){
common.showNotification(this,new Random().nextInt(),
dataRecv.get(common.NOTI_TITLE),
dataRecv.get(common.NOTI_CONTENT),
null);
}
}
#Override
public void onNewToken(String s) {
super.onNewToken(s);
common.updateToken(this,s);
}
}
dependencies
implementation 'com.google.firebase:firebase-auth:19.3.0'
implementation 'com.google.firebase:firebase-database:19.2.1'
implementation 'com.google.firebase:firebase-messaging:20.1.4'
implementation 'com.google.firebase:firebase-storage:19.1.1'
implementation 'com.firebaseui:firebase-ui-database:5.0.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.9'
manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.designerclubadmin">
<application
<service android:name=".services.MyFCMService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
you should updateTokens in mainActivity in serverAPP like the Client App
the same in two app
like this
private void GotoHomeActivity(ServerUserModel serverUserModel) {
FirebaseInstanceId.getInstance()
.getInstanceId()
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MainActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
dialog.dismiss();
common.currentServerUser = serverUserModel;
startActivity(new Intent(MainActivity.this , HomeActivity.class));
finish();
}
}).addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
dialog.dismiss();
common.currentServerUser = serverUserModel;
//this what i talk about (Update Token)
common.UpdateToken(MainActivity.this, task.getResult().getToken());
startActivity(new Intent(MainActivity.this , HomeActivity.class));
finish();
}
});
}
UpdateToken in Common Class
public static void UpdateToken(Context context, String newToken) {
FirebaseDatabase.getInstance()
.getReference(common.TOKEN_REF)
.child(common.currentServerUser.getUid())
.setValue(new TokenModel(common.currentServerUser.getPhone() , newToken))
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(context, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
I am working with paging library and I am struggling with the LiveData PagedList.
My paginated list is working properly but there is an scenario where it is not. I have RecyclerView + SwipeRefreshLayout when data is already shown in the list and I disable network and I try to swipe refresh all the data in the list is removed. How can I avoid that?
public class InterestsViewModel extends ViewModel {
private LiveData<PagedList<InterestItem>> mListInterests;
private CompositeDisposable mCompositeDisposable = new CompositeDisposable();
private static final int PAGE_SIZE = 15;
private GroupsInterestsDataSourceFactory mGroupsInterestsDataSourceFactory;
public InterestsViewModel() {
Executor executor = Executors.newFixedThreadPool(5);
mGroupsInterestsDataSourceFactory = new GroupsInterestsDataSourceFactory(mCompositeDisposable);
PagedList.Config config = new PagedList.Config.Builder()
.setPageSize(PAGE_SIZE)
.setInitialLoadSizeHint(PAGE_SIZE)
.setEnablePlaceholders(true)
.build();
mListInterests = new LivePagedListBuilder<>(mGroupsInterestsDataSourceFactory,config)
.setFetchExecutor(executor)
.build();
}
public void retry() {
mGroupsInterestsDataSourceFactory.getGroupsInterestsDataSource().getValue().retry();
}
public void refresh() {
mGroupsInterestsDataSourceFactory.getGroupsInterestsDataSource().getValue().invalidate();
}
public LiveData<NetworkState> getNetworkState() {
return Transformations.switchMap(mGroupsInterestsDataSourceFactory.getGroupsInterestsDataSource(), new Function<GroupsInterestsDataSource, LiveData<NetworkState>>() {
#Override
public LiveData<NetworkState> apply(GroupsInterestsDataSource input) {
return input.getNetworkState();
}
});
}
public LiveData<NetworkState> getRefreshState() {
return Transformations.switchMap(mGroupsInterestsDataSourceFactory.getGroupsInterestsDataSource(), new Function<GroupsInterestsDataSource, LiveData<NetworkState>>() {
#Override
public LiveData<NetworkState> apply(GroupsInterestsDataSource input) {
return input.getInitialLoad();
}
});
}
public LiveData<PagedList<InterestItem>> getListInterests() {
return mListInterests;
}
#Override
protected void onCleared() {
super.onCleared();
mCompositeDisposable.dispose();
}
}
From the the fragment:
private void initAdapter() {
mAdapter = new InterestsAdapter(this);
mListInterest.setAdapter(mAdapter);
mInterestsViewModel.getListInterests().observe(this, new Observer<PagedList<InterestItem>>() {
#Override
public void onChanged(#Nullable PagedList<InterestItem> interestItems) {
mAdapter.submitList(interestItems);
}
});
mInterestsViewModel.getNetworkState().observe(this, new Observer<NetworkState>() {
#Override
public void onChanged(#Nullable NetworkState networkState) {
mAdapter.setNetworkState(networkState);
}
});
mInterestsViewModel.getRefreshState().observe(this, new Observer<NetworkState>() {
#Override
public void onChanged(#Nullable NetworkState networkState) {
if (networkState != null) {
if (mAdapter.getCurrentList() != null) {
if (networkState.getStatus()
== NetworkState.LOADED.getStatus() || networkState.getStatus()
== Status.FAILED)
mIsRefreshing = false;
if (mAdapter.getCurrentList().size() > 0) {
mSwipeRLInterests.setRefreshing(networkState.getStatus()
== NetworkState.LOADING.getStatus());
}
}
setInitialLoadingState(networkState);
}
}
});
}
#Override
public void retry() {
mInterestsViewModel.retry();
}
private void initSwipeToRefresh() {
mSwipeRLInterests.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mIsRefreshing = true;
mInterestsViewModel.refresh();
}
});
mSwipeRLInterests.setColorSchemeColors(getResources().getColor(R.color.colorPrimaryDark)
, getResources().getColor(R.color.colorPrimary)
, getResources().getColor(R.color.colorPrimaryDark));
}
I am using quickblox for my android application. I am able to register, login user, even add custom objects and retrieve them from the quick-blox server, but in chatting listing screen my count is coming wrong.
I am getting issue with unread count
Here is my code flow:-
public class ConversationFragment extends Fragment implements Observer, DialogsManager.ManagingDialogsCallbacks {
ConversationViewModel conversationViewModel;
FragmentConversationBinding binding;
QBChatDialogMessageListener allDialogsMessagesListener;
SystemMessagesListener systemMessagesListener;
QBSystemMessagesManager systemMessagesManager;
QBIncomingMessagesManager incomingMessagesManager;
private DialogsManager dialogsManager;
public ConversationFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_conversation, container, false);
getActivity().getWindow().setBackgroundDrawableResource(R.drawable.bg_img);
View view = binding.getRoot();
systemMessagesListener = new SystemMessagesListener();
dialogsManager = new DialogsManager();
return view;
}
private void setUpModel() {
Bundle mBundle = getArguments();
if (mBundle != null) {
conversationViewModel = new ConversationViewModel(getActivity(), binding, getArguments().getString("DialogIdData"));
} else {
conversationViewModel = new ConversationViewModel(getActivity(), binding, "");
}
binding.setConversationViewModel(conversationViewModel);
setUpObserver(conversationViewModel);
}
private void setUpObserver(ConversationViewModel observer) {
observer.addObserver(this);
}
#Override
public void update(Observable o, Object arg) {
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onResume() {
super.onResume();
setUpModel();
}
#Override
public void onPause() {
super.onPause();
unregisterQbChatListeners();
}
public void unregisterQbChatListeners() {
if (incomingMessagesManager != null) {
incomingMessagesManager.removeDialogMessageListrener(allDialogsMessagesListener);
}
if (systemMessagesManager != null) {
systemMessagesManager.removeSystemMessageListener(systemMessagesListener);
}
dialogsManager.removeManagingDialogsCallbackListener(this);
}
#Override
public void onDialogCreated(QBChatDialog chatDialog) {
}
#Override
public void onDialogUpdated(String chatDialog) {
}
#Override
public void onNewDialogLoaded(QBChatDialog chatDialog) {
}
private class SystemMessagesListener implements QBSystemMessageListener {
#Override
public void processMessage(final QBChatMessage qbChatMessage) {
dialogsManager.onSystemMessageReceived(qbChatMessage);
}
#Override
public void processError(QBChatException e, QBChatMessage qbChatMessage) {
}
}
private BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
}
};
}
Here is my Fragment viewModel code :-
public class ConversationViewModel extends Observable implements DialogsManager.ManagingDialogsCallbacks {
private static final int REQUEST_DIALOG_ID_FOR_UPDATE = 165;
public Context mContext;
FragmentConversationBinding binding;
private ActionMode currentActionMode;
public QBRequestGetBuilder requestBuilder;
private int skipRecords = 0;
private DialogsAdapter dialogsAdapter;
private QBChatDialogMessageListener allDialogsMessagesListener;
private SystemMessagesListener systemMessagesListener;
private QBSystemMessagesManager systemMessagesManager;
private QBIncomingMessagesManager incomingMessagesManager;
private DialogsManager dialogsManager;
private QBUser currentUser;
private String id;
public ConversationViewModel(Context mContext, FragmentConversationBinding binding, String Dialogid) {
this.mContext = mContext;
this.binding = binding;
this.id = Dialogid;
initUI();
}
public void initUI() {
allDialogsMessagesListener = new AllDialogsMessageListener();
systemMessagesListener = new SystemMessagesListener();
dialogsManager = new DialogsManager();
currentUser = ChatHelper.getCurrentUser();
initList();
registerQbChatListeners();
if (QbDialogHolder.getInstance().getDialogs().size() > 0) {
loadDialogsFromQb(true, true);
} else {
loadDialogsFromQb(false, true);
}
if (!id.isEmpty()) {
loadUpdatedDialog(id);
id = "";
} else {
updateDialogsList();
}
}
public void initList() {
dialogsAdapter = new DialogsAdapter(mContext, new ArrayList<>(QbDialogHolder.getInstance().getDialogs().values()));
binding.listDialogsChats.setAdapter(dialogsAdapter);
binding.listDialogsChats.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
QBChatDialog selectedDialog = (QBChatDialog) parent.getItemAtPosition(position);
if (currentActionMode == null) {
ChatActivity.startForResult(((Activity) mContext), REQUEST_DIALOG_ID_FOR_UPDATE, selectedDialog);
} else {
dialogsAdapter.toggleSelection(selectedDialog);
}
}
});
binding.listDialogsChats.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
QBChatDialog selectedDialog = (QBChatDialog) parent.getItemAtPosition(position);
dialogsAdapter.selectItem(selectedDialog);
return true;
}
});
requestBuilder = new QBRequestGetBuilder();
binding.swipyRefreshLayout.setOnRefreshListener(new SwipyRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh(SwipyRefreshLayoutDirection direction) {
requestBuilder.setSkip(skipRecords += ChatHelper.DIALOG_ITEMS_PER_PAGE);
loadDialogsFromQb(true, false);
}
});
}
private void loadUpdatedDialog(String dialogId) {
ChatHelper.getInstance().getDialogById(dialogId, new QbEntityCallbackImpl<QBChatDialog>() {
#Override
public void onSuccess(QBChatDialog result, Bundle bundle) {
QbDialogHolder.getInstance().addDialog(result);
updateDialogsAdapter();
}
#Override
public void onError(QBResponseException e) {
}
});
}
public void updateDialogsList() {
requestBuilder.setSkip(skipRecords = 0);
loadDialogsFromQb(true, true);
}
#Override
public void onDialogCreated(QBChatDialog chatDialog) {
updateDialogsAdapter();
}
#Override
public void onDialogUpdated(String chatDialog) {
updateDialogsAdapter();
}
#Override
public void onNewDialogLoaded(QBChatDialog chatDialog) {
updateDialogsAdapter();
}
private void registerQbChatListeners() {
incomingMessagesManager = QBChatService.getInstance().getIncomingMessagesManager();
systemMessagesManager = QBChatService.getInstance().getSystemMessagesManager();
if (incomingMessagesManager != null) {
incomingMessagesManager.addDialogMessageListener(allDialogsMessagesListener != null
? allDialogsMessagesListener : new AllDialogsMessageListener());
}
if (systemMessagesManager != null) {
systemMessagesManager.addSystemMessageListener(systemMessagesListener != null
? systemMessagesListener : new SystemMessagesListener());
}
dialogsManager.addManagingDialogsCallbackListener(this);
}
private class SystemMessagesListener implements QBSystemMessageListener {
#Override
public void processMessage(final QBChatMessage qbChatMessage) {
dialogsManager.onSystemMessageReceived(qbChatMessage);
}
#Override
public void processError(QBChatException e, QBChatMessage qbChatMessage) {
}
}
private class AllDialogsMessageListener extends QbChatDialogMessageListenerImp {
#Override
public void processMessage(final String dialogId, final QBChatMessage qbChatMessage, Integer senderId) {
if (!senderId.equals(ChatHelper.getCurrentUser().getId())) {
dialogsManager.onGlobalMessageReceived(dialogId, qbChatMessage);
}
}
}
public void updateDialogsAdapter() {
dialogsAdapter.updateList(new ArrayList<>(QbDialogHolder.getInstance().getDialogs().values()));
}
public void loadDialogsFromQb(final boolean silentUpdate, final boolean clearDialogHolder) {
if (!silentUpdate) {
binding.progressDialogs.setVisibility(View.VISIBLE);
}
ChatHelper.getInstance().getDialogs(requestBuilder, new QBEntityCallback<ArrayList<QBChatDialog>>() {
#Override
public void onSuccess(ArrayList<QBChatDialog> dialogs, Bundle bundle) {
binding.progressDialogs.setVisibility(View.GONE);
binding.swipyRefreshLayout.setRefreshing(false);
if (clearDialogHolder) {
QbDialogHolder.getInstance().clear();
}
QbDialogHolder.getInstance().addDialogs(dialogs);
updateDialogsAdapter();
}
#Override
public void onError(QBResponseException e) {
binding.progressDialogs.setVisibility(View.GONE);
binding.swipyRefreshLayout.setRefreshing(false);
Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
Here is my Chat Activity:-
public class ChatActivity extends BindingActivity<ActivityChatBinding> implements OnImagePickedListener {
ChatViewModel chatViewModel;
public static final int REQUEST_CODE_ATTACHMENT = 721;
public static final String EXTRA_DIALOG_ID = "dialogId";
#Override
protected int getLayoutId() {
return R.layout.activity_chat;
}
public static void startForResult(Activity activity, int code, QBChatDialog dialogId) {
Intent intent = new Intent(activity, ChatActivity.class);
intent.putExtra(ChatActivity.EXTRA_DIALOG_ID, dialogId);
activity.startActivityForResult(intent, code);
}
#Override
public void setInitBinding() {
getWindow().setBackgroundDrawableResource(R.drawable.bg_img);
chatViewModel = new ChatViewModel(this, binding);
binding.setChatViewModel(chatViewModel);
}
#Override
protected void setUpObserver() {
chatViewModel.addObserver(this);
}
#Override
public void update(Observable o, Object arg) {
}
#Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
#Override
public void onBackPressed() {
binding.getChatViewModel().releaseChat();
binding.getChatViewModel().sendDialogId();
super.onBackPressed();
}
#Override
public void onImagePicked(int requestCode, File file) {
switch (requestCode) {
case REQUEST_CODE_ATTACHMENT:
binding.getChatViewModel().attachmentPreviewAdapter.add(file);
break;
}
}
#Override
public void onImagePickError(int requestCode, Exception e) {
Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
}
#Override
public void onImagePickClosed(int requestCode) {
}
}
Chat Activity View Model :-
public class ChatViewModel extends Observable {
public Context mContext;
ActivityChatBinding binding;
public static final String TAG = ChatActivity.class.getSimpleName();
public static final int REQUEST_CODE_ATTACHMENT = 721;
public static final String PROPERTY_SAVE_TO_HISTORY = "save_to_history";
public static final String EXTRA_DIALOG_ID = "dialogId";
public ChatAdapter chatAdapter;
public AttachmentPreviewAdapter attachmentPreviewAdapter;
public QBChatDialog qbChatDialog;
public ArrayList<QBChatMessage> unShownMessages;
public int skipPagination = 0;
public ChatMessageListener chatMessageListener;
QBPrivacyList qbPrivacyList;
public static boolean mBlock;
public static int userId, recipientId;
public QBPrivacyListsManager privacyListsManager;
public ObservableField<String> chatMessage = new ObservableField<>("");
public ChatViewModel(Context mContext, ActivityChatBinding binding) {
this.mContext = mContext;
this.binding = binding;
Log.v(TAG, "onCreate ChaActivity on Thread ID = " + Thread.currentThread().getId());
qbChatDialog = (QBChatDialog) ((Activity) mContext).getIntent().getSerializableExtra(EXTRA_DIALOG_ID);
Log.v(TAG, "deserialized dialog = " + qbChatDialog);
qbChatDialog.initForChat(QBChatService.getInstance());
chatMessageListener = new ChatMessageListener();
qbPrivacyList = new QBPrivacyList();
privacyListsManager = QBChatService.getInstance().getPrivacyListsManager();
qbChatDialog.addMessageListener(chatMessageListener);
initViews();
initChat();
}
public void initViews() {
try {
recipientId = qbChatDialog.getRecipientId();
userId = qbChatDialog.getUserId();
getPrivacyList();
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
}
attachmentPreviewAdapter = new AttachmentPreviewAdapter(mContext,
new AttachmentPreviewAdapter.OnAttachmentCountChangedListener() {
#Override
public void onAttachmentCountChanged(int count) {
binding.attachmentContainer.setVisibility(count == 0 ? View.GONE : View.VISIBLE);
}
},
new AttachmentPreviewAdapter.OnAttachmentUploadErrorListener() {
#Override
public void onAttachmentUploadError(QBResponseException e) {
Toast.makeText(mContext, e.toString(), Toast.LENGTH_SHORT).show();
}
});
binding.attachmentAdapter.setAdapter(attachmentPreviewAdapter);
}
public void onAttachmentsClick(View view) {
new ImagePickHelper().pickAnImage(((FragmentActivity) mContext), REQUEST_CODE_ATTACHMENT);
}
private void initChat() {
switch (qbChatDialog.getType()) {
case PRIVATE:
loadDialogUsers();
break;
default:
Toaster.shortToast(String.format("%s %s", getString(R.string.chat_unsupported_type), qbChatDialog.getType().name()));
((Activity) mContext).finish();
break;
}
}
public void loadDialogUsers() {
ChatHelper.getInstance().getUsersFromDialog(qbChatDialog, new QBEntityCallback<ArrayList<QBUser>>() {
#Override
public void onSuccess(ArrayList<QBUser> users, Bundle bundle) {
String chatName = QbDialogUtils.getDialogName(qbChatDialog);
binding.dialogName.setText(chatName);
loadChatHistory();
}
#Override
public void onError(QBResponseException e) {
Toast.makeText(mContext, e.toString(), Toast.LENGTH_SHORT).show();
}
});
}
public void loadChatHistory() {
ChatHelper.getInstance().loadChatHistory(qbChatDialog, skipPagination, new QBEntityCallback<ArrayList<QBChatMessage>>() {
#Override
public void onSuccess(ArrayList<QBChatMessage> messages, Bundle args) {
Collections.reverse(messages);
if (chatAdapter == null) {
chatAdapter = new ChatAdapter(mContext, qbChatDialog, messages);
chatAdapter.setPaginationHistoryListener(new PaginationHistoryListener() {
#Override
public void downloadMore() {
loadChatHistory();
}
});
chatAdapter.setOnItemInfoExpandedListener(new ChatAdapter.OnItemInfoExpandedListener() {
#Override
public void onItemInfoExpanded(final int position) {
if (isLastItem(position)) {
((Activity) mContext).runOnUiThread(new Runnable() {
#Override
public void run() {
binding.listChat.setSelection(position);
}
});
} else {
binding.listChat.smoothScrollToPosition(position);
}
}
private boolean isLastItem(int position) {
return position == chatAdapter.getCount() - 1;
}
});
if (unShownMessages != null && !unShownMessages.isEmpty()) {
List<QBChatMessage> chatList = chatAdapter.getList();
for (QBChatMessage message : unShownMessages) {
if (!chatList.contains(message)) {
chatAdapter.add(message);
}
}
}
binding.listChat.setAdapter(chatAdapter);
binding.listChat.setAreHeadersSticky(false);
binding.listChat.setDivider(null);
} else {
chatAdapter.addList(messages);
binding.listChat.setSelection(messages.size());
}
binding.progressBar.setVisibility(View.GONE);
}
#Override
public void onError(QBResponseException e) {
binding.progressBar.setVisibility(View.GONE);
skipPagination -= ChatHelper.CHAT_HISTORY_ITEMS_PER_PAGE;
Toast.makeText(mContext, e.toString(), Toast.LENGTH_SHORT).show();
}
});
skipPagination += ChatHelper.CHAT_HISTORY_ITEMS_PER_PAGE;
QBRestChatService.markMessagesAsRead(qbChatDialog.getDialogId(), null);
}
public class ChatMessageListener extends QbChatDialogMessageListenerImp {
#Override
public void processMessage(String s, QBChatMessage qbChatMessage, Integer integer) {
showMessage(qbChatMessage);
}
}
public void showMessage(QBChatMessage message) {
if (chatAdapter != null) {
chatAdapter.add(message);
scrollMessageListDown();
} else {
if (unShownMessages == null) {
unShownMessages = new ArrayList<>();
}
unShownMessages.add(message);
}
}
public void scrollMessageListDown() {
binding.listChat.setSelection(binding.listChat.getCount() - 1);
}
public void onSendChatClick(View view) {
int totalAttachmentsCount = attachmentPreviewAdapter.getCount();
Collection<QBAttachment> uploadedAttachments = attachmentPreviewAdapter.getUploadedAttachments();
if (!uploadedAttachments.isEmpty()) {
if (uploadedAttachments.size() == totalAttachmentsCount) {
for (QBAttachment attachment : uploadedAttachments) {
sendChatMessage(null, attachment);
}
} else {
Toaster.shortToast(R.string.chat_wait_for_attachments_to_upload);
}
}
String text = binding.getChatViewModel().chatMessage.get().trim();
if (!TextUtils.isEmpty(text)) {
sendChatMessage(text, null);
}
}
public void sendChatMessage(String text, QBAttachment attachment) {
QBChatMessage chatMessage = new QBChatMessage();
if (attachment != null) {
chatMessage.addAttachment(attachment);
} else {
chatMessage.setBody(text);
}
chatMessage.setProperty(PROPERTY_SAVE_TO_HISTORY, "1");
chatMessage.setDateSent(System.currentTimeMillis() / 1000);
chatMessage.setMarkable(true);
if (!QBDialogType.PRIVATE.equals(qbChatDialog.getType()) && !qbChatDialog.isJoined()) {
Toaster.shortToast("You're still joining a group chat, please wait a bit");
return;
}
try {
qbChatDialog.sendMessage(chatMessage);
if (QBDialogType.PRIVATE.equals(qbChatDialog.getType())) {
showMessage(chatMessage);
}
if (attachment != null) {
attachmentPreviewAdapter.remove(attachment);
} else {
binding.getChatViewModel().chatMessage.set("");
}
} catch (SmackException.NotConnectedException e) {
Log.w(TAG, e);
Toaster.shortToast("Can't send a message, You are not connected to chat");
}
}
public void leaveGroupDialog() {
try {
ChatHelper.getInstance().leaveChatDialog(qbChatDialog);
} catch (XMPPException | SmackException.NotConnectedException e) {
Log.w(TAG, e);
}
}
public void releaseChat() {
qbChatDialog.removeMessageListrener(chatMessageListener);
if (!QBDialogType.PRIVATE.equals(qbChatDialog.getType())) {
leaveGroupDialog();
}
}
public void sendDialogId() {
Intent result = new Intent();
result.putExtra(EXTRA_DIALOG_ID, qbChatDialog.getDialogId());
((Activity) mContext).setResult(RESULT_OK, result);
}
public void finishActivity(View view) {
((Activity) mContext).finish();
}
public void clickButtonBlock(View view) {
AppUtils.dialog(mContext);
if (mBlock) {
onClickUnblock();
} else {
onClickBlock();
}
}
public void getPrivacyList() throws SmackException.NotConnectedException, XMPPException.XMPPErrorException, SmackException.NoResponseException {
QBPrivacyListsManager privacyListsManager = QBChatService.getInstance().getPrivacyListsManager();
QBPrivacyList privacyList = privacyListsManager.getPrivacyList("public");
List<QBPrivacyListItem> items = privacyList.getItems();
int i;
for (i = 0; i < privacyList.getItems().size(); i++) {
QBPrivacyListItem item = items.get(i);
String valueForType = item.getValueForType();
String[] splitvalueType = valueForType.split("-");
String blockId = splitvalueType[0];
if (blockId.equalsIgnoreCase(String.valueOf(recipientId))) {
mBlock = true;
binding.tvBlock.setText("Unblock");
break;
} else {
binding.tvBlock.setText("Block");
}
}
}
}
The problem is chatDialog.getUnreadMessageCount() giving me count 2 when I once enter in chat room and come back to my chat listing page.
Description on issue:-
Example:-
I have installed my application in two devices. when i send message from one (Device A) to other (Device B).The device B will display correct Unread count i.e 1 . Now when i click on chat dialog and get entered inside the chat room (of Device B). and come back to it's listing page and then again try to send message from Device A to device B . This time the unread count comes as 2 but it should be one as i already viewed my previous message. This get more worse if i try to open my chat room again to read the message(Device B) and get back to my listing page(Device B) after reading the message . This time if I send the message from Device A to Device B, Then the count came out as "5" just for my one message this thing is making me sick, I debugged the whole code, it's chatDialog .getUnreadMessageCount() who is returning me count "5", I don't know why my previous messages are not counted as being read messages and why everytime I open chat room one additional number gets added up inside the unread count.Please help me out , i am scratching my head from past two days.
Your help will be greatly Appreciated.
Thanks
Problem is that your AllDialogsMessageListener is not getting unregistered so unregister it by calling unregisterQbChatListeners(); when you will be opening your chat room screen . Every thing will work fine once you do that.
This what i mean :-
binding.listDialogsChats.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
QBChatDialog selectedDialog = (QBChatDialog) parent.getItemAtPosition(position);
if (currentActionMode == null) {
unregisterQbChatListeners();
ChatActivity.startForResult(((Activity) mContext), REQUEST_DIALOG_ID_FOR_UPDATE, selectedDialog);
} else {
dialogsAdapter.toggleSelection(selectedDialog);
}
}
});
private void unregisterQbChatListeners() {
if (incomingMessagesManager != null) {
incomingMessagesManager.removeDialogMessageListrener(allDialogsMessagesListener);
}
if (systemMessagesManager != null) {
systemMessagesManager.removeSystemMessageListener(systemMessagesListener);
}
dialogsManager.removeManagingDialogsCallbackListener(this);
}
cheers!!!
Please use this code below :
QBChatService.markMessagesAsRead("YOUR_DIALOG_ID", null, new QBEntityCallback<Void>() {
#Override
public void onSuccess(Void aVoid, Bundle bundle) {
QBRequestGetBuilder requestBuilder = new QBRequestGetBuilder();
requestBuilder.eq("_id", Team.getCurrent().getChatId());
QBChatService.getChatDialogs(null, requestBuilder, new QBEntityCallback<ArrayList<QBDialog>>() {
#Override
public void onSuccess(ArrayList<QBDialog> qbDialogs, Bundle bundle) {
if (qbDialogs != null && qbDialogs.size() > 0) {
QBDialog dialog = qbDialogs.get(0);//here you get your dialog with unreadMessageCount = 0
}
}
#Override
public void onError(QBResponseException e) {
}
});
}
#Override
public void onError(QBResponseException e) {
}
});
On just adding my Custom object it is finishing activity , not giving any error or indication , below is my code please help
#Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.create_profile_button:
prepareData();
if (CheckFields()) {
mProgressDialog.show();
mProgressDialog.setCancelable(Boolean.FALSE);
mProgressDialog.setMessage("Creating Profile");
Toast.makeText(this, "All set to rock", Toast.LENGTH_LONG).show();
throwData(createObject());
}
break;
}
}
private School createObject() {
School profile = new School();
profile.setSchoolName(name);
profile.setSchoolRegNo(regNo);
profile.setSchoolBoard(board);
profile.setSchoolCity(city);
profile.setSchoolPincode(pincode);
profile.setSchoolAddress(address);
profile.setSchoolState(state);
profile.setSchoolContact(contact);
profile.setSchoolEmail(email);
return profile;
}
private void throwData(School profile) {
mDatabase.child(regNo).setValue(profile).addOnCompleteListener(CreateProfileActivity.this).addOnFailureListener(CreateProfileActivity.this);
}
School Class:
public class School {
public School() {
}
public String SchoolRegNo,SchoolName, SchoolBoard,
SchoolCity, SchoolPincode,
SchoolAddress, SchoolState,
SchoolContact, SchoolEmail;
public String getSchoolRegNo() {
return SchoolRegNo;
}
public void setSchoolRegNo(String schoolRegNo) {
SchoolRegNo = schoolRegNo;
}
public String getSchoolName() {
return SchoolName;
}
public void setSchoolName(String schoolName) {
SchoolName = schoolName;
}
public String getSchoolBoard() {
return SchoolBoard;
}
public void setSchoolBoard(String schoolBoard) {
SchoolBoard = schoolBoard;
}
public String getSchoolCity() {
return SchoolCity;
}
public void setSchoolCity(String schoolCity) {
SchoolCity = schoolCity;
}
public String getSchoolPincode() {
return SchoolPincode;
}
public void setSchoolPincode(String schoolPincode) {
SchoolPincode = schoolPincode;
}
public String getSchoolAddress() {
return SchoolAddress;
}
public void setSchoolAddress(String schoolAddress) {
SchoolAddress = schoolAddress;
}
public String getSchoolState() {
return SchoolState;
}
public void setSchoolState(String schoolState) {
SchoolState = schoolState;
}
public String getSchoolContact() {
return SchoolContact;
}
public void setSchoolContact(String schoolContact) {
SchoolContact = schoolContact;
}
public String getSchoolEmail() {
return SchoolEmail;
}
public void setSchoolEmail(String schoolEmail) {
SchoolEmail = schoolEmail;
}
}
I'm trying to do a simple Chat project with Firebase but in the method to singing I have an error of FirebaseException: Failed to bounce to type when I try to instantiate the currentUser with dataSnapshot.
This is the method:
public void signIn(String email, String password) {
dataReference.authWithPassword(email, password, new Firebase.AuthResultHandler() {
#Override
public void onAuthenticated(AuthData authData) {
myUserReference = helper.getMyUserReference();
myUserReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User currentUser = dataSnapshot.getValue(User.class);
if (currentUser == null) {
String email = helper.getAuthUserEmail();
if (email != null) {
currentUser = new User();
myUserReference.setValue(currentUser);
}
}
helper.changeUserContectionStatus(User.ONLINE);
postEvent(LoginEvent.ON_SING_IN_SUCCESS);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
#Override
public void onAuthenticationError(FirebaseError firebaseError) {
postEvent(LoginEvent.ON_SING_IN_ERROR,firebaseError.getMessage() );
}
});
}
And this is the POJO:
public class User {
String email;
boolean online;
Map<String,Boolean> contacs;
public static final boolean ONLINE = true;
public static final boolean OFFLINE = false;
public User() {
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isOnline() {
return online;
}
public void setOnline(boolean online) {
this.online = online;
}
public Map<String, Boolean> getContacs() {
return contacs;
}
public void setContacs(Map<String, Boolean> contacs) {
this.contacs = contacs;
}
#Override
public boolean equals(Object object){
boolean equals = false;
if (object instanceof User) {
User user = (User)object;
equals = this.email.equals(user.getEmail());
}
return equals;
}
}