Not receiving unread messages count in quickblox - android

I am using quickblox android sdk for a groupchat application and it is working perfectly well except for the fact that i am unable to receive push notification if a message is sent when i was offline. So i decided to query for unread messages count but am getting 0 from the server. I don't know what i have to do to get groupchat dialog for a user to be able to receive notification when the user was not online.
This is the code I used for querying for unread messages:
Set<String> dialogIds = new HashSet<String>();
String groupChatId = groupChat.getDialogId();
System.out.println("GroupChat Id: "+groupChatId);
dialogIds.add(groupChatId);
QBChatDialog chatDialog = new QBChatDialog(groupChatId);
QBMessageGetBuilder messageGetBuilder = new QBMessageGetBuilder();
messageGetBuilder.setLimit(500);
messageGetBuilder.sortDesc("date_sent");
QBRestChatService.getTotalUnreadMessagesCount(dialogsIds).performAsync(new QBEntityCallback<Integer>() {
#Override
public void onSuccess(Integer total, Bundle params) {
Log.i(TAG, "total unread messages: " + total);
// if you have more then one dialog you can get each value with params.getInt(dialog_id)
}
#Override
public void onError(QBResponseException e) {
e.printStackTrace();
}
});

The first part is correct:
Set<String> dialogIds = new HashSet<String>();
String groupChatId = groupChat.getDialogId();
dialogsIds.add(groupChatId);
But, after that you were not using dialogIds. And also, instead of getDialogMessages () you need to use getTotalUnreadMessagesCount() as following:
QBRestChatService.getTotalUnreadMessagesCount(dialogIds).performAsync(new QBEntityCallback<Integer>() {
#Override
public void onSuccess(Integer total, Bundle params) {
Log.i(TAG, "totat messages: " + total);
// if you have more then one dialog you can get each value with params.getInt(dialog_id)
}
#Override
public void onError(QBResponseException e) { }
});

Related

Android - Use Broadcast Receiver to reload activity

