8

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");

Community
  • 1
  • 1
RajaReddy PolamReddy
  • 22,428
  • 19
  • 115
  • 166
  • In some answers The access token looks like this "something|sessionKey|somethingElse", but my access token looks like this--AAABeS1oNtyABANFNGJRZBLn5G1SKzj3jKlSi36F2iagYi0lhwvnt0ZAHtSxbWWZB8Ehq3CY3x5JxNz5wKSAlj5xagXAm4qxPJkOh3KMTEy1HeVmNZC1l. why both are different.. – RajaReddy PolamReddy Jun 25 '12 at 09:31
  • Is it facebook sdk change the access token format.. – RajaReddy PolamReddy Jun 25 '12 at 10:39
  • Can you please give me a link to download the jar to import XMPP,Sasl and ConnectionConfiguration in my android project to implement FB chat. – Arun PS Jan 31 '13 at 06:45
  • @Arun look at this list of asmack lib's available here, https://code.google.com/p/asmack/downloads/list in this i am using asmack-2010.05.07. it will be useful for Gmail and Facebook. – RajaReddy PolamReddy Jan 31 '13 at 06:54
  • Will we be able to import Sasl from this ? – Arun PS Jan 31 '13 at 07:00
  • @RajaReddyPolamReddy have you got the solution for this problem,i got server not connect error keystore jsks implemention not found,how to resolve that one – Karthick M Mar 28 '14 at 08:57

3 Answers3

14

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();
            }
        }
Amal
  • 971
  • 9
  • 25
  • Hi, thanks for your response i am able to get that access_token, still i'm getting the error not connected to server error. – RajaReddy PolamReddy Jun 27 '12 at 11:27
  • @RajaReddyP can you tell me where this error arise as with the code I posted I have no errors at all you have to connect before login to xmpp as I did in the last code fragment – Amal Jun 27 '12 at 13:32
  • i will check it once again clearly, may be i did the wrong. let you know after checking. – RajaReddy PolamReddy Jun 27 '12 at 13:39
  • @RajaReddyP: You can apply [this](http://stackoverflow.com/a/11242390/1472665) steps to resolve "server not connected error". – Dipali Jul 01 '12 at 15:22
  • When i try to use the last section of code i get an error because the `rosterListner` was never declared. where and how do i declare it? – Peter Oct 31 '12 at 15:33
  • @Peter org.jivesoftware.smack.RosterListener is interface you need to implement and then declare and use as it provide callback methods like presenceChanged. – Amal Nov 05 '12 at 11:03
  • @Amal I'll give that a try.. Do you have an example of that I could look at? – Peter Nov 05 '12 at 15:32
  • I'm trying to get this solution working with the facebook 3.0 sdk and its not working, anyone have any luck or solutions? – Peter Jan 26 '13 at 22:14
  • @Amal i am unable to find "org.apache.harmony.javax.security.sasl.Sasl" class on Android. Actually there seems neither "org.apache.harmony" package, nor "javax.security.sasl" package exist. Also i found CallbackHandler at "javax.security.auth.callback.CallbackHandler". Is there a jar or native implementation for it? – Gökhan Barış Aker Jan 28 '13 at 08:46
  • 1
    @GökhanBarışAker I'm using asmack-issue15.jar and it has those classes in with the other imported classes. it's Android version of smack library – Amal Jan 30 '13 at 12:48
  • Can you please give me a link to download the jar to import XMPP,Sasl and ConnectionConfiguration in my android project to implement FB chat. – Arun PS Jan 31 '13 at 06:46
  • 1
    @Arun http://code.google.com/p/asmack/downloads/detail?name=asmack-issue15.jar&can=2&q= – Gökhan Barış Aker Jan 31 '13 at 10:31
  • Hi...This was a very good post...I was able to login and logout to Facebook chat using this code. Can any one tell me how to sent and receive messages using this code. – Arun PS Jan 31 '13 at 11:21
  • @Amal Describe the first line of answer where we need to use the code,i am having big issue with this one,i asked question toohttp://stackoverflow.com/questions/22660397/how-to-connect-facebook-chat-using-xmpp-i-want-to-enter-username-of-friends-and – Karthick M Mar 27 '14 at 13:11
  • Where we need to provide api key an access token? – Karthick M Mar 27 '14 at 13:11
6

You need an access token. http://developers.facebook.com/tools/access_token/

For more info http://developers.facebook.com/docs/chat/

Alex Wiese
  • 8,142
  • 6
  • 42
  • 71
  • is this tools as token was different from normal token? why i'm asking is i worked on fb sdk in previous app i got a big token here is shows smaller than that. and how can i get this token by dynamic bez. it will expires. – RajaReddy PolamReddy Jun 15 '12 at 06:08
  • 2
    @RajaReddy P tokens you get from here is for testing but you should use the tokens you get normally from sdk at the end. to use APIKey and accessToken please look at my answer http://stackoverflow.com/questions/5317329/xmpp-with-java-asmack-library-supporting-x-facebook-platform/11099138#11099138 – Amal Jun 19 '12 at 10:37
  • @alexw can you explain me it clearly ...i am able to get access_token from android sdk. for login it requires apiKey, sessionKey, sionSecret how can i get those values .. – RajaReddy PolamReddy Jun 25 '12 at 13:59
  • Can you please give me a link to download the jar to import XMPP,Sasl and ConnectionConfiguration in my android project to implement FB chat. – Arun PS Jan 31 '13 at 06:47
0

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));
}
chanda
  • 53
  • 1
  • 9