Group chat in gtalk for Android - android

I am making gtalk Im using smack 3.2.1 API.
I am stuck with group chat implementation.
here is my code for initiate a group chat:
conf = new MultiUserChat(connection, "room#groupchat.google.com"); // create object of multiserchat class
try
{ // Create the room
conf.create("room#groupchat.google.com");
// Send an empty room configuration form which indicates that we want an instant room
conf.sendConfigurationForm(new Form(Form.TYPE_SUBMIT));
}
catch (XMPPException e)
{
Toast.makeText(this, "Error in create room: "+e.toString(), Toast.LENGTH_LONG).show();
}
conf.invite("userid", "Invitation for group chat");
But I am getting error: Service not Available (503)
Thanks in advance.

Room should be -- private-chat-
And there is no need to create room.
Simply join the room with users name and password. That will satishfy:
Code snippet:
String room = "private-chat-" + UUID.randomUUID().toString();
room = room + "#groupchat.google.com";
MultiUserChat muc = new MultiUserChat(cc, room);
muc.join("username", "password");
muc.invite("username", "hi");
Let me know if this works.

Related

SmackAndroid(context) not found user search module ejabberd

I am working upon a android based chat application using ejabberd-17.01 server on windows. Using Smack 4.1 for android. I want to search for users using following code
public void searchUser(){
try {
UserSearchManager userSearchManager = new UserSearchManager(connection);
Collection<String> services = userSearchManager.getSearchServices();
if(services.isEmpty()){
return;
}
Form searchForm = userSearchManager.getSearchForm(services.iterator().next());
Form answerForm = searchForm.createAnswerForm();
answerForm.setAnswer("Name", true);
answerForm.setAnswer("search", "test"); // here i'm passsing the Text value to search
ReportedData resultData;
resultData = userSearchManager.getSearchResults(answerForm, "search." + connection.getServiceName());
Iterator<ReportedData.Row> it = (Iterator)resultData.getRows();
ReportedData.Row row = null;
while (it.hasNext()) {
String value = it.next().toString();
Log.i("Iteartor values......", " " + value);
System.out.println("Jabber_id :" + row.getValues("jid").toString());
System.out.println("Name :" + row.getValues("Name").toString());
row = it.next();
}
}
catch (SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException | XmppStringprepException e){
Log.w("app" , e.toString());
}
}
my problem is that
userSearchManager.getSearchServices()
returns zero values. I read about that i should initialize smack for android by calling SmackAndroid.init(context) before connection but whenever i write this it only says create class SmackAndroid(context) and does not show any import.
compile "org.igniterealtime.smack:smack-im:4.1.0"
compile "org.igniterealtime.smack:smack-android:4.1.0"
compile "org.igniterealtime.smack:smack-tcp:4.1.0"
compile "org.igniterealtime.smack:smack-extensions:4.1.0"
i also tested all dependencies mentioned in smack document but cant find this method. What am i missing or is there any other way to search register user in ejabberd. Also i want to know do i need to add any module to ejabberd for searching purpose like search module is added manually in openfire server?

Invitation Listener not working smack 4.2

