Vijay,
Il codice mi ha aiutato molto, grazie! Sto postando qui per offrire la mia soluzione al problema dell'utilizzo di AccountManager per accedere a Google Talk. Finora non ho trovato una soluzione completa, ma ho sviluppato la mia basata sul codice precedente e correggendo alcune righe che non funzionano.
Ci sono due parti per la soluzione. Il primo è basato sull'idea e sul codice di cui sopra. Si tratta di creare una sottoclasse di SASLMechanism:
import java.io.IOException;
import java.net.URLEncoder;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.sasl.SASLMechanism;
import android.util.Base64;
import android.util.Log;
public class GTalkOAuth2 extends SASLMechanism {
public static final String NAME="X-GOOGLE-TOKEN";
public GTalkOAuth2(SASLAuthentication saslAuthentication) {
super(saslAuthentication);
}
@Override
protected String getName() {
return NAME;
}
static void enable() { }
@Override
protected void authenticate() throws IOException, XMPPException
{
String authCode = password;
String jidAndToken = "\0" + URLEncoder.encode(authenticationId, "utf-8") + "\0" + authCode;
StringBuilder stanza = new StringBuilder();
stanza.append("<auth mechanism=\"").append(getName());
stanza.append("\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
stanza.append(new String(Base64.encode(jidAndToken.getBytes("UTF-8"), Base64.DEFAULT)));
stanza.append("</auth>");
Log.v("BlueTalk", "Authentication text is "+stanza);
// Send the authentication to the server
getSASLAuthentication().send(new Auth2Mechanism(stanza.toString()));
}
public class Auth2Mechanism extends Packet {
String stanza;
public Auth2Mechanism(String txt) {
stanza = txt;
}
public String toXML() {
return stanza;
}
}
/**
* Initiating SASL authentication by select a mechanism.
*/
public class AuthMechanism extends Packet {
final private String name;
final private String authenticationText;
public AuthMechanism(String name, String authenticationText) {
if (name == null) {
throw new NullPointerException("SASL mechanism name shouldn't be null.");
}
this.name = name;
this.authenticationText = authenticationText;
}
public String toXML() {
StringBuilder stanza = new StringBuilder();
stanza.append("<auth mechanism=\"").append(name);
stanza.append("\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
if (authenticationText != null &&
authenticationText.trim().length() > 0) {
stanza.append(authenticationText);
}
stanza.append("</auth>");
return stanza.toString();
}
}
}
La seconda parte è l'uso di esso. La cosa importante che nessun altro esempio mi ha dato è che quando si ottiene il token dal sistema AccountManager, il tipo di token non è "ah" ma "mail". L'idea era là fuori in alcuni esempi facendo una comunicazione diretta con i server di google per ottenere il token ma non per richiederlo da AccountManager. Metterli insieme ti dà la necessità di fare quanto segue nel codice del driver. Creare una funzione per ottenere il token:
public String getAuthToken(String name)
{
Context context = getApplicationContext();
Activity activity = this;
String retVal = "";
Account account = new Account(name, "com.google");
AccountManagerFuture<Bundle> accFut = AccountManager.get(context).getAuthToken(account, "mail", null, activity, null, null);
try
{
Bundle authTokenBundle = accFut.getResult();
retVal = authTokenBundle.get(AccountManager.KEY_AUTHTOKEN).toString();
}
catch (OperationCanceledException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (AuthenticatorException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return retVal;
}
E poi chiamarlo dopo essersi assicurati verrà utilizzato il sistema di SASL destra:
SASLAuthentication.registerSASLMechanism(GTalkOAuth2.NAME, GTalkOAuth2.class);
SASLAuthentication.supportSASLMechanism(GTalkOAuth2.NAME, 0);
config.setSASLAuthenticationEnabled(true);
String saslAuthString = getAuthToken(acct.name);
connection = new XMPPConnection(config);
try {
connection.connect();
connection.login(name, saslAuthString);
} catch (XMPPException e) {
// Most likely an expired token
// Invalidate the token and start over. There are example of this available
}
Felice Google Parlare!
L'ho già visto, ma non l'ho mai provato. Ti dispiacerebbe postare il tuo codice in modo che io possa provare a farlo da solo e forse troverò una soluzione. Grazie – Guillaume