I'm creating XMPP client for FACEBOOK. i did this for gmail, now i have to create same for FaceBook. i googled a lot for this got some code, still i'm getting this type of errors Not connected to server
and service-unavailable(503)
here i'm sharing the code what i did.
public class ClientJabberActivity extends Activity {
ArrayList<String> m_discussionThread;
ArrayAdapter<String> m_discussionThreadAdapter;
XMPPConnection m_connection;
private Handler m_handler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
m_handler = new Handler();
try {
initConnection();
} catch (XMPPException e) {
e.printStackTrace();
}
final EditText recipient = (EditText) this.findViewById(R.id.recipient);
final EditText message = (EditText) this.findViewById(R.id.message);
ListView list = (ListView) this.findViewById(R.id.thread);
m_discussionThread = new ArrayList<String>();
m_discussionThreadAdapter = new ArrayAdapter<String>(this,
R.layout.multi_line_list_item, m_discussionThread);
list.setAdapter(m_discussionThreadAdapter);
Button send = (Button) this.findViewById(R.id.send);
send.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
String to = recipient.getText().toString();
String text = message.getText().toString();
Message msg = new Message(to, Message.Type.chat);
msg.setBody(text);
m_connection.sendPacket(msg);
m_discussionThread.add(" Me : ");
m_discussionThread.add(text);
m_discussionThreadAdapter.notifyDataSetChanged();
}
});
}
private void initConnection() throws XMPPException {
ConnectionConfiguration config = new ConnectionConfiguration(
"chat.facebook.com", 5222, "chat.facebook.com");
config.setSASLAuthenticationEnabled(true);
m_connection = new XMPPConnection(config);
try {
SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM",
SASLXFacebookPlatformMechanism.class);
SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);
m_connection.connect();
m_connection.login(apiKey + "|" + sessionKey, sessionSecret, "Application");
} catch (XMPPException e) {
m_connection.disconnect();
e.printStackTrace();
}
Presence presence = new Presence(Presence.Type.available);
m_connection.sendPacket(presence);
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
m_connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
Message message = (Message) packet;
if (message.getBody() != null) {
String fromName = StringUtils.parseBareAddress(message
.getFrom());
m_discussionThread.add(fromName + ":");
m_discussionThread.add(message.getBody());
m_handler.post(new Runnable() {
public void run() {
m_discussionThreadAdapter.notifyDataSetChanged();
}
});
}
}
}, filter);
ChatManager chatmanager = m_connection.getChatManager();
chatmanager.addChatListener(new ChatManagerListener() {
public void chatCreated(final Chat chat,
final boolean createdLocally) {
chat.addMessageListener(new MessageListener() {
public void processMessage(Chat chat, Message message) {
System.out.println("Received message: "
+ (message != null ? message.getBody() : "NULL"));
Log.i("CHAT USER",
"Received message is: " + message.getBody());
}
});
}
});
}
}
and this class SASLXFacebookPlatformMechanism
How can i login like this xmpp.login(apiKey + "|" + sessionKey, sessionSecret, "Application");
i know how to get acessToken, Application Key for facebook. i don't know about sessionKey, sessionSecret how to get those values and how to solve this problem.
If i use xmpp.login(apiKey, accessToken, "Application");
i am getting this error --IllegalArgumentException: API key or session key is not present
EDIT: Finally i got solution from Amal solution : xmpp.login(apiKey, accessToken, "Application");
to get access token first you have to login
fb.authorize(FacebookActivity.this, new String[] {"xmpp_login"},Facebook.FORCE_DIALOG_AUTH, new DialogListner());
SASLXFacebookPlatformMecha class
import java.io.IOException;
import java.net.URLEncoder;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
import org.apache.harmony.javax.security.sasl.Sasl;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.util.Base64;
public class SASLXFacebookPlatformMecha extends SASLMechanism {
private static final String NAME = "X-FACEBOOK-PLATFORM";
private String apiKey = "";
private String access_token = "";
/**
* Constructor.
*/
public SASLXFacebookPlatformMecha(SASLAuthentication saslAuthentication) {
super(saslAuthentication);
}
@Override
protected void authenticate() throws IOException, XMPPException {
getSASLAuthentication().send(new AuthMechanism(NAME, ""));
}
@Override
public void authenticate(String apiKey, String host, String acces_token)
throws IOException, XMPPException {
if (apiKey == null || acces_token == null) {
throw new IllegalArgumentException("Invalid parameters");
}
this.access_token = acces_token;
this.apiKey = apiKey;
this.hostname = host;
String[] mechanisms = { NAME };
Map<String, String> props = new HashMap<String, String>();
this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,
this);
authenticate();
}
@Override
public void authenticate(String username, String host, CallbackHandler cbh)
throws IOException, XMPPException {
String[] mechanisms = { NAME };
Map<String, String> props = new HashMap<String, String>();
this.sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props,
cbh);
authenticate();
}
@Override
protected String getName() {
return NAME;
}
@Override
public void challengeReceived(String challenge) throws IOException {
byte[] response = null;
if (challenge != null) {
String decodedChallenge = new String(Base64.decode(challenge));
Map<String, String> parameters = getQueryMap(decodedChallenge);
String version = "1.0";
String nonce = parameters.get("nonce");
String method = parameters.get("method");
long callId = new GregorianCalendar().getTimeInMillis();
String composedResponse = "api_key="
+ URLEncoder.encode(apiKey, "utf-8") + "&call_id=" + callId
+ "&method=" + URLEncoder.encode(method, "utf-8")
+ "&nonce=" + URLEncoder.encode(nonce, "utf-8")
+ "&access_token="
+ URLEncoder.encode(access_token, "utf-8") + "&v="
+ URLEncoder.encode(version, "utf-8");
response = composedResponse.getBytes("utf-8");
}
String authenticationText = "";
if (response != null) {
authenticationText = Base64.encodeBytes(response,
Base64.DONT_BREAK_LINES);
}
// Send the authentication to the server
getSASLAuthentication().send(new Response(authenticationText));
}
private Map<String, String> getQueryMap(String query) {
Map<String, String> map = new HashMap<String, String>();
String[] params = query.split("\\&");
for (String param : params) {
String[] fields = param.split("=", 2);
map.put(fields[0], (fields.length > 1 ? fields[1] : null));
}
return map;
}
}
I created ChatManager class
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterListener;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;
import org.jivesoftware.smackx.pubsub.PresenceState;
public class FacebookChatManager {
private static FacebookChatManager chatManager;
private XMPPConnection connection;
private final String SERVER = "chat.facebook.com";
private final int PORT = 5222;
private final String FACEBOOK_MECHANISM = "X-FACEBOOK-PLATFORM";
private RosterListener rosterListner;
private FacebookChatManager(RosterListener rosterListner)
{
this.rosterListner = rosterListner;
ConnectionConfiguration connFig = new ConnectionConfiguration(SERVER,
PORT);
connFig.setSASLAuthenticationEnabled(true);
connection = new XMPPConnection(connFig);
//setup facebook authentication mechanism
SASLAuthentication.registerSASLMechanism(FACEBOOK_MECHANISM,
SASLXFacebookPlatformMecha.class);
SASLAuthentication.supportSASLMechanism(FACEBOOK_MECHANISM, 0);
}
public static FacebookChatManager getInstance(RosterListener rosterListner)
{
if(chatManager == null)
{
chatManager = new FacebookChatManager(rosterListner);
}
return chatManager;
}
public boolean connect()
{
try {
connection.connect();
return true;
} catch (XMPPException e) {
e.printStackTrace();
connection.disconnect();
}
return false;
}
public void disConnect()
{
connection.disconnect();
}
public boolean logIn(String apiKey, String accessToken)
{
try {
connection.login(apiKey, accessToken);
setPresenceState(Presence.Type.available, "");
connection.getRoster().addRosterListener(rosterListner);
return true;
} catch (XMPPException e) {
connection.disconnect();
e.printStackTrace();
}
return false;
}
public Roster getRoster()
{
return connection.getRoster();
}
public Chat createNewChat(String user, MessageListener messageListner)
{
return connection.getChatManager().createChat(user, messageListner);
}
public void registerNewIncomingChatListner(ChatManagerListener chatManagerListner)
{
connection.getChatManager().addChatListener(chatManagerListner);
}
public void setPresenceState(Type precenseType, String status)
{
Presence presence = new Presence(precenseType);
presence.setStatus(status);
connection.sendPacket(presence);
}
public Presence getUserPresence(String userId)
{
return connection.getRoster().getPresence(userId);
}
}
at the end to use that FacebookChatManager class note that rosterListnr is used to get info about your friends state change implement one as you want
FacebookChatManager facebookChatManager = FacebookChatManager.getInstance(rosterListner);
if (facebookChatManager.connect()) {
if (facebookChatManager.logIn(FacebookActivity.APP_ID,
access_token)) {
return facebookChatManager.getRoster();
}
}
You need an access token.
http://developers.facebook.com/tools/access_token/
For more info
http://developers.facebook.com/docs/chat/
Connections must be made in AsyncTask for android 2.2 higher...
private class AsyncCallWS extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
Log.i(TAG, "doInBackground");
calculate();
return null;
}
@Override
protected void onPostExecute(Void result) {
Log.i(TAG, "onPostExecute");
}
@Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
@Override
protected void onProgressUpdate(Void... values) {
Log.i(TAG, "onProgressUpdate");
}
public void calculate()
{
Session s = Session.getActiveSession();
ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com", 5222);
config.setSASLAuthenticationEnabled(true);
XMPPConnection mFbConnection = new XMPPConnection(config);
SASLAuthentication.registerSASLMechanism("X-FACEBOOK-PLATFORM", SASLXFacebookPlatformMechanism.class);
SASLAuthentication.supportSASLMechanism("X-FACEBOOK-PLATFORM", 0);
try {
mFbConnection.connect();
Log.i("XMPPClient",
"Connected to " + mFbConnection.getHost());
mFbConnection.login("7028228197XXXXXX",s.getAccessToken(),"Application");
Roster roster = mFbConnection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
Log.i("XMPPClient","\n\n"+ entries.size() + " buddy(ies):");
// shows first time onliners---->
String temp[] = new String[50];
int i = 0;
for (RosterEntry entry : entries) {
String user = entry.getName();
Log.i("TAG", user);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Dont forget to add permissions.
private static final List<String> PERMISSIONS = Arrays.asList("xmpp_login");
if(checkPermissions())
{
AsyncCallWS task = new AsyncCallWS();
task.execute();
}
else
{
requestPermissions();
}
public boolean checkPermissions() {
Session s = Session.getActiveSession();
if (s!=null) {
return s.getPermissions().contains("xmpp_login");
}
else
return false;
}
public void requestPermissions() {
Session s = Session.getActiveSession();
if (s!=null)
s.requestNewReadPermissions(new Session.NewPermissionsRequest(this, PERMISSIONS));
}