I can create group chat room successfully XMPP(smack). I have added
invitation listener, but never called. Does anyone know how to do it?
Using:
XMPP
Smack 4.2
Openfire server
Send Invitation code:
muc.invite(userId +"#" +XMPP.getInstance().HOST + "/Smack", "Meet me in this excellent room");
Invitation listener code:
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);
manager.addInvitationListener(new InvitationListener() {
#Override
public void invitationReceived(XMPPConnection xmppConnection, MultiUserChat muc, String inviter, String reason, String password, Message message) {
try {
muc.join(nickname);
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
}
});
Probably you have an issue about RESOURCE.
When you send an invitation to a certain JID, you might omit resource part or the message will be sent only to specified resource.
JID it's composed in following way:
user#serverdomain/resource
With this invitation, you are inviting only user using "Smack" as Resource.
Resource it's configurated in AbstractXMPPConnection object or in login phase
XMPPTCPConnectionConfiguration.builder()
.setServiceName(serverName)
.setHost(server)
.setPort(port)
.setResource( RESOURCE_IDENTIFIER)
.build();
connection = new XMPPTCPConnection(config);
connection.login(username, password, RESOURCE_IDENTIFIER);
So, probably, you declared as your resource identificator (just an arbitrary String) not "Smack" but "Spark" o something else or left default one.
Just omit Resource part (or fix with correct one, but I suggest to omit)
muc.invite(userId +"#" +XMPP.getInstance().HOST, "Meet me in this excellent room");
Of course, userId must exist and HOST it's the valid one

Offline message not retrive from smack api 4.1.6 from xmpp MongooseIM server

I am facing the issue to retrieve offline message in android apps using smack api from XMPP Mongoose server. As per the code flow Try to retrive offline message when user become login in xmpp mongoose server before sending available presence to mongoose server.
Tried with two different way to retrieve offline message still not able to find working solution for the same. Both method which i tried those all things are explain below with detail.
Below Api we are using for the xmpp connection and all other extension :
// Smack (XMPP Client Library)
compile 'org.igniterealtime.smack:smack-android:4.1.6'

compile 'org.igniterealtime.smack:smack-tcp:4.1.6'
compile 'org.igniterealtime.smack:smack-im:4.1.6'
compile 'org.igniterealtime.smack:smack-android-extensions:4.1.6'
Tried retrive offline message Using offlineMessageManager
Below is code which I tried to retrieve offline message after login and before send available presence to server
try {
Boolean isFelxibleRetrievalSupport = offlineMessageManager.supportsFlexibleRetrieval();
Iterator i = (Iterator) offlineMessageManager.getMessages();
while (i.hasNext())
{
 Message msg = i.next();
 System.out.println("Got text [" + msg.getBody() + "] from [" + msg.getFrom() + "]");
} catch (XMPPException e)
{
 System.out.println("Error Offline Message.");
 e.printStackTrace();
 }
catch (SmackException.NotConnectedException e)
{
 System.out.println("Error Offline Message. No connection");
 e.printStackTrace(); 
}
catch (SmackException.NoResponseException e)
{
 System.out.println("Error Offline Message. No Reponse");
 e.printStackTrace();
 }
Issue case 1:
Below is exception detail which generate when above code execute
I got Exception when execute below line of code.
Iterator i = (Iterator) offlineMessageManager.getMessages();
Below is exception description which Generate when above line execute
org.jivesoftware.smack.XMPPException$XMPPErrorException: XMPPError: service-unavailable - cancel
Issue Case 2:
If checking is Flexible offline message supported from android code using smack from xmmp mongoose server so i got false value. Below is code which i used for testing.
Boolean isFelxibleRetrievalSupport = offlineMessageManager.supportsFlexibleRetrieval();
Issue Case 3:
When I try to retrieve supported features using below method using smack code like below.
ServiceDiscoveryManager manager = ServiceDiscoveryManager
.getInstanceFor(connection);
List AllFetures = manager.getFeatures();
Below is features list which i retrived:
http://jabber.org/protocol/bytestreams,
jabber:iq:privacy, urn:xmpp:ping,
http://jabber.org/protocol/commands,
jabber:iq:version,
jabber:iq:last,
http://jabber.org/protocol/xdata-validate,
http://jabber.org/protocol/xhtml-im,
vcard-temp,
http://jabber.org/protocol/chatstates,
urn:xmpp:receipts, urn:xmpp:time,
http://jabber.org/protocol/xdata-layout,
http://jabber.org/protocol/muc,
http://jabber.org/protocol/disco#items,
http://jabber.org/protocol/disco#info,
http://jabber.org/protocol/caps,
jabber:x:data
Tried to retreive offline message Using package listener from XMPP MongooseIM
below is code which i tried using package listener from smack api 4.1.6.
private static final StanzaFilter MESSAGE_PACKET_FILTER= new OrFilter(StanzaTypeFilter.MESSAGE);
configuration = XMPPTCPConnectionConfiguration.builder()
.setServiceName(SERVICE_NAME)
.setHost(KDevelopmentXMPPServer)
.setPort(PORT)
.setSendPresence(false)
.build();
// Create Connection object of xmpp connection with configured detail
connection = new XMPPTCPConnection(configuration);
connection.addAsyncStanzaListener(new StanzaListener() {
#Override
public void processPacket(Stanza packet) throws SmackException.NotConnectedException {
Log.d("CheckPacket", "OfflineMEssage");
Message message = (Message) packet;
if (message != null) {
if (message.getBody() != null) {
Log.i("XMPPClient", "Got text [" + message.getBody()
+ "] from [" + message.getFrom() + "]");
}
}
}
}, MESSAGE_PACKET_FILTER);
connection.login(user, password);
Thanks In Advance, Please anybody help me for best working solution for my critical issue.
The issue is in trying to fetch offline messages before
sending the initial presence. XEP-0160 states:
When the recipient next sends non-negative available presence to the server, the server delivers the message to the resource that has sent that presence. [...]
MongooseIM works with accordance to this recommendation.
You already pointed out what is signaled by isFlexibleRetrievalSupport - the server does not support flexible offline message retrieval.
I know I am writing this too late, but if someone like me who is hunting for same query as in "how to save and get archive messages in android app" can refer this answer :
Note :
this is implemented in the lastest version
Requrirements :
lastest openfire as of now 4.1.4
install Archives plugin in openfire
MamManager mamManager = MamManager.getInstanceFor(connection);
boolean isSupported = mamManager.isSupportedByServer();
if (isSupported) {
MamManager.MamQueryResult mamQueryResult = mamManager.queryArchive(500);
List<Forwarded> forwardedMessages = mamQueryResult.forwardedMessages;
Forwarded d = forwardedMessages.get(0);
}
Please Refer : Documention for MamManager Class

Android xmpp MUC setting default configuration

Am using the Xabber open source project and am able to create a new group, But it always says: This room is locked from entry until configuration is confirmed. I tried to set a default configuration but it throws me exception: 401 not authorized. Whats exactly the problem.
final MultiUserChat multiUserChat;
try {
multiUserChat = new MultiUserChat(xmppConnection, room);
// CHANAKYA: set default config for the MUC
// Send an empty room configuration form which indicates that we want
// an instant room
try {
multiUserChat.sendConfigurationForm(new Form(Form.TYPE_SUBMIT));
} catch (XMPPException e) {
e.printStackTrace();
}
I was also facing the same error. Here I modified the code and it's work for me.
Error 401 is not authorized error when we are calling the any getConfigurationForm(), without joining it.
multiUserChat.join(nickname, password);
setConfig(multiUserChat); // Here I am calling submit form
private void setConfig(MultiUserChat multiUserChat) {
try {
Form form = multiUserChat.getConfigurationForm();
Form submitForm = form.createAnswerForm();
for (Iterator<FormField> fields = submitForm.getFields(); fields
.hasNext();) {
FormField field = (FormField) fields.next();
if (!FormField.Type.hidden.equals(field.getType())
&& field.getVariable() != null) {
submitForm.setDefaultAnswer(field.getVariable());
}
}
submitForm.setAnswer("muc#roomconfig_publicroom", true);
submitForm.setAnswer("muc#roomconfig_persistentroom", true);
multiUserChat.sendConfigurationForm(submitForm);
} catch (Exception e) {
e.printStackTrace();
}
}
And now I am able to successfully submit the form without any exception. Hope this will work for you.
You must have permissions to set the configuration. This can usually be changed in the server settings. If you have Openfire for example you should go to Group Chat>Group chat settings>Click your Group Chat service>Room Creation Permissions or Administrators.
You are probably unable to change this client side, it's only possible if you have access to the server you are trying to connect to.

Differentiate between GCM and C2DM ids

I'm migrating my app from C2DM to GCM but the server on which i'll be sending the registration id will still be entertaining C2DM ids. So my question is what can I do from my app so that server can identify that this is GCM id. Google recommends to send a new bit along with registration id. How can I do that. Please give an exmaple.
Here's what you need to do if you're not using AppEngine.
In your server, you should already have a table that stores all the registration id (reg_id). You need to add another column to this table, say 'is_gcm_reg_id'. You would default all existing rows to '0' for this column since they are currently all C2DM reg_ids. You could also just create a new table to store the GCM reg_ids, if you like.
Then in your GCM enabled application, you just need to let your server know the reg_id is a GCM reg_id. You didn't mention how you upload the reg_id to your server (Web Service call? Simple POST request?). If using Web Service call, just create a new method that will be used exclusively by your new GCM-enabled app. If using POST request, just add another key value pair like 'gcm=true' and your server should look for this kvp.
Finally, you should have all the pieces needed to know the reg_id is of GCM, and update the 'is_gcm_reg_id' column field (or a new GCM table) accordingly.
Assuming you're using App Engine to implement GCM/C2DM.
In the deviceInfo entity for your App Engine there is already a "type" field. This is the field you will modify to either say "ac2dm" or "gcm".
An easy way to do this is to create a new registration request that simply passes "gcm" instead of "ac2dm". Take a look in your AppEngine project and locate the RegistrationInfo class. Look at the register() method. Simply replace "ac2dm" with "gcm".
EX:
// original
public void register() {
log.info("register " + this);
try {
doRegister(getDeviceRegistrationId(), "ac2dm", getDeviceId(), getAccountName());
} catch (Exception e) {
log.info("Got exception in registration: " + e + " - " + e.getMessage());
for (StackTraceElement ste : e.getStackTrace()) {
log.info(ste.toString());
}
}
log.info("Successfully registered");
}
// new version
public void register() {
log.info("register " + this);
try {
doRegister(getDeviceRegistrationId(), "gcm", getDeviceId(), getAccountName());
} catch (Exception e) {
log.info("Got exception in registration: " + e + " - " + e.getMessage());
for (StackTraceElement ste : e.getStackTrace()) {
log.info(ste.toString());
}
}
log.info("Successfully registered");
}
You will probably have to recompile the RPC service to get this to work.
Now, it's up to you to make sure your server checks for the "gcm" tag of the deviceInfo entity and acts accordingly. Also, read this if you haven't seen it https://developer.android.com/guide/google/gcm/c2dm.html

Categories

Resources