3

我很难弄清楚发生了什么。我有一个典型的应用程序结构,它生成一个负责获取 twitter 令牌的 OAuthActivity,然后我的主要应用程序活动使用该令牌进行各种与 twitter 相关的操作。

我的 OAuthActivity 有效。我得到了一个身份验证令牌,Twitter 网页屏幕正确显示了我的应用程序名称等。此外,在该活动中,我可以发送一条推文并发布它。. 这意味着 OAuthActivity 工作,时钟同步令牌有效,等等......

但是,当这个 OAuthActivity 完成并返回到调用活动时,每当我尝试使用该令牌(从持久密钥/秘密重新创建它)时,无论如何,操作总是失败并显示 401,抱怨 AuthChallenge 报告为 null.. . 就像我提供了一个空令牌,但我没有

请在附件中找到我的 OAuthActivity 的来源,以及我如何在主要活动中初始化 Twitter 对象的来源。如果您发现有问题,请告诉我。

PD -我显然已经检查过我分配的令牌值是否与我得到的相同!还尝试了通过属性,通过构建器,通过集合来实例化 Twitter 的不同方法....并且没有任何变化:(

编辑-> 我发现如果我想重用一个令牌,我必须在新的 twitter 对象上调用“ verifyCredentials() ”,但是....没有运气!(请在最后找到发布的异常)

EDIT-2> 如果我在子活动和父活动上都使用

mTwitter=TwitterFactory.getSingleton()

然后 twitter 对象可以工作,但这对我来说并不是真的可以接受,因为它不使用持久性,而且我每次都需要授权应用程序。此外,只有 Twitter 对象被授权,TwitterStream 不断抛出异常。

干杯!

父活动的源代码,我尝试使用在子活动中获得的访问令牌,如下所示。无论我试图用这个令牌做什么总是得到 401。

private void init_twitter(String tok, String sec) {

    ConfigurationBuilder cb = new ConfigurationBuilder();

    cb.setDebugEnabled(true)
      .setOAuthConsumerKey(Conf.OAUTH_CONSUMER_KEY)
      .setOAuthConsumerSecret(Conf.OAUTH_CONSUMER_SECRET)
      .setOAuthAccessToken(tok)
      .setOAuthAccessTokenSecret(sec);

    TwitterFactory tf = new TwitterFactory(cb.build());

    mTwitter=tf.getInstance();



    /** This always fails, even though I call this routine with the 
                correct token & secret !!! See at the enf of message for an alternate 
                routine like this one that makes use of verifyCredentials and
                also fails. */ 

    new Thread(new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            try {
                mTwitter.updateStatus("yello 2");
            } catch (TwitterException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }}).start();


}

子 OAuthActivity 的源代码,当我获得访问令牌并能够发推文时,它显然可以工作:

import a lot;

public class TwitterLogin extends Activity {

    private final String TAG = "TwitterLogin";
    public final static String PREF_KEY_OAUTH_TOKEN="twitter.oauth.token", PREF_KEY_OAUTH_SECRET="twitter.oauth.secret", PREF_KEY_TWITTER_LOGIN="twitter.oauth.login";

    private SharedPreferences mPreferences;

    private Twitter twitter = new TwitterFactory().getInstance();


    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "Starting task to retrieve request token.");
        this.mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        super.onCreate(savedInstanceState);
        getActionBar().setTitle("TWITTER AUTHENTICATION");


    }

    private void returnParent(boolean result)  {
        setResult(result?Activity.RESULT_OK:Activity.RESULT_CANCELED, null);
        if (Conf.LOG_ON) Log.d(TAG, "TWITTER AUTH: END PROCESS , GLOBAL RESULT "+result);

        /** THE FOLLOWING THING WORKS !!!!! IT SUCCESSFULLY TWEETS */

        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    twitter.updateStatus("yello");
                } catch (TwitterException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }}).start();



        finish();
    }

    /**
     * Uses TWITTER4J to get the Request URL. It gets something like 
     * AUTH URL TWITTER4J IS http://api.twitter.com/oauth/authorize?oauth_token=xxxxxxxxxxxxxxxxxxxxx
     *
     * @return The Request URL to open in webview and get the Verifier
     */

    private String oauth_twitter4j_getRequestUrl() throws TwitterException {
        twitter.setOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
        RequestToken tempToken = twitter.getOAuthRequestToken(Constants.OAUTH_CALLBACK_URL);
        return tempToken.getAuthorizationURL();
    }


    @Override
    protected void onResume() {
        super.onResume();
        WebView webview = new WebView(this);
        webview.getSettings().setJavaScriptEnabled(true);  
        webview.setVisibility(View.VISIBLE);
        setContentView(webview);

        Log.i(TAG, "Retrieving request token from Google servers");

        try {

            StrictMode.ThreadPolicy policy = new StrictMode. ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);

            String authorizationUrl=oauth_twitter4j_getRequestUrl();
            Log.d(TAG, "AUTH URL TWITTER4J IS "+authorizationUrl_t);

            webview.setWebViewClient(new WebViewClient() {  

                @Override
                public boolean shouldOverrideUrlLoading(WebView webView, String url) { 
                    if (Conf.LOG_ON) Log.d(TAG,"WebView: "+url);
                    if (url != null && url.startsWith(Constants.OAUTH_CALLBACK_URL)) try {
                        System.out.println("TWEET TWEET TWEET");
                        retrieveAccessToken(url); //added this
                        webView.setVisibility(View.GONE); //added this
                        return true;            
                    } catch (Exception e) {
                        e.printStackTrace();
                        returnParent(false);
                        return true;
                    } else return false;
                }

                private void saveAccessToken(AccessToken accessToken) {

                    // Shared Preferences
                    Editor e = mPreferences.edit();

                    // After getting access token, access token secret
                    // store them in application preferences

                    e.putString(PREF_KEY_OAUTH_TOKEN, accessToken.getToken());
                    e.putString(PREF_KEY_OAUTH_SECRET,accessToken.getTokenSecret());
                    e.putBoolean(PREF_KEY_TWITTER_LOGIN, true);
                    e.commit(); 

                    Log.e("Twitter OAuth Token", "> " + accessToken.getToken()+"-"+accessToken.getScreenName());

                }

                private void retrieveAccessToken(String url) throws Exception {
                    String requestToken  = extractParamFromUrl(url,"oauth_token");
                    String verifier= extractParamFromUrl(url,"oauth_verifier");
                    if (Conf.LOG_ON) Log.d(TAG, "Tenemos ACCESS TOKEN y VERIFIER :"+requestToken+","+verifier+","+(new Date().toString()));

                    if (ONLY_TWITTER4J)
                        retrieveAccessToken_with4j(verifier);
                    else
                        retrieveAccessToken_signpost(verifier);
                }

                private void retrieveAccessToken_with4j(String verifier) throws TwitterException {
                    AccessToken a=twitter.getOAuthAccessToken(verifier);
                    saveAccessToken(a);
                    returnParent(true);
                }

                private String extractParamFromUrl(String url,String paramName) {
                    String queryString = url.substring(url.indexOf("?", 0)+1,url.length());
                    QueryStringParser queryStringParser = new QueryStringParser(queryString);
                    return queryStringParser.getQueryParamValue(paramName);
                }  

            });  

            webview.loadUrl(authorizationUrl);  
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}

