Android twitter登錄集成

集成的方式有兩種,主要在于獲取用戶信息的方式不同。

一、準(zhǔn)備工作

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'
        }
       ...
    }
}
  1. 在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'
  1. 在清單文件中配置fabric key,
  <meta-data
            android:name="io.fabric.ApiKey"
            android:value="Your key str"
            />
  1. 在twitter平臺注冊自己的app,獲取twitter 的key和secret


二、授權(quán)訪問用戶信息

在我們要調(diào)用的位置,初始化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<TwitterSession>() {
            @Override
            public void success(Result<TwitterSession> 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<String>() {

            @Override
            public void success(Result<String> 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<User>() {
            @Override
            public void success(Result<User> 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<User> show(@Query("user_id") long id);
        }
    }

另一種是用twitter loginBtn控件
xml中添加下面代碼:


            <com.twitter.sdk.android.core.identity.TwitterLoginButton
                android:id="@+id/twitter_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:layout_gravity="center"
                android:visibility="gone"
                android:clickable="true" />

在頁面使用下面的方式:
初始化控件

 mTwitterLoginButton = findViewById(R.id.twitter_button);
        twitterLogin();

回調(diào)監(jiān)聽

    
    private void twitterLogin() {
        mTwitterLoginButton.setCallback(new Callback<TwitterSession>() {

            @Override
            public void success(Result<TwitterSession> 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<User> call = twitterApiClient.getAccountService().verifyCredentials(true, false, true);
        call.enqueue(new Callback<User>() {
            @Override
            public void success(Result<User> 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挖坑填坑系列

  1. 當(dāng)?shù)卿洶粹o成功回調(diào),但是下一步請求用戶頭像出問題401時,參考這位博主的帖子https://blog.csdn.net/xu20082100226/article/details/79315830,救命了。
  2. 當(dāng)手機(jī)端沒有安裝twitter客戶端時,
    預(yù)期:顯示Twitter登錄網(wǎng)頁以輸入用戶名和密碼,然后繼續(xù)。
    實際:未顯示任何頁面。
    在Android app中點擊twitter登錄按鈕,返回錯誤信息為
08-06 13:56:09.317 6499-6499/? E/Twitter: Invalid json: <?xml version="1.0" encoding="UTF-8"?><errors><error code="415">Callback URL not approved for this client application. Approved callback URLs can be adjusted in your application settings</error></errors>
    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.<init>(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.<init>(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設(shè)備上,我們收到此錯誤“無法獲取請求令牌”。我們發(fā)現(xiàn)請求https://api.twitter.com/oauth/request_token收到403錯誤。
我們的iOS應(yīng)用程序也是如此,錯誤日志“未批準(zhǔn)此客戶端應(yīng)用程序的回調(diào)URL??梢栽谀膽?yīng)用程序設(shè)置中調(diào)整已批準(zhǔn)的回調(diào)URL”。
這是因為twitter api 的這種變化

要解決此問題,您可以在https://apps.twitter.com上的應(yīng)用控制臺中指定以下回調(diào)網(wǎng)址
網(wǎng)址方案
適用于Android的TwitterKit twittersdk:// OAuth1aService.java#L59
適用于iOS的TwitterKit twitterkit-YOUR_CONSUMER_KEY:// TWTRLoginURLParser.m#L39
000000000.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,139評論 25 708
  • 中醫(yī)的經(jīng)絡(luò)理論認(rèn)為,五臟六腑自脾、肝、腎始,踝部以下有66個穴位。用熱水泡腳如同用艾條灸這些穴位一樣,有推動血運(yùn)、...
    靈動衣櫥管理閱讀 531評論 0 0
  • 淅瀝瀝的下著小雨,風(fēng)吹過來讓人發(fā)抖,春天的天氣冷暖不定,明明前幾天暖的都能穿單件,今天卻又得穿上厚厚的羽絨衣。南方...
    時光不知道閱讀 129評論 0 1
  • 荷花(Lotus flower):屬毛茛目睡蓮科,是蓮屬二種植物的通稱。又名蓮花、水芙蓉等。是蓮屬多年生水生草本花...
    微茉輕揚(yáng)閱讀 377評論 1 1

友情鏈接更多精彩內(nèi)容