My sinch client sends duplicate messages to my parse database in an incremental way. That is for the first message it posts once in the database. Twice for the second message. Thrice for the third in that order.
This is my ChatActivity
package com.app.knowtes;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import com.parse.FindCallback;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseUser;
import com.sinch.android.rtc.PushPair;
import com.sinch.android.rtc.messaging.Message;
import com.sinch.android.rtc.messaging.MessageClient;
import com.sinch.android.rtc.messaging.MessageClientListener;
import com.sinch.android.rtc.messaging.MessageDeliveryInfo;
import com.sinch.android.rtc.messaging.MessageFailureInfo;
import com.sinch.android.rtc.messaging.WritableMessage;
import java.util.Arrays;
import java.util.List;
/**
* Created by RR on 12/6/2015.
*/
public class ChatActivity extends ActionBarActivity {
private String recipientId;
private EditText messageBodyField;
private String messageBody;
private MessageService.MessageServiceInterface messageService;
private String currentUserId;
private ServiceConnection serviceConnection = new MyServiceConnection();
ListView messagesList;
MessageAdapter messageAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chatactivity);
bindService(new Intent(this, MessageService.class), serviceConnection, BIND_AUTO_CREATE);
//get recipientId from the intent
Intent intent = getIntent();
recipientId = intent.getStringExtra("RECIPIENT_ID");
currentUserId = ParseUser.getCurrentUser().getObjectId();
messageBodyField = (EditText) findViewById(R.id.messageBodyField);
messagesList = (ListView) findViewById(R.id.listMessages);
messageAdapter = new MessageAdapter(this);
messagesList.setAdapter(messageAdapter);
String[] cuserIds = {currentUserId, recipientId};
String[] ruserIds = {recipientId,currentUserId};
ParseQuery<ParseObject> query = ParseQuery.getQuery("ParseMessage");
query.whereContainedIn("senderId", Arrays.asList(cuserIds));
query.whereContainedIn("recipientId", Arrays.asList(ruserIds));
query.orderByAscending("createdAt");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> messageList, com.parse.ParseException e) {
if (e == null) {
for (int i = 0; i < messageList.size(); i++) {
WritableMessage message = new WritableMessage(messageList.get(i).get("recipientId").toString(), messageList.get(i).get("messageText").toString());
if (messageList.get(i).get("senderId").toString().equals(currentUserId)) {
messageAdapter.addMessage(message, MessageAdapter.DIRECTION_OUTGOING);
} else {
messageAdapter.addMessage(message, MessageAdapter.DIRECTION_INCOMING);
}
}
}
}
});
//listen for a click on the send button
findViewById(R.id.sendButton).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//send the message!
messageBody = messageBodyField.getText().toString();
if (messageBody.equals("")) {
Toast.makeText(getApplicationContext(), "Please enter a message", Toast.LENGTH_SHORT).show();
return;
}else {
messageService.sendMessage(recipientId, messageBody);
messageBodyField.setText("");
}
}
});
}
//unbind the service when the activity is destroyed
#Override
public void onDestroy() {
unbindService(serviceConnection);
messageService.removeMessageClientListener(new MyMessageClientListener());
super.onDestroy();
}
private class MyServiceConnection implements ServiceConnection {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
messageService = (MessageService.MessageServiceInterface) iBinder;
messageService.addMessageClientListener(new MyMessageClientListener());
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
messageService = null;
}
}
private class MyMessageClientListener implements MessageClientListener {
//Notify the user if their message failed to send
#Override
public void onMessageFailed(MessageClient client, Message message,
MessageFailureInfo failureInfo) {
Toast.makeText(getApplicationContext(), "Message failed to send." + failureInfo.getSinchError().getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onIncomingMessage(MessageClient client, Message message) {
//Display an incoming message
if (message.getSenderId().equals(recipientId)) {
WritableMessage writableMessage = new WritableMessage(message.getRecipientIds().get(0), message.getTextBody());
messageAdapter.addMessage(writableMessage, MessageAdapter.DIRECTION_INCOMING);
}
}
#Override
public void onMessageSent(MessageClient client, Message message, final String recipientId) {
//Display the message that was just sent
//Later, I'll show you how to store the
//message in Parse, so you can retrieve and
//display them every time the conversation is opened
//WritableMessage writableMessage = new WritableMessage(message.getRecipientIds().get(0), message.getTextBody());
//messageAdapter.addMessage(writableMessage, MessageAdapter.DIRECTION_OUTGOING);
Toast.makeText(getApplicationContext(), "Message successfully senT.", Toast.LENGTH_SHORT).show();
final WritableMessage writableMessage = new WritableMessage(message.getRecipientIds().get(0), message.getTextBody());
messageAdapter.addMessage(writableMessage, MessageAdapter.DIRECTION_OUTGOING);
//only add message to parse database if it doesn't already exist there
ParseQuery<ParseObject> query = ParseQuery.getQuery("ParseMessage");
query.whereEqualTo("sinchId", message.getMessageId());
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> messageList, com.parse.ParseException e) {
if (e == null) {
if (messageList.size() == 0) {
ParseObject parseMessage = new ParseObject("ParseMessage");
parseMessage.put("senderId", currentUserId);
parseMessage.put("recipientId", recipientId);
parseMessage.put("messageText", writableMessage.getTextBody());
parseMessage.put("sinchId", writableMessage.getMessageId());
parseMessage.saveInBackground();
messageAdapter.addMessage(writableMessage, MessageAdapter.DIRECTION_OUTGOING);
}
}
}
});
}
//Do you want to notify your user when the message is delivered?
#Override
public void onMessageDelivered(MessageClient client, MessageDeliveryInfo deliveryInfo) {}
//Don't worry about this right now
#Override
public void onShouldSendPushData(MessageClient client, Message message, List<PushPair> pushPairs) {}
}
}
And this is my MessageService.java
package com.app.knowtes;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import com.parse.ParseUser;
import com.sinch.android.rtc.ClientRegistration;
import com.sinch.android.rtc.Sinch;
import com.sinch.android.rtc.SinchClient;
import com.sinch.android.rtc.SinchClientListener;
import com.sinch.android.rtc.SinchError;
import com.sinch.android.rtc.messaging.MessageClient;
import com.sinch.android.rtc.messaging.MessageClientListener;
import com.sinch.android.rtc.messaging.WritableMessage;
/**
* Created by RR on 12/4/2015.
*/
public class MessageService extends Service implements SinchClientListener {
private static final String APP_KEY = "XXXXXXXXXXXXXXXXXXX";
private static final String APP_SECRET = "XXXXXXXXXXXXXXXX";
private static final String ENVIRONMENT = "sandbox.sinch.com";
private final MessageServiceInterface serviceInterface = new MessageServiceInterface();
private SinchClient sinchClient = null;
private MessageClient messageClient = null;
private String currentUserId;
private Intent broadcastIntent = new Intent("com.app.knowtes.ChatListActivity");
private LocalBroadcastManager broadcaster;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//get the current user id from Parse
currentUserId = ParseUser.getCurrentUser().getObjectId();
if (currentUserId != null && !isSinchClientStarted()) {
startSinchClient(currentUserId);
}
broadcaster = LocalBroadcastManager.getInstance(this);
return super.onStartCommand(intent, flags, startId);
}
public void startSinchClient(String username) {
sinchClient = Sinch.getSinchClientBuilder()
.context(this)
.userId(username)
.applicationKey(APP_KEY)
.applicationSecret(APP_SECRET)
.environmentHost(ENVIRONMENT)
.build();
//this client listener requires that you define
//a few methods below
sinchClient.addSinchClientListener(this);
//messaging is "turned-on", but calling is not
sinchClient.setSupportMessaging(true);
sinchClient.setSupportActiveConnectionInBackground(true);
sinchClient.checkManifest();
sinchClient.start();
}
private boolean isSinchClientStarted() {
return sinchClient != null && sinchClient.isStarted();
}
//The next 5 methods are for the sinch client listener
#Override
public void onClientFailed(SinchClient client, SinchError error) {
sinchClient = null;
broadcastIntent.putExtra("success", false);
broadcaster.sendBroadcast(broadcastIntent);
}
#Override
public void onClientStarted(SinchClient client) {
client.startListeningOnActiveConnection();
messageClient = client.getMessageClient();
broadcastIntent.putExtra("success", true);
broadcaster.sendBroadcast(broadcastIntent);
}
#Override
public void onClientStopped(SinchClient client) {
sinchClient = null;
}
#Override
public void onRegistrationCredentialsRequired(SinchClient client, ClientRegistration clientRegistration) {}
#Override
public void onLogMessage(int level, String area, String message) {}
#Override
public IBinder onBind(Intent intent) {
return serviceInterface;
}
public void sendMessage(String recipientUserId, String textBody) {
if (messageClient != null) {
WritableMessage message = new WritableMessage(recipientUserId, textBody);
messageClient.send(message);
}
}
public void addMessageClientListener(MessageClientListener listener) {
if (messageClient != null) {
messageClient.addMessageClientListener(listener);
}
}
public void removeMessageClientListener(MessageClientListener listener) {
if (messageClient != null) {
messageClient.removeMessageClientListener(listener);
}
}
#Override
public void onDestroy() {
sinchClient.stopListeningOnActiveConnection();
//sinchClient.stop();
sinchClient.terminate();
}
//public interface for ListUsersActivity & MessagingActivity
public class MessageServiceInterface extends Binder {
public void sendMessage(String recipientUserId, String textBody) {
MessageService.this.sendMessage(recipientUserId, textBody);
}
public void addMessageClientListener(MessageClientListener listener) {
MessageService.this.addMessageClientListener(listener);
}
public void removeMessageClientListener(MessageClientListener listener) {
MessageService.this.removeMessageClientListener(listener);
}
public boolean isSinchClientStarted() {
return MessageService.this.isSinchClientStarted();
}
public void terminateSinchClient(){
}
}
}
enter code here
When you log out, our servers dont know that the messages have been delivered to that device. We keep messages for delivery for 30 days. AS a developer you will experience this more since you are wiping the install when you deploy.
If you just kill the app and launch it again you will see that its not delivered again.
There is a couple of ways of avoiding this,
1. Dont log out
2. If you want logout functionality, dont toast as old messages arrive look at time stamp.
or keep track of messages id in your own database
Related
The Image shows the dashboard of the application
package com.example.leeyueloong.proximityapplication;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;
import com.estimote.mustard.rx_goodness.rx_requirements_wizard.Requirement;
import com.estimote.mustard.rx_goodness.rx_requirements_wizard.RequirementsWizardFactory;
import com.estimote.proximity_sdk.proximity.EstimoteCloudCredentials;
import com.estimote.proximity_sdk.proximity.ProximityContext;
import com.estimote.proximity_sdk.proximity.ProximityObserver;
import com.estimote.proximity_sdk.proximity.ProximityObserverBuilder;
import com.estimote.proximity_sdk.proximity.ProximityZone;
import com.ubidots.ApiClient;
import com.ubidots.Variable;
import java.util.ArrayList;
import java.util.List;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
public class MainActivity extends AppCompatActivity {
private ProximityObserver proximityObserver;
private int send;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EstimoteCloudCredentials cloudCredentials =
new EstimoteCloudCredentials("tan-kok-hui-s-proximity-fo-07q", "d18623351c273ce3e09ffcc1f6201861");
// 2. Create the Proximity Observer
this.proximityObserver =
new ProximityObserverBuilder(getApplicationContext(), cloudCredentials)
.withOnErrorAction(new Function1<Throwable, Unit>() {
#Override
public Unit invoke(Throwable throwable) {
Log.e("app", "proximity observer error: " + throwable);
return null;
}
})
.withLowLatencyPowerMode()
.build();
// add this below:
ProximityZone zone = this.proximityObserver.zoneBuilder()
.forTag("desks")
.inNearRange()
.withOnEnterAction(new Function1<ProximityContext, Unit>() {
#Override
public Unit invoke(ProximityContext context) {
String deskOwner = context.getAttachments().get("desk-owner");
Log.d("app", "Welcome to " + deskOwner + "'s desk");
return null;
}
})
.withOnExitAction(new Function1<ProximityContext, Unit>() {
#Override
public Unit invoke(ProximityContext context) {
return null;
}
})
.withOnChangeAction(new Function1<List<? extends ProximityContext>, Unit>() {
#Override
public Unit invoke(List<? extends ProximityContext> contexts) {
List<String> deskOwners = new ArrayList<>();
for (ProximityContext context : contexts) {
deskOwners.add(context.getAttachments().get("desk-owner"));
}
for (int i = 0; i < deskOwners.size(); i++) {
if (deskOwners.get(i).contains("Peter")) {
send = 1;
Toast.makeText(MainActivity.this, "Alert:Unauthorized Zone", Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, "Sending information to ubidots..........", Toast.LENGTH_LONG).show();
} else if (deskOwners.get(i).contains("Alex")) {
send = 0;
Toast.makeText(MainActivity.this, "Device has entered this range", Toast.LENGTH_SHORT).show();
}
else if (deskOwners.get(i).contains("Paul"))
{
}
}
Log.d("app", "In range of desks: " + deskOwners);
return null;
}
})
.create();
this.proximityObserver.addProximityZone(zone);
ProximityZone innerZone = this.proximityObserver.zoneBuilder()
.forTag("treasure")
.inCustomRange(3.0)
.create();
ProximityZone outerZone = this.proximityObserver.zoneBuilder()
.forTag("treasure")
.inCustomRange(9.0)
.create();
RequirementsWizardFactory
.createEstimoteRequirementsWizard()
.fulfillRequirements(MainActivity.this,
// onRequirementsFulfilled
new Function0<Unit>() {
#Override
public Unit invoke() {
Log.d("app", "requirements fulfilled");
proximityObserver.start();
return null;
}
},
// onRequirementsMissing
new Function1<List<? extends Requirement>, Unit>() {
#Override
public Unit invoke(List<? extends Requirement> requirements) {
Log.e("app", "requirements missing: " + requirements);
return null;
}
},
// onError
new Function1<Throwable, Unit>() {
#Override
public Unit invoke(Throwable throwable) {
Log.e("app", "requirements error: " + throwable);
return null;
}
});
}
private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (send == 1 || send == 0) {
new ApiUbidots().execute(send);
}
}
};
#Override
protected void onStart() {
super.onStart();
registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
// Stop the BroadcastReceiver
#Override
protected void onStop() {
unregisterReceiver(mBatteryReceiver);
super.onStop();
}
// In Charge of sending variable to ubidots
public class ApiUbidots extends AsyncTask<Integer, Void, Void> {
private final String API_KEY = "A1E-0109ebb46b4990a4ed82f74d2912a9e6b481";
private final String VARIABLE_ID = "5b62ab7ac03f97418ba1c28e";
#Override
protected Void doInBackground(Integer... params) {
ApiClient apiClient = new ApiClient(API_KEY);
Variable batteryLevel = apiClient.getVariable(VARIABLE_ID);
batteryLevel.saveValue(params[0]);
return null;
}
}
}
The problem is i am able to sending the data to the ubidots however i want to make it so that only if the condition has met, it will then send to the cloud. Other than that, it would not have send any data to the cloud.
I'm making a library that uses Android Wear's DataMap Api to send information between a Wear device and a phone. I've got the DataMap Api working with another project, but despite using the same steps, it doesn't seem to work in this one. If I use putDataItem on the wear device, or the phone, onDataChanged is only called on the device that changed the data, not the other device.
I've looked everywhere else I could find. I've included a timestamp in my data to make sure the data changes, I've set the PutDataRequest as Urgent with setUrgent() to make sure it gets sent immediately, and I've made sure the onResult returns true when I send the data. The gms versions in the manifest match, and I've tried setting up the intent filter in the manifest too.
Here's the code I've been using:
Phone Part:
package a.package.name; //I've changed this here, to hide stuff.. it's the same as below, though.
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
public class WatchCommsPhone implements DataApi.DataListener, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, ResultCallback {
public static final String DATA_PATH_WATCH = "/watch_comms1";
public static final String DATA_PATH_PHONE = "/watch_comms2";
private GoogleApiClient gac;
Context c;
WatchCommsCallback wcc;
Handler h = new Handler();
public WatchCommsPhone(Context currentContext, WatchCommsCallback callback){
wcc = callback;
c = currentContext;
gac = new GoogleApiClient.Builder(c).addApi(Wearable.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
gac.connect();
}
public void sendString(String message,long timestamp, String tag){
PutDataMapRequest pdmr = PutDataMapRequest.create(DATA_PATH_PHONE);
DataMap dm = pdmr.getDataMap();
Asset a = Asset.createFromBytes(message.getBytes());
dm.putAsset("data",a);
dm.putLong("timestamp", timestamp);
dm.putString("tag",tag);
PutDataRequest pdr = pdmr.asPutDataRequest();
pdr.setUrgent();
Wearable.DataApi.putDataItem(gac,pdr).setResultCallback(this);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d("WatchCommsPhone","Watch Comms Watch: Connected");
Wearable.DataApi.addListener(gac,this);
}
#Override
public void onConnectionSuspended(int i) {
Log.d("WatchCommsPhone","Watch Comms Watch: Connection Suspended");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e("WatchCommsPhone","Watch Comms Watch: Connection Failed");
}
#Override
public void onDataChanged(DataEventBuffer dataEventBuffer) { //This gets called when you get data!
Log.d("WatchCommsPhone", "On Data Changed!");
for (DataEvent event: dataEventBuffer){
if (event.getType() == DataEvent.TYPE_CHANGED){
Log.d("WatchCommsPhone","Got data of path: " + event.getDataItem().getUri().getPath());
if(event.getDataItem().getUri().getPath().equals(DATA_PATH_WATCH)){
Log.d("WatchCommsPhone","Got data from watch.");
DataMap dm = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
String tag = dm.getString("tag");
Long timestamp = dm.getLong("timestamp");
String data = dm.getString("data");
ProcessData pd = new ProcessData(tag,data,timestamp);
h.post(pd);
}
}
}
}
#Override
public void onResult(#NonNull Result result) {
Log.d("WatchCommsPhone","onResultCalled: " + result.getStatus().isSuccess());
}
public interface WatchCommsCallback{
void onWatchMessageReceived(String tag, String message, long timestamp);
}
public class ProcessData implements Runnable{
String tag;
String data;
Long timestamp;
public ProcessData(String receivedTag, String receivedData, Long receivedTimestamp){
tag = receivedTag;
data = receivedData;
timestamp = receivedTimestamp;
}
#Override
public void run(){
wcc.onWatchMessageReceived(tag,data,timestamp);
}
}
}
Then the Wear part:
package a.package.name; //I've changed this here, to hide stuff.. it's the same as above, though.
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.Asset;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
public class WatchCommsWatch implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, DataApi.DataListener, ResultCallback {
public static final String DATA_PATH_WATCH = "/watch_comms1";
public static final String DATA_PATH_PHONE = "/watch_comms2";
Context c;
GoogleApiClient gac;
WatchCommsCallback wcc;
Handler h = new Handler();
public WatchCommsWatch(Context currentContext,WatchCommsCallback callback){
wcc = callback;
c = currentContext;
gac = new GoogleApiClient.Builder(c).addApi(Wearable.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
gac.connect();
}
public void sendString(String message,long timestamp, String tag){
PutDataMapRequest pdmr = PutDataMapRequest.create(DATA_PATH_WATCH);
pdmr.setUrgent();
DataMap dm = pdmr.getDataMap();
Asset a = Asset.createFromBytes(message.getBytes());
dm.putAsset("data",a);
dm.putLong("timestamp", timestamp);
dm.putString("tag",tag);
PutDataRequest pdr = pdmr.asPutDataRequest();
pdr.setUrgent();
Wearable.DataApi.putDataItem(gac,pdr).setResultCallback(this);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d("WatchCommsWatch","Watch Connected.");
Wearable.DataApi.addListener(gac,this);
}
#Override
public void onConnectionSuspended(int i) {
Log.d("WatchCommsWatch","Watch Connection Suspended.");
}
#Override
public void onDataChanged(DataEventBuffer dataEventBuffer) {
Log.d("WatchCommsWatch","onDataChanged Called.");
for (DataEvent event: dataEventBuffer){
if (event.getType() == DataEvent.TYPE_CHANGED){
if(event.getDataItem().getUri().getPath().equals(DATA_PATH_WATCH)){
Log.d("WatchCommsWatch","Got data from watch.");
DataMap dm = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
String tag = dm.getString("tag");
Long timestamp = dm.getLong("timestamp");
Asset dataAsset = dm.getAsset("data");
//String data = new String(dataAsset.getData());
String data = tag;
ProcessData pd = new ProcessData(tag,data,timestamp);
h.post(pd);
}
}
}
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e("WatchCommsWatch","WatchCommsWatch: Connection Failed.");
}
#Override
public void onResult(#NonNull Result result) {
Log.d("WatchCommsWatch","onResultCalled: " + result.getStatus().isSuccess());
}
public interface WatchCommsCallback{
void onWatchMessageReceived(String message, String tag, long timestamp);
}
public class ProcessData implements Runnable{
String tag;
String data;
Long timestamp;
public ProcessData(String receivedTag, String receivedData, Long receivedTimestamp){
tag = receivedTag;
data = receivedData;
timestamp = receivedTimestamp;
}
#Override
public void run(){
wcc.onWatchMessageReceived(tag,data,timestamp);
}
}
}
Thanks!
Of course you are free to choose their own way, but for my taste i prefer RXWear from Patloev
https://github.com/patloew/RxWear
See this snippet from my E52 watchface
Receive complex obj data from wear:
rxWear.message().listen("/dataMap", MessageApi.FILTER_LITERAL)
.compose(MessageEventGetDataMap.noFilter())
.subscribe(dataMap -> {
// String title = dataMap.getString("title", getString(R.string.no_message));
if (dataMap.containsKey("alWearTimersCategories")) {
String json = dataMap.getString("alWearTimersCategories");
alTimersCategories= allData.convertStringToALTimerWorkspace(json);
allData.setAlTimersCategoriesFromWear(alTimersCategories);
if (indata != null) {
timerdataset.refreshInternalData(alTimersCategories.get( iActiveWorkSpaceindex).alTimersCategoryInWorkspace);
}
}
});
Send some to clock:
rxWear.message().sendDataMapToAllRemoteNodes("/dataMap")
.putString("timers", "TimersCategories")
.putString("alTimersCategories", convertALTimerWorkspace(alTimersCategories))
.toObservable()
.subscribe(requestId -> { });
}
I am creating chat app using smack API 4.1.8. I am getting composing status when user starts typing in one-to-one chat. But I am not getting how to achieve same in group chatting. Here is my code for single chat:
chatStateManager=ChatStateManager.getInstance(RoosterConnection.xmppConnection);
chat=ChatManager.getInstanceFor(RoosterConnection.xmppConnection).createChat(str+"#service_name");
try {
chatStateManager.setCurrentState(ChatState.composing,chat);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
Log.d(TAG,"...NotConnectedException occured in onCreate().");
}`
Create in the same package and use like ChatStateManager.
package org.jivesoftware.smack;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromTypeFilter;
import org.jivesoftware.smack.filter.MessageTypeFilter;
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.chatstates.ChatState;
import org.jivesoftware.smackx.chatstates.ChatStateManager;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.muc.MultiUserChatManager;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MUChatStateManager extends Manager {
private static final Logger LOGGER = Logger.getLogger(ChatStateManager.class.getName());
public static final String NAMESPACE = "http://jabber.org/protocol/chatstates";
private static final Map<XMPPConnection, MUChatStateManager> INSTANCES = new WeakHashMap<>();
private static final StanzaFilter INCOMING_MESSAGE_FILTER =
new AndFilter(MessageTypeFilter.GROUPCHAT, FromTypeFilter.ENTITY_FULL_JID);
private static final StanzaFilter INCOMING_CHAT_STATE_FILTER = new AndFilter(INCOMING_MESSAGE_FILTER, new StanzaExtensionFilter(NAMESPACE));
private final Set<MUChatStateListener> chatStateListeners = new HashSet<>();
private final AsyncButOrdered<MultiUserChat> asyncButOrdered = new AsyncButOrdered<>();
public static synchronized MUChatStateManager getInstance(final XMPPConnection connection) {
MUChatStateManager manager = INSTANCES.get(connection);
if (manager == null) {
manager = new MUChatStateManager(connection);
INSTANCES.put(connection, manager);
}
return manager;
}
private MUChatStateManager(XMPPConnection connection) {
super(connection);
connection.addSyncStanzaListener(stanza -> {
final Message message = (Message) stanza;
EntityFullJid fullFrom = message.getFrom().asEntityFullJidIfPossible();
EntityBareJid bareFrom = fullFrom.asEntityBareJid();
final MultiUserChat chat = MultiUserChatManager.getInstanceFor(connection()).getMultiUserChat(bareFrom);
ExtensionElement extension = message.getExtension(NAMESPACE);
String chatStateElementName = extension.getElementName();
ChatState state;
try {
state = ChatState.valueOf(chatStateElementName);
} catch (Exception ex) {
LOGGER.log(Level.WARNING, "Invalid chat state element name: " + chatStateElementName, ex);
return;
}
final ChatState finalState = state;
List<MUChatStateListener> listeners;
synchronized (chatStateListeners) {
listeners = new ArrayList<>(chatStateListeners.size());
listeners.addAll(chatStateListeners);
}
final List<MUChatStateListener> finalListeners = listeners;
asyncButOrdered.performAsyncButOrdered(chat, () -> {
for (MUChatStateListener listener : finalListeners) {
listener.stateChanged(chat, finalState, message);
}
});
}, INCOMING_CHAT_STATE_FILTER);
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(NAMESPACE);
}
/**
* Register a ChatStateListener. That listener will be informed about changed chat states.
*
* #param listener chatStateListener
* #return true, if the listener was not registered before
*/
public boolean addChatStateListener(MUChatStateListener listener) {
synchronized (chatStateListeners) {
return chatStateListeners.add(listener);
}
}
/**
* Unregister a ChatStateListener.
*
* #param listener chatStateListener
* #return true, if the listener was registered before
*/
public boolean removeChatStateListener(MUChatStateListener listener) {
synchronized (chatStateListeners) {
return chatStateListeners.remove(listener);
}
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MUChatStateManager that = (MUChatStateManager) o;
return connection().equals(that.connection());
}
#Override
public int hashCode() {
return connection().hashCode();
}
public interface MUChatStateListener {
void stateChanged(MultiUserChat chat, ChatState finalState, Message message);
}
}
But this class only for observing. You can send custom message like this:
public void changeChatStateMUC(ChatState state, String chatJid) {
try {
Message statusPacket = new Message();
statusPacket.setBody(null);
statusPacket.setType(Message.Type.groupchat);
statusPacket.setTo(chatJid);
ChatStateExtension extension = new ChatStateExtension(state);
statusPacket.addExtension(extension);
sendStanza(statusPacket);
} catch (SmackException.NotConnectedException | InterruptedException e) {
e.printStackTrace();
}
}
public void sendStanza(Stanza stanza) throws SmackException.NotConnectedException, InterruptedException {
xmpptcpConnection.sendStanza(stanza);
}
I am using telegram API to develop my application. Here is the whole code.
app_info.java:
package com.example.mytelegram;
import org.telegram.api.engine.AppInfo;
public class app_info extends AppInfo {
public app_info(int apiId, String deviceModel, String systemVersion,
String appVersion, String langCode) {
super(apiId, deviceModel, systemVersion, appVersion, langCode);
// TODO Auto-generated constructor stub
}
MemoryApiState.java:
package com.example.mytelegram;
import org.telegram.api.TLConfig;
import org.telegram.api.TLDcOption;
import org.telegram.api.engine.storage.AbsApiState;
import org.telegram.mtproto.state.AbsMTProtoState;
import org.telegram.mtproto.state.ConnectionInfo;
import org.telegram.mtproto.state.KnownSalt;
import java.util.ArrayList;
import java.util.HashMap;
public class MemoryApiState implements AbsApiState {
private HashMap<Integer, ConnectionInfo[]> connections = new HashMap<Integer, ConnectionInfo[]>();
private HashMap<Integer, byte[]> keys = new HashMap<Integer, byte[]>();
private HashMap<Integer, Boolean> isAuth = new HashMap<Integer, Boolean>();
private int primaryDc = 2; // I have tested application with primaryDc=0 to 10
public MemoryApiState(boolean isTest) {
connections.put(1, new ConnectionInfo[]{
new ConnectionInfo(1, 0, isTest ? "149.154.167.40" : "149.154.167.50", 443)
});
}
#Override
public synchronized int getPrimaryDc() {
return primaryDc;
}
#Override
public synchronized void setPrimaryDc(int dc) {
primaryDc = dc;
}
#Override
public synchronized boolean isAuthenticated(int dcId) {
if (isAuth.containsKey(dcId)) {
return isAuth.get(dcId);
}
return false;
}
#Override
public synchronized void setAuthenticated(int dcId, boolean auth) {
isAuth.put(dcId, auth);
}
#Override
public synchronized void updateSettings(TLConfig config) {
connections.clear();
HashMap<Integer, ArrayList<ConnectionInfo>> tConnections = new HashMap<Integer, ArrayList<ConnectionInfo>>();
int id = 0;
for (TLDcOption option : config.getDcOptions()) {
if (!tConnections.containsKey(option.getId())) {
tConnections.put(option.getId(), new ArrayList<ConnectionInfo>());
}
tConnections.get(option.getId()).add(new ConnectionInfo(id++, 0, option.getIpAddress(), option.getPort()));
}
for (Integer dc : tConnections.keySet()) {
connections.put(dc, tConnections.get(dc).toArray(new ConnectionInfo[0]));
}
}
#Override
public synchronized byte[] getAuthKey(int dcId) {
return keys.get(dcId);
}
#Override
public synchronized void putAuthKey(int dcId, byte[] key) {
keys.put(dcId, key);
}
#Override
public synchronized ConnectionInfo[] getAvailableConnections(int dcId) {
if (!connections.containsKey(dcId)) {
return new ConnectionInfo[0];
}
return connections.get(dcId);
}
#Override
public synchronized AbsMTProtoState getMtProtoState(final int dcId) {
return new AbsMTProtoState() {
private KnownSalt[] knownSalts = new KnownSalt[0];
#Override
public byte[] getAuthKey() {
return MemoryApiState.this.getAuthKey(dcId);
}
#Override
public ConnectionInfo[] getAvailableConnections() {
return MemoryApiState.this.getAvailableConnections(dcId);
}
#Override
public KnownSalt[] readKnownSalts() {
return knownSalts;
}
#Override
protected void writeKnownSalts(KnownSalt[] salts) {
knownSalts = salts;
}
};
}
#Override
public synchronized void resetAuth() {
isAuth.clear();
}
#Override
public synchronized void reset() {
isAuth.clear();
keys.clear();
}
}
MainActivity.java:
package com.example.mytelegram;
import java.io.IOException;
import org.telegram.api.TLAbsUpdates;
import org.telegram.api.TLConfig;
import org.telegram.api.TLNearestDc;
import org.telegram.api.auth.TLAuthorization;
import org.telegram.api.auth.TLSentCode;
import org.telegram.api.engine.ApiCallback;
import org.telegram.api.engine.AppInfo;
import org.telegram.api.engine.LoggerInterface;
import org.telegram.api.engine.RpcException;
import org.telegram.api.engine.TelegramApi;
import org.telegram.api.requests.TLRequestAuthSendCall;
import org.telegram.api.requests.TLRequestAuthSendCode;
import org.telegram.api.requests.TLRequestAuthSignIn;
import org.telegram.api.requests.TLRequestHelpGetConfig;
import org.telegram.api.requests.TLRequestHelpGetNearestDc;
import org.telegram.api.requests.TLRequestUpdatesGetState;
import org.telegram.api.updates.TLState;
import android.support.v7.app.ActionBarActivity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends ActionBarActivity {
static Context context;
private static AppInfo ai;
private static void createApi() throws IOException {
String res = "No test";
boolean useTest = res.equals("test");
apiState = new MemoryApiState(useTest);
ai=new AppInfo(App_ID, "Sony", "???", "???", "en");
api = new TelegramApi(apiState, ai, new ApiCallback() {
#Override
public void onAuthCancelled(TelegramApi api) {
}
#Override
public void onUpdatesInvalidated(TelegramApi api) {
}
#Override
public void onUpdate(TLAbsUpdates updates) {
Log.d("tlg", "onUpdate(TLAbsUpdates updates)");
}
});
}
private static void login() throws IOException {
//TLNearestDc dcInfo = api.doRpcCallNonAuth(new TLRequestHelpGetNearestDc());
// api.switchToDc(dcInfo.getNearestDc());
//************ Exception raises here ************
TLConfig config = api.doRpcCallNonAuth(new TLRequestHelpGetConfig()); // I have An IOException Here (e=timeout Exception)
apiState.updateSettings(config);
Log.d("tlg","completed.");
String phone = "+9891********"; // I have tested app with the phone without plus too
Log.d("tlg","Sending sms to phone " + phone + "...");
TLSentCode sentCode = null;
try {
api.doRpcCallNonAuth(new TLRequestAuthSendCode(phone, 1, app_id, "__hash__", "en"));
} catch (RpcException e) {
if (e.getErrorCode() == 303) {
int destDC;
if (e.getErrorTag().startsWith("NETWORK_MIGRATE_")) {
destDC = Integer.parseInt(e.getErrorTag().substring("NETWORK_MIGRATE_".length()));
} else if (e.getErrorTag().startsWith("PHONE_MIGRATE_")) {
destDC = Integer.parseInt(e.getErrorTag().substring("PHONE_MIGRATE_".length()));
} else if (e.getErrorTag().startsWith("USER_MIGRATE_")) {
destDC = Integer.parseInt(e.getErrorTag().substring("USER_MIGRATE_".length()));
} else {
throw e;
}
api.switchToDc(destDC);
sentCode = api.doRpcCallNonAuth(new TLRequestAuthSendCode(phone, 0, app_id, "__hash__", "en"));
} else {
throw e;
}
}
Log.d("tlg","Activation code:");
String code = "123";
TLAuthorization auth = api.doRpcCallNonAuth(new TLRequestAuthSignIn(phone, sentCode.getPhoneCodeHash(), code));
apiState.setAuthenticated(apiState.getPrimaryDc(), true);
Log.d("tlg","Activation complete.");
TLState state = api.doRpcCall(new TLRequestUpdatesGetState());
Log.d("tlg","loaded.");
}
static MemoryApiState apiState;
static TelegramApi api;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context=getApplicationContext();
try {
createApi();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
login();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//workLoop();
}
}
I have added telegram-api library (telegram-api-1.1.127-shadow.jar) in my eclipse 'libs' folder. The problem is Timeout Exception in MainActivity.java when I want to call RPC. Where is the problem? What should I do? My OS is windows 8.1 . I am searching for 2 whole days. I have read github codes too. They are very complicated for me. I can not figure out what should I do?
I have added INTERNET and ACCESS_NETWORK_STATE permisions to AndroidManifest.xml. I allways check the network connection when my application runs.
I found the problem in your code:
In MemoryApiState you should put, in the 'connections' map, 'primaryDc' as key and not '1'.
I'm trying to get all the user chats (created in my database) using an ArrayList and Recyclerview.Adapter but only first item from my ArrayList is being shown on my emulator screen.
Here's the corresponding code:
MainActivity:
package com.wipro.chat.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import com.wipro.chat.R;
import com.wipro.chat.adapter.ChatRoomsAdapter;
import com.wipro.chat.app.Config;
import com.wipro.chat.app.EndPoints;
import com.wipro.chat.app.MyApplication;
import com.wipro.chat.gcm.GcmIntentService;
import com.wipro.chat.gcm.NotificationUtils;
import com.wipro.chat.helper.SimpleDividerItemDecoration;
import com.wipro.chat.model.ChatRoom;
import com.wipro.chat.model.Message;
public class MainActivity extends AppCompatActivity {
private String TAG = MainActivity.class.getSimpleName();
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private BroadcastReceiver mRegistrationBroadcastReceiver;
private ArrayList<ChatRoom> chatRoomArrayList;
private ChatRoomsAdapter mAdapter;
private RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* Check for login session. If not logged in launch
* login activity
* */
if (MyApplication.getInstance().getPrefManager().getUser() == null) {
launchLoginActivity();
}
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
/**
* Broadcast receiver calls in two scenarios
* 1. gcm registration is completed
* 2. when new push notification is received
* */
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// checking for type intent filter
if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
// gcm successfully registered
// now subscribe to `global` topic to receive app wide notifications
subscribeToGlobalTopic();
} else if (intent.getAction().equals(Config.SENT_TOKEN_TO_SERVER)) {
// gcm registration id is stored in our server's MySQL
Log.e(TAG, "GCM registration id is sent to our server");
} else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
// new push notification is received
handlePushNotification(intent);
}
}
};
chatRoomArrayList = new ArrayList<>();
mAdapter = new ChatRoomsAdapter(this, chatRoomArrayList);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(new SimpleDividerItemDecoration(
getApplicationContext()
));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
recyclerView.addOnItemTouchListener(new ChatRoomsAdapter.RecyclerTouchListener(getApplicationContext(), recyclerView, new ChatRoomsAdapter.ClickListener() {
#Override
public void onClick(View view, int position) {
// when chat is clicked, launch full chat thread activity
ChatRoom userChatRoom = chatRoomArrayList.get(position);
Intent intent = new Intent(MainActivity.this, ChatRoomActivity.class);
intent.putExtra("user_id", userChatRoom.getId());
intent.putExtra("name", userChatRoom.getName());
startActivity(intent);
}
#Override
public void onLongClick(View view, int position) {
}
}));
/**
* Always check for google play services availability before
* proceeding further with GCM
* */
if (checkPlayServices()) {
registerGCM();
fetchChatRooms();
}
}
/**
* Handles new push notification
*/
private void handlePushNotification(Intent intent) {
/*int type = intent.getIntExtra("type", -1);
// if the push is of chat room message
// simply update the UI unread messages count
if (type == Config.PUSH_TYPE_CHATROOM) {
Message message = (Message) intent.getSerializableExtra("message");
String chatRoomId = intent.getStringExtra("chat_room_id");
if (message != null && chatRoomId != null) {
updateRow(chatRoomId, message);
}
} else if (type == Config.PUSH_TYPE_USER) {
// push belongs to user alone
// just showing the message in a toast
Message message = (Message) intent.getSerializableExtra("message");
Toast.makeText(getApplicationContext(), "New push: " + message.getMessage(), Toast.LENGTH_LONG).show();
}*/
Message message = (Message) intent.getSerializableExtra("message");
String userChatRoomId = intent.getStringExtra("user_id");
if (message != null && userChatRoomId != null) {
updateRow(userChatRoomId, message);
}
}
/**
* Updates the chat list unread count and the last message
*/
private void updateRow(String chatRoomId, Message message) {
for (ChatRoom cr : chatRoomArrayList) {
if (cr.getId().equals(chatRoomId)) {
int index = chatRoomArrayList.indexOf(cr);
cr.setLastMessage(message.getMessage());
cr.setUnreadCount(cr.getUnreadCount() + 1);
chatRoomArrayList.remove(index);
chatRoomArrayList.add(index, cr);
break;
}
}
mAdapter.notifyDataSetChanged();
}
/**
* fetching the chat rooms by making http call
*/
private void fetchChatRooms() {
StringRequest strReq = new StringRequest(Request.Method.GET,
EndPoints.CHAT_ROOMS, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e(TAG, "response: " + response);
try {
JSONObject obj = new JSONObject(response);
// check for error flag
if (obj.getBoolean("error") == false) {
JSONArray chatRoomsArray = obj.getJSONArray("chat_rooms");
for (int i = 0; i < chatRoomsArray.length(); i++) {
JSONObject chatRoomsObj = (JSONObject) chatRoomsArray.get(i);
ChatRoom cr = new ChatRoom();
cr.setId(chatRoomsObj.getString("user_id"));
cr.setName(chatRoomsObj.getString("name"));
cr.setLastMessage("");
cr.setUnreadCount(0);
cr.setTimestamp(chatRoomsObj.getString("created_at"));
chatRoomArrayList.add(cr);
}
} else {
// error in fetching chat rooms
Toast.makeText(getApplicationContext(), "" + obj.getJSONObject("error").getString("message"), Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
Log.e(TAG, "json parsing error: " + e.getMessage());
Toast.makeText(getApplicationContext(), "Json parse error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
mAdapter.notifyDataSetChanged();
// subscribing to all chat room topics
//subscribeToAllTopics();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
NetworkResponse networkResponse = error.networkResponse;
Log.e(TAG, "Volley error: " + error.getMessage() + ", code: " + networkResponse);
Toast.makeText(getApplicationContext(), "Volley error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
//Adding request to request queue
MyApplication.getInstance().addToRequestQueue(strReq);
}
// subscribing to global topic
private void subscribeToGlobalTopic() {
Intent intent = new Intent(this, GcmIntentService.class);
intent.putExtra(GcmIntentService.KEY, GcmIntentService.SUBSCRIBE);
intent.putExtra(GcmIntentService.TOPIC, Config.TOPIC_GLOBAL);
startService(intent);
}
// Subscribing to all chat room topics
// each topic name starts with `topic_` followed by the ID of the chat room
// Ex: topic_1, topic_2
/*private void subscribeToAllTopics() {
for (ChatRoom cr : chatRoomArrayList) {
Intent intent = new Intent(this, GcmIntentService.class);
intent.putExtra(GcmIntentService.KEY, GcmIntentService.SUBSCRIBE);
intent.putExtra(GcmIntentService.TOPIC, "topic_" + cr.getId());
startService(intent);
}
}*/
private void launchLoginActivity() {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
#Override
protected void onResume() {
super.onResume();
// register GCM registration complete receiver
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(Config.REGISTRATION_COMPLETE));
// register new push message receiver
// by doing this, the activity will be notified each time a new message arrives
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(Config.PUSH_NOTIFICATION));
// clearing the notification tray
NotificationUtils.clearNotifications();
}
#Override
protected void onPause() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
super.onPause();
}
// starting the service to register with GCM
private void registerGCM() {
Intent intent = new Intent(this, GcmIntentService.class);
intent.putExtra("key", "register");
startService(intent);
}
private boolean checkPlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
.show();
} else {
Log.i(TAG, "This device is not supported. Google Play Services not installed!");
Toast.makeText(getApplicationContext(), "This device is not supported. Google Play Services not installed!", Toast.LENGTH_LONG).show();
finish();
}
return false;
}
return true;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_logout:
MyApplication.getInstance().logout();
break;
}
return super.onOptionsItemSelected(menuItem);
}
}
ChatRoomsAdapter:
package com.wipro.chat.adapter;
/**
* Created by COMP on 16-06-2016.
*/
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import com.wipro.chat.R;
import com.wipro.chat.model.ChatRoom;
public class ChatRoomsAdapter extends RecyclerView.Adapter<ChatRoomsAdapter.ViewHolder> {
private Context mContext;
private ArrayList<ChatRoom> chatRoomArrayList;
private static String today;
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView name, message, timestamp, count;
public ViewHolder(View view) {
super(view);
name = (TextView) view.findViewById(R.id.name);
message = (TextView) view.findViewById(R.id.message);
timestamp = (TextView) view.findViewById(R.id.timestamp);
count = (TextView) view.findViewById(R.id.count);
}
}
public ChatRoomsAdapter(Context mContext, ArrayList<ChatRoom> chatRoomArrayList) {
this.mContext = mContext;
this.chatRoomArrayList = chatRoomArrayList;
Calendar calendar = Calendar.getInstance();
today = String.valueOf(calendar.get(Calendar.DAY_OF_MONTH));
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.chat_rooms_list_row, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
ChatRoom chatRoom = chatRoomArrayList.get(position);
holder.name.setText(chatRoom.getName());
holder.message.setText(chatRoom.getLastMessage());
if (chatRoom.getUnreadCount() > 0) {
holder.count.setText(String.valueOf(chatRoom.getUnreadCount()));
holder.count.setVisibility(View.VISIBLE);
} else {
holder.count.setVisibility(View.GONE);
}
holder.timestamp.setText(getTimeStamp(chatRoom.getTimestamp()));
}
#Override
public int getItemCount() {
return chatRoomArrayList.size();
}
public static String getTimeStamp(String dateStr) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String timestamp = "";
today = today.length() < 2 ? "0" + today : today;
try {
Date date = format.parse(dateStr);
SimpleDateFormat todayFormat = new SimpleDateFormat("dd");
String dateToday = todayFormat.format(date);
format = dateToday.equals(today) ? new SimpleDateFormat("hh:mm a") : new SimpleDateFormat("dd LLL, hh:mm a");
String date1 = format.format(date);
timestamp = date1.toString();
} catch (ParseException e) {
e.printStackTrace();
}
return timestamp;
}
public interface ClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
public static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ChatRoomsAdapter.ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ChatRoomsAdapter.ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildLayoutPosition(child));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildLayoutPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
}
PHP code which is retrieving the chatroom is like:
/* * *
* fetching all chat rooms
*/
$app->get('/chat_rooms', function() {
$response = array();
$db = new DbHandler();
// fetching all user tasks
$result = $db->getAllChats();
$response["error"] = false;
$response["chat_rooms"] = array();
// pushing single chat room into array
while ($chat_room = $result->fetch_assoc()) {
$tmp = array();
$tmp["user_id"] = $chat_room["user_id"];
$tmp["name"] = $chat_room["name"];
$tmp["created_at"] = $chat_room["created_at"];
array_push($response["chat_rooms"], $tmp);
}
echoRespnse(200, $response);
});
public function getAllChats() {
$stmt = $this->conn->prepare("SELECT user_id, name, created_at FROM users");
$stmt->execute();
$tasks = $stmt->get_result();
$stmt->close();
return $tasks;
}
There are two user chats in my database, namely Messaging, Chat and I'm getting the both from database into ArrayList but it is only showing Messaging.
Adapter display:
Response from database:
Check recycler_view in your main layout. The height should be set to "wrap_content".