使用我确定是正确的令牌调用 VerifyCredentials 时出现异常:

    Received authentication challenge is null
    W/System.err(24915): Relevant discussions can be found on the Internet at:
    W/System.err(24915):    http://www.google.co.jp/search?q=6f0f59ca or
    W/System.err(24915):    http://www.google.co.jp/search?q=20d0f74e
    W/System.err(24915): TwitterException{exceptionCode=[6f0f59ca-20d0f74e 1de2170b-f94dee38], statusCode=-1, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=3.0.3}
    W/System.err(24915):    at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:192)
    W/System.err(24915):    at twitter4j.internal.http.HttpClientWrapper.request(HttpClientWrapper.java:61)
    W/System.err(24915):    at twitter4j.internal.http.HttpClientWrapper.get(HttpClientWrapper.java:89)
    W/System.err(24915):    at twitter4j.TwitterBaseImpl.fillInIDAndScreenName(TwitterBaseImpl.java:126)
    W/System.err(24915):    at twitter4j.TwitterImpl.verifyCredentials(TwitterImpl.java:592)
    W/System.err(24915):    at com.regaliz.helpers.TwitterManager$2.run(TwitterManager.java:140)
    W/System.err(24915):    at java.lang.Thread.run(Thread.java:856)
    W/System.err(24915): Caused by: java.io.IOException: Received authentication challenge is null
    W/System.err(24915):    at libcore.net.http.HttpURLConnectionImpl.processAuthHeader(HttpURLConnectionImpl.java:397)
    W/System.err(24915):    at libcore.net.http.HttpURLConnectionImpl.processResponseHeaders(HttpURLConnectionImpl.java:345)
    W/System.err(24915):    at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:276)
    W/System.err(24915):    at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:479)
    W/System.err(24915):    at twitter4j.internal.http.HttpResponseImpl.<init>(HttpResponseImpl.java:34)
    W/System.err(24915):    at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:156)
    W/System.err(24915):    ... 6 more

这是修改为使用 verifyCredentials 的函数:

    private void init_twitter_2(final String tok, final String sec) throws TwitterException {

            ConfigurationBuilder cb = new ConfigurationBuilder();

            cb.setDebugEnabled(true)
              .setOAuthConsumerKey(Conf.OAUTH_CONSUMER_KEY)
              .setOAuthConsumerSecret(Conf.OAUTH_CONSUMER_SECRET);
    //        .setOAuthAccessToken(tok)
    //        .setOAuthAccessTokenSecret(sec);

            TwitterFactory tf = new TwitterFactory(cb.build());

            mTwitter=tf.getInstance();
            Log.d(TAG, "init_twitter_2 "+tok+","+sec);
            new Thread(new Runnable(){

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    User u;
                    try {
                        /** also tried setting token&secret like this, instead of in the builder-->no success */
                        mTwitter.setOAuthAccessToken(new AccessToken(tok,sec));
                        u = mTwitter.verifyCredentials();
                        Log.d(TAG, "User: "+u.getName());

                    } catch (TwitterException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }}).start();


        }
4

1 回答 1

5

有愚蠢的人,愚蠢的人,愚蠢的人,然后是我。一个星期以来,我一直在为代码苦苦挣扎,跟踪 Twitter4j,使用 curl 复制 oauth,怀疑垃圾收集活动,跟踪 DDMS,计算令牌的哈希值......只是发现我有 2 个 Conf.OAUTH_CONSUMER_xxxxx 实例不同的价值观。

由于这些东西来自常量,而且名称相似,我没有意识到这一点。

叹息——50 声望点落马桶!

于 2013-05-28T01:52:54.140 回答