I am developing an android application and I have one activity which shows all the tables in a restaurant. Within this activity, there is a method to change the table color (the table is just a button) based on whether a customer is at the table.
On the customer's screen, when they select their table, my MYQSL database is updated and the user is now assigned to the table.
Now, when I go to open the map screen (note: this is used by waiters on the app, it cant be accessed by customers), the table will be a different color (it checks the table status in the db, if the table is assigned it is a different color).
However, the only way to get the updated map is by reloading the map activity. I want the map activity to update automatically using a BroadcastReceiver() but I am struggling to find a tutorial on how to implement this. When a customer clicks a table to assign themselves to it, I want the broadcast to be sent, automatically reloading the map activity... Is this possible? And if so, how do I implement it?
EDIT: The waiter and customer are using the same application but on different devices
The ChooseTable activity has an on click listener for each table which results in the following method being called:
private void assignUserToTable(final int table, final String userid) {
String url = "hidden";
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (response.trim().equals("success")) {
Toast.makeText(ChooseTable.this, "Welcome!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(ChooseTable.this, "Oops, something went wrong!", Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(ChooseTable.this, "Error! " + error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("table_id", String.valueOf(table));
params.put("user", userid);
return params;
}
};
MySingleton.getInstance(this).addToRequestQueue(stringRequest);
}
The waiter map view looks has the following method which checks the table status on the activity being loaded:
private void checkTables(){
String url = "hidden";
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try{
JSONObject jsonObject = new JSONObject(response);
String success = jsonObject.getString("success");
JSONArray jsonArray = jsonObject.getJSONArray("toggles");
if(success.equals("1")){
for(int i=0; i<jsonArray.length(); i++){
JSONObject object = jsonArray.getJSONObject(i);
String tableid = object.getString("tableid");
if(Tbl1.getTag().equals(tableid)){
Tbl1.setBackgroundColor(ContextCompat.getColor(WaitingStaffMapScreen.this, R.color.tableReq));
} else if(Tbl2.getTag().equals(tableid)){
Tbl2.setBackgroundColor(ContextCompat.getColor(WaitingStaffMapScreen.this, R.color.tableReq));
} else if(Tbl3.getTag().equals(tableid)){
Tbl3.setBackgroundColor(ContextCompat.getColor(WaitingStaffMapScreen.this, R.color.tableReq));
} else if(Tbl4.getTag().equals(tableid)){
Tbl4.setBackgroundColor(ContextCompat.getColor(WaitingStaffMapScreen.this, R.color.tableReq));
} else if(Tbl5.getTag().equals(tableid)){
Tbl5.setBackgroundColor(ContextCompat.getColor(WaitingStaffMapScreen.this, R.color.tableReq));
} else if(Tbl6.getTag().equals(tableid)){
Tbl6.setBackgroundColor(ContextCompat.getColor(WaitingStaffMapScreen.this, R.color.tableReq));
} else if(Tbl7.getTag().equals(tableid)){
Tbl7.setBackgroundColor(ContextCompat.getColor(WaitingStaffMapScreen.this, R.color.tableReq));
} else if(Tbl8.getTag().equals(tableid)){
Tbl8.setBackgroundColor(ContextCompat.getColor(WaitingStaffMapScreen.this, R.color.tableReq));
}
}
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(WaitingStaffMapScreen.this, "Oops, something went wrong!", Toast.LENGTH_LONG).show();
}
}
},new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(WaitingStaffMapScreen.this, "Error! " +error.toString(), Toast.LENGTH_LONG).show();
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("table_id", "0");
return params;
}
};
MySingleton.getInstance(this).addToRequestQueue(stringRequest);
}
Essentially I want some means of reloading the map screen activity when a table button has been clicked.
Since everything is running on separate devices, what I would do is implement firebase cloud messaging:
https://firebase.google.com/docs/cloud-messaging/android/client
When the application is started, the device receives a token.
When the device receives this token, you will POST it to your database(assuming you have a table of devices) under a new column(ie: FirebaseToken) for that device row.
When the table status is updated(ie: a user selects a table), and that reaches out to the server, you will have a query that goes through each device registered to the business, and sends a push notification.
Then on the android app, you will have a firebase service running that receives the push notification(ie:)
public class MyFirebaseMessagingService extends FirebaseMessagingService
{
NotificationManager notificationManager;
#Override public void onMessageReceived(RemoteMessage remoteMessage)
{
Map<String,String> data = remoteMessage.getData();
if (data.get("title").equals("Update Tables")) {
//Call logic to update the adapter
}
}
}
Very general gist of it. Relatively easy to implement. Any questions, I can do my best to clarify.
As the below comment said, using group messaging is best. I didn't know how many devices each business would have, so was trying to keep it as simple as possible.
Here is a server side example. This will simply send a push notification to the phone, and will be received in the FirebaseMessagingService class you extended.
public bool SendMessage(string firebaseTokenId, FirebaseMessages type)
{
httpWebRequest = (HttpWebRequest)WebRequest.Create("http://fcm.googleapis.com/fcm/send");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Headers.Add("Authorization", "your key");
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
var messageToSend = new Message()
{
to = firebaseTokenId,
data = new DataPayload()
{
title = firebaseMessages[type].title,
message = firebaseMessages[type].body,
}
};
string json = JsonConvert.SerializeObject(messageToSend, Formatting.Indented);
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
}
public enum FirebaseMessages
{
UpdateTables
}
public class Message
{
public DataPayload data {get;set;}
public string to { get; set; }
}
public class DataPayload
{
public string title { get; set; }
public string message { get; set; }
}
//on the on receive, this is a datapayload(not notification), so no push intent will ever be shown, hence you can leave the body null.
firebaseMessages.Add(FirebaseMessages.MessageReceived, new FirebaseMessage() { title = "Table Update", body = ""});

The SendBird.addChannelHandler in Android doesn't work while implementing receive messages

The following code is written in onResume and is implementing the receive message functionality of SendBird API
protected void onResume()
{
super.onResume();
Log.d("----->", "in on resume");
SendBird.addChannelHandler("ABCD" , new SendBird.ChannelHandler()
{
#Override
public void onMessageReceived(BaseChannel baseChannel, BaseMessage
baseMessage)
{
Log.d("----->","onMessageReceived");
if (baseMessage instanceof UserMessage)
{
// message is a UserMessage
UserMessage userMessage = (UserMessage) baseMessage;
String msg = userMessage.getMessage();
alMsgs.add(msg);
adapter.notifyDataSetChanged();
Log.d("---->",msg);
}
else if (baseMessage instanceof FileMessage)
{
// message is a FileMessage
}
}
#Override
public void onChannelDeleted(String channelUrl,
BaseChannel.ChannelType channelType)
{
super.onChannelDeleted(channelUrl, channelType);
Log.d("---->","on channel deleted");
}
});
}
I don't get any Log output in Android Monitor Except the one that says "in on resume".

How to enable the XEP-0199 in Smack?

