Vijay,
Mã của bạn đã giúp tôi rất nhiều! Tôi đăng bài ở đây để cung cấp giải pháp cho vấn đề sử dụng AccountManager để đăng nhập vào Google talk. Cho đến nay tôi đã không tìm thấy một giải pháp đầy đủ trên mạng, nhưng tôi đã phát triển mỏ dựa trên mã trên và sửa một vài dòng không hoạt động.
Có hai phần của giải pháp. Việc đầu tiên được dựa trên ý tưởng và mã trên. Đó là tạo một lớp con của 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();
}
}
}
Phần thứ hai là việc sử dụng nó. Điều quan trọng mà không có ví dụ nào khác cho tôi là khi nhận được mã thông báo từ hệ thống AccountManager, loại mã thông báo không phải là "ah" nhưng "thư". Ý tưởng được đưa ra ở đó trong các ví dụ thực hiện giao tiếp trực tiếp với các máy chủ của Google để nhận mã thông báo nhưng không yêu cầu nó từ Trình quản lý tài khoản. Đặt chúng lại với nhau cho rằng bạn cần phải làm như sau trong mã trình điều khiển của bạn. Tạo một chức năng để có mã thông báo:
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;
}
Và sau đó gọi nó là sau khi đảm bảo các hệ thống SASL đúng sẽ được sử dụng:
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
}
Chúc mừng Google Talking!
Tôi đã xem xét điều này trước đây, nhưng chưa bao giờ thực sự thử nó. Bạn có nhớ đăng mã của bạn để tôi có thể cố gắng làm điều đó bản thân mình và có lẽ tôi sẽ tìm một giải pháp. Cảm ơn – Guillaume