集成的方式有两种,主要在于获取用户信息的方式不同。
一、准备工作
1.在项目级build.gradle文件中配置fabric
buildscript {
repositories {
google()
jcenter()
mavenCentral()
maven {
url 'https://maven.fabric.io/public'
}
}
dependencies {
...
classpath 'io.fabric.tools:gradle:1.+'
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
maven {
url 'https://jitpack.io'
}
...
}
}
- 在app级build.gradle文件中配置
apply plugin: 'io.fabric'
...
repositories {
mavenCentral()
maven {
url 'https://maven.fabric.io/public'
}
}
...
implementation('com.twitter.sdk.android:twitter-core:3.1.1@aar') {
transitive = true
}
implementation('com.twitter.sdk.android:tweet-composer:3.1.1@aar') {
transitive = true
}
implementation('com.twitter.sdk.android:tweet-ui:3.1.1@aar') {
transitive = true
}
implementation('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') {
transitive = true
}
...
apply plugin: 'com.google.gms.google-services'
- 在清单文件中配置fabric key,
-
在twitter平台注册自己的app,获取twitter 的key和secret
二、授权访问用户信息
在我们要调用的位置,初始化twitter配置信息
TwitterConfig config = new TwitterConfig.Builder(this)
.logger(new DefaultLogger(Log.DEBUG))
.twitterAuthConfig(new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET))
.debug(BuildConfig.DEBUG)
.build();
Twitter.initialize(config);
一种是不用twitter的btn控件按钮,访问用户信息用url
private void twitterLogin() {
loginTwitter(LoginActivity.this, new LoginCallback() {
@Override
public void onSuccess(User user, String email, String twitterSecret, String twitterToken) {
String imageProfileUrl = user.profileImageUrl;
String userName = user.name;
String profileUrl = imageProfileUrl.replace("_normal", "");
LogTracer.INSTANCE.print(TAG, "loginTwitter onSuccess");
}
@Override
public void onFailure(Exception e) {
LogTracer.INSTANCE.print(TAG, "twitter login failed:" + e.getMessage());
ToastUtils.INSTANCE.showLongToast(LoginActivity.this, R.string.toast_common_failed);
}
});
}
private TwitterAuthClient mTwitterAuthClient;
public interface LoginCallback {
void onSuccess(User user, String email, String twitterSecret, String twitterToken);
void onFailure(Exception e);
}
public void loginTwitter(Activity activity, final LoginCallback callback) {
if (mTwitterAuthClient == null) {
mTwitterAuthClient = new TwitterAuthClient();
}
mTwitterAuthClient.authorize(activity, new Callback() {
@Override
public void success(Result result) {
String name = result.data.getUserName();
long userId = result.data.getUserId();
LogTracer.INSTANCE.print(TAG, "loginTwitter name =" + name + ", userId=" + userId);
getTwitterUserEmail(userId, callback);
}
@Override
public void failure(TwitterException e) {
LogTracer.INSTANCE.print(TAG, "loginTwitter failure e=" + e.getMessage());
callback.onFailure(e);
}
});
}
private void getTwitterUserEmail(final long userId, final LoginCallback callback) {
final TwitterSession activeSession = TwitterCore.getInstance().getSessionManager().getActiveSession();
mTwitterAuthClient.requestEmail(activeSession, new Callback() {
@Override
public void success(Result result) {
String email = result.data;
LogTracer.INSTANCE.print(TAG, "getTwitterUserEmail email::" + email);
getTwitterUserInfo(userId, email, callback);
}
@Override
public void failure(TwitterException e) {
getTwitterUserInfo(userId, "", callback);
LogTracer.INSTANCE.print(TAG, "getTwitterUserEmail failure::" + e.getMessage());
}
});
}
private void getTwitterUserInfo(final long userId, final String email, final LoginCallback callback) {
final TwitterSession activeSession = TwitterCore.getInstance().getSessionManager().getActiveSession();
final String twitterSecret = activeSession.getAuthToken().secret;
final String twitterToken = activeSession.getAuthToken().token;
MyTwitterApiClient client = new MyTwitterApiClient(activeSession);
client.getCustomService().show(userId).enqueue(new Callback() {
@Override
public void success(Result result) {
User data = result.data;
callback.onSuccess(data, email, twitterSecret, twitterToken);
}
@Override
public void failure(TwitterException e) {
e.printStackTrace();
callback.onFailure(e);
}
});
}
static class MyTwitterApiClient extends TwitterApiClient {
public MyTwitterApiClient(TwitterSession session) {
super(session);
}
/**
* Provide CustomService with defined endpoints
*/
public CustomService getCustomService() {
return getService(CustomService.class);
}
// example users/show service endpoint
interface CustomService {
@GET("/1.1/users/show.json")
Call show(@Query("user_id") long id);
}
}
另一种是用twitter loginBtn控件
xml中添加下面代码:
在页面使用下面的方式:
初始化控件
mTwitterLoginButton = findViewById(R.id.twitter_button);
twitterLogin();
回调监听
private void twitterLogin() {
mTwitterLoginButton.setCallback(new Callback() {
@Override
public void success(Result result) {
LogTracer.INSTANCE.print(TAG, "twitter login success");
TwitterSession session = result.data;
final String twitterID = session.getAuthToken().secret;
final String twitterToken = session.getAuthToken().token;
getTwitterUserPhoto(twitterID, twitterToken);
}
@Override
public void failure(TwitterException e) {
LogTracer.INSTANCE.print(TAG, "twitter login failed:" + e.getMessage());
ToastUtils.INSTANCE.showLongToast(LoginActivity.this, R.string.toast_common_failed);
}
});
}
private void getTwitterUserPhoto(final String twitterID,final String twitterToken) {
final TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient();
Call call = twitterApiClient.getAccountService().verifyCredentials(true, false, true);
call.enqueue(new Callback() {
@Override
public void success(Result result) {
User user = result.data;
String imageProfileUrl = user.profileImageUrl;
String email = user.email;
String userName = user.name;
String profileUrl = imageProfileUrl.replace("_normal", "");
}
@Override
public void failure(TwitterException e) {
LogTracer.INSTANCE.print(TAG, "twitter getTwitterUserPhoto failed:" + e.getMessage());
ToastUtils.INSTANCE.showLongToast(LoginActivity.this, R.string.toast_common_failed);
}
});
}
在onActivityResult方法中添加此代码
mTwitterLoginButton.onActivityResult(requestCode, resultCode, data);
三、twitter挖坑填坑系列
- 当登录按钮成功回调,但是下一步请求用户头像出问题401时,参考这位博主的帖子https://blog.csdn.net/xu20082100226/article/details/79315830,救命了。
- 当手机端没有安装twitter客户端时,
预期:显示Twitter登录网页以输入用户名和密码,然后继续。
实际:未显示任何页面。
在Android app中点击twitter登录按钮,返回错误信息为
08-06 13:56:09.317 6499-6499/? E/Twitter: Invalid json: Callback URL not approved for this client application. Approved callback URLs can be adjusted in your application settings
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
at com.twitter.sdk.android.core.models.SafeListAdapter$1.read(SafeListAdapter.java:45)
at com.twitter.sdk.android.core.models.SafeMapAdapter$1.read(SafeMapAdapter.java:45)
at com.google.gson.Gson.fromJson(Gson.java:888)
at com.google.gson.Gson.fromJson(Gson.java:853)
at com.google.gson.Gson.fromJson(Gson.java:802)
at com.google.gson.Gson.fromJson(Gson.java:774)
at com.twitter.sdk.android.core.TwitterApiException.parseApiError(TwitterApiException.java:110)
at com.twitter.sdk.android.core.TwitterApiException.readApiError(TwitterApiException.java:95)
at com.twitter.sdk.android.core.TwitterApiException.(TwitterApiException.java:43)
at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:213)
at com.twitter.sdk.android.core.models.SafeListAdapter$1.read(SafeListAdapter.java:45)
at com.twitter.sdk.android.core.models.SafeMapAdapter$1.read(SafeMapAdapter.java:45)
at com.google.gson.Gson.fromJson(Gson.java:888)
at com.google.gson.Gson.fromJson(Gson.java:853)
at com.google.gson.Gson.fromJson(Gson.java:802)
at com.google.gson.Gson.fromJson(Gson.java:774)
at com.twitter.sdk.android.core.TwitterApiException.parseApiError(TwitterApiException.java:110)
at com.twitter.sdk.android.core.TwitterApiException.readApiError(TwitterApiException.java:95)
at com.twitter.sdk.android.core.TwitterApiException.(TwitterApiException.java:43)
at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Failed to get request token
com.twitter.sdk.android.core.TwitterApiException: HTTP request failed, Status: 403
at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
08-06 13:56:09.347 6499-6499/? D/Twitter: onActivityResult called with 140 1
08-06 13:56:09.348 6499-6499/? E/Twitter: Authorization completed with an error
com.twitter.sdk.android.core.TwitterAuthException: Failed to get request token
at com.twitter.sdk.android.core.identity.OAuthController$1.failure(OAuthController.java:94)
at com.twitter.sdk.android.core.internal.oauth.OAuth1aService$1.failure(OAuth1aService.java:191)
at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
在Android设备上,我们收到此错误“无法获取请求令牌”。我们发现请求https://api.twitter.com/oauth/request_token收到403错误。
我们的iOS应用程序也是如此,错误日志“未批准此客户端应用程序的回调URL。可以在您的应用程序设置中调整已批准的回调URL”。
这是因为twitter api 的这种变化。
要解决此问题,您可以在https://apps.twitter.com上的应用控制台中指定以下回调网址
网址方案 | 码 | |
---|---|---|
适用于Android的TwitterKit | twittersdk:// |
OAuth1aService.java#L59 |
适用于iOS的TwitterKit | twitterkit-YOUR_CONSUMER_KEY:// |
TWTRLoginURLParser.m#L39 |