I'm using aSmack. My app listens a chatroom and reacts to the messages but it never send a message. The app doesn't receive more messages if the chatroom remains in silence for a while and then a new message is sent. I researched and I think that XEP-0199 is the solution here. I see that #Flow (the current Smack maintainer) implemented it and the issue related was closed.
I think that I need to use PingProvider but I really don't know how to connect this class with the Connection.
How can I enable the XEP-0199? How can I use PingProvider?
Connection code:
smack = SmackAndroid.init(getActivity().getApplicationContext());
connection = new XMPPConnection(App.getServer());
connection.addConnectionListener(new ConnectionListener() {
private final static String SMACK = "SMACK";
#Override
public void reconnectionSuccessful() {
Log.i(SMACK , "reconnectionSuccessful");
}
#Override
public void reconnectionFailed(Exception e) {
Log.i(SMACK, "reconnectionFailed", e);
}
#Override
public void reconnectingIn(int seconds) {
Log.i(SMACK, "reconnectingIn " + seconds);
}
#Override
public void connectionClosedOnError(Exception e) {
Log.i(SMACK, "connectionClosedOnError", e);
}
#Override
public void connectionClosed() {
Log.i(SMACK, "connectionClosed");
}
});
connection.connect();
connection.login(user, password);
I fix the problem implementing the ping response manually:
connection.addPacketListener(new PacketListener() {
#Override
public void processPacket(Packet packet) {
connection.sendPacket(new Pong((Ping) packet));
}
}, new PacketFilter() {
#Override
public boolean accept(Packet packet) {
return packet instanceof Ping;
}
});
To prevent user from disconnecting your session
PingManager pm = PingManager.getInstanceFor(MyApplication.connection) ;
pm.setPingInterval(5) ; // 5 sec
pm.pingMyServer() ;
pm.registerPingFailedListener(new PingFailedListener() {
#Override
public void pingFailed() {
Log.e(TAG , "pingFailed") ;
}
});
XEP 0199 is not a solution, Ping is used to check weather the server is up or not. actually you will send ping to the server.
Now as fas as your problem is concerned. Show me the message stanza that you are trying to send. and also check if the chat-room is public or private. you can not send a message to a private chat room.
Answer Updated:
Try using this code for detecting message recieve
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
Network.connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
Message message = (Message) packet;
if (message.getBody() != null) {
String fromName = StringUtils.parseBareAddress(message.getFrom());
Log.i("XMPPClient", "Got text [" + message.getBody() + "] from [" + fromName + "]");
//recieve.setText(message.getBody());
/*messages.add(fromName + ":");
messages.add(message.getBody());*/
// Add the incoming message to the list view
item = new RowItem(R.drawable.billing, message.getBody());
adapter = new CustomListViewAdapter(getBaseContext(),
R.layout.list_item, rowItems);
rowItems.add(item);
//listView.setAdapter(adapter);
}
}
}, filter);
I called PingManager.getInstanceFor method to enable XEP-0199 support.

Delivery receipt requests not working for XMPP Android (aSmack)

I'm using OpenFire with aSmack.
I can't seem to get DeliveryReceipts working.
I do the following when I create a connection:
//create connection
connection.login(username, password);
DeliveryReceiptManager.getInstanceFor(connection).enableAutoReceipts();
DeliveryReceiptManager.getInstanceFor(connection).addReceiptReceivedListener(new ReceiptReceivedListener()
{
#Override
public void onReceiptReceived(String arg0, String arg1, String arg2)
{
Log.v("app", arg0 + ", " + arg1 + ", " + arg2);
}
});
I'm sending a message to another user using:
//send chat
Message msg = new Message(id, Message.Type.chat);
msg.setBody(chat);
DeliveryReceiptManager.addDeliveryReceiptRequest(msg);
connection.sendPacket(msg);
The above does not work although the message gets sent with the ReceiptRequest. The listener does not get fired at the sender's end although the receiver receives the message. (I confirmed it through debugging that a DeliveryReceiptRequest does indeed get attached to the message that is sent).
I've also tried manually sending back the Receipt by using the following in my PacketListener with (MessageTypeFilter(Message.Type.chat)):
Packet received = new Message();
received.addExtension(new DeliveryReceipt(packet.getPacketID()));
received.setTo(packet.getFrom());
getConnection().sendPacket(received);
Still, the client at the receiving end receives the message alright but the listener does not get fired in the sender's system. Anything I'm missing?
Add these lines before you set up your connection and Auto Receipts will work with ReceiptReceivedListener. Seems like the DeliveryReceipt extensions aren't registered by default.
ProviderManager.getInstance().addExtensionProvider(DeliveryReceipt.ELEMENT, DeliveryReceipt.NAMESPACE, new DeliveryReceipt.Provider());
ProviderManager.getInstance().addExtensionProvider(DeliveryReceiptRequest.ELEMENT, new DeliveryReceiptRequest().getNamespace(), new DeliveryReceiptRequest.Provider());
Hi the above said answer given me NPE, so I used following code to get message notifications which was working perfectly for me:
Don't forget to add this ProviderManager
ProviderManager pm = ProviderManager.getInstance();
pm.addExtensionProvider("x", "jabber:x:event",new MessageEventProvider());
MessageEventManager messageEventManager = new MessageEventManager(connection);
messageEventManager.addMessageEventNotificationListener(m_messageEventNotificationListener);
messageEventManager.addMessageEventRequestListener(m_DefaultMessageEventRequestListener);
/*
* Notifies when message events happend
*
*/
MessageEventNotificationListener m_messageEventNotificationListener = new MessageEventNotificationListener() {
#Override
public void deliveredNotification(String fromJID, String messageID) {
final String _messageID =messageID;
System.out.println("deliveredNotification");
UiUtility.printMe("Message("+messageID+") Was Delivered to "+fromJID);
//WRITE YOUR CUSTOM METHOD WHEN MSG DELIVERED NOTFICATIONN RECIEVED.
}
#Override
public void displayedNotification(String string, String string1) {
}
#Override
public void composingNotification(String string, String string1) {
}
#Override
public void offlineNotification(String string, String string1) {
}
#Override
public void cancelledNotification(String string, String string1) {
}
};
/*
* Send a request when message events occured
*/
DefaultMessageEventRequestListener m_DefaultMessageEventRequestListener = new DefaultMessageEventRequestListener() {
#Override
public void deliveredNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.deliveredNotificationRequested(from, packetID, messageEventManager); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void displayedNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.displayedNotificationRequested(from, packetID, messageEventManager); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void offlineNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.offlineNotificationRequested(from, packetID, messageEventManager); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void composingNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.composingNotificationRequested(from, packetID, messageEventManager); //To change body of generated methods, choose Tools | Templates.
}
};
It's a bit late but this will help someone, take note of
receiptManager.setAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.always);
Check below code:
DeliveryReceiptManager receiptManager = DeliveryReceiptManager.getInstanceFor(connection);
//automatically enable delivery receipts to every message
receiptManager.autoAddDeliveryReceiptRequests();
receiptManager.setAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.always);
receiptManager.addReceiptReceivedListener(new ReceiptReceivedListener() {
#Override
public void onReceiptReceived(Jid fromJid, Jid toJid, String receiptId, Stanza receipt) {
//handle delivery receipts here
}
});

Salesforce Rest API with android - NullPointerException # AsyncRequestCallback

I'm trying to get the Salesforce REST API working with Android and new to android programming, followed the sample code to connect with SFDC http://wiki.developerforce.com/page/Getting_Started_with_the_Mobile_SDK_for_Android#Authentication
I'm trying to get a few records from SFDC and display them in the android app, looks like when the Async Call is made at "client.sendAsync(sfRequest, new AsyncRequestCallback()" - NullPointerException is thrown.
I did see a couple of similar issues online, but didn't help me. Hoping if some one would point me in the right direction to troubleshoot this. Thanks much.
public class GetAccountsActivity extends Activity {
private PasscodeManager passcodeManager;
private String soql;
private String apiVersion;
private RestClient client;
private TextView resultText;
private RestRequest sfRequest;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get Api Version
apiVersion = getString(R.string.api_version);
//Create Query
soql = "select id, name from Account limit 10";
// Setup view
setContentView(R.layout.get_accounts_activity);
((TextView) findViewById(R.id.Acc_Title)).setText(apiVersion);
// Passcode manager
passcodeManager = ForceApp.APP.getPasscodeManager();
}
#Override
public void onResume() {
super.onResume();
//Get SFClient
// Login options
String accountType = ForceApp.APP.getAccountType();
LoginOptions loginOptions = new LoginOptions(
null, // login host is chosen by user through the server picker
ForceApp.APP.getPasscodeHash(),
getString(R.string.oauth_callback_url),
getString(R.string.oauth_client_id),
new String[] {"api"});
new ClientManager(this, accountType, loginOptions).getRestClient(this, new RestClientCallback() {
#Override
public void authenticatedRestClient(RestClient client) {
if (client == null) {
ForceApp.APP.logout(GetAccountsActivity.this);
return;
}
GetAccountsActivity.this.client = client;
}
});
//Get Rest Object to query
try {
sfRequest = RestRequest.getRequestForQuery(apiVersion, soql);
//Use SF Rest Client to send the request
client.sendAsync(sfRequest, new AsyncRequestCallback(){
#Override
public void onSuccess(RestRequest request, RestResponse response){
//Check responses and display results
// EventsObservable.get().notifyEvent(EventType.RenditionComplete);
}//end onSuccess
#Override
public void onError(Exception exception) {
//printException(exception);
EventsObservable.get().notifyEvent(EventType.RenditionComplete);
}//End Exception for Async Method
});
}catch (UnsupportedEncodingException e) {
//printHeader("Could Send Query request");
//printException(e);
return;
}
}
}
enter code here
You are calling client.sendAsync from onResume() but client is not set until the authenticatedRestClient callback is called, you need to move your sendAsync call into the authenticatedRestClient callback.

Categories

Resources