0

純粋なJavaアプリケーションを実行するとTwitterの読み取りが機能し、Android Javaプログラムから呼び出すと機能しない理由がわかりません。誰かが私を助けてくれることを願っています。twitter の 1.1 API のアプリケーション認証方式を使用しています。

Javaを実行するときに次のコードを使用していますが、これは機能しています:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;

import javax.net.ssl.HttpsURLConnection;

import org.apache.commons.codec.binary.Base64;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;



public class testSomething {

    private final static String getTokenURL = "https://api.twitter.com/oauth2/token";
    private static String bearerToken;

    public static final String CONSUMER_KEY = "<key>";
    public static final String CONSUMER_SECRET= "<secret>";

    /**
     * @param args
     */
    public static void main(String[] args) {

        // encodeKeys(APIKEY, APISECRET);

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {

                    bearerToken = requestBearerToken(getTokenURL);

                    System.out.println("Search = " + "https://api.twitter.com/1.1/search/tweets.json?q=%23PhuseKatja&count=20");
                    System.out.println("Bearer = " + bearerToken);

                    ArrayList<Tweet> tweets = fetchSearchTweet("https://api.twitter.com/1.1/search/tweets.json?q=%23PhuseKatja&count=20",
                                                               bearerToken);

                    System.out.println(tweets.size());

                } catch (IOException e) {
                    System.out.println("IOException e");
                    e.printStackTrace();
                }
            }
        }).start();

    }

    // Encodes the consumer key and secret to create the basic authorization key
    private static String encodeKeys(String consumerKey, String consumerSecret) {
        try {
            String encodedConsumerKey = URLEncoder.encode(consumerKey, "UTF-8");
            String encodedConsumerSecret = URLEncoder.encode(consumerSecret,
                    "UTF-8");

            String fullKey = encodedConsumerKey + ":" + encodedConsumerSecret;
            byte[] encodedBytes = Base64.encodeBase64(fullKey.getBytes());

            return new String(encodedBytes);
        } catch (UnsupportedEncodingException e) {
            return new String();
        }
    }

    // Constructs the request for requesting a bearer token and returns that
    // token as a string
    public static String requestBearerToken(String endPointUrl)
            throws IOException {
        HttpsURLConnection connection = null;
        String encodedCredentials = encodeKeys(CONSUMER_KEY, CONSUMER_SECRET);

        System.out.println("encodedCredentials "+encodedCredentials);
        try {
            URL url = new URL(endPointUrl);
            connection = (HttpsURLConnection) url.openConnection();
            System.out.println(connection);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Host", "api.twitter.com");
            connection.setRequestProperty("User-Agent", "Android Phuse Application");
            connection.setRequestProperty("Authorization", "Basic " + encodedCredentials);
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
            connection.setRequestProperty("Content-Length", "29");
            connection.setUseCaches(false);

            writeRequest(connection, "grant_type=client_credentials");

            // Parse the JSON response into a JSON mapped object to fetch fields
            // from.
            JSONObject obj = (JSONObject) JSONValue.parse(readResponse(connection));

            if (obj != null) {
                String tokenType = (String) obj.get("token_type");
                String token = (String) obj.get("access_token");

                return ((tokenType.equals("bearer")) && (token != null)) ? token
                        : "";
            }
            return new String();
        } catch (MalformedURLException e) {
            throw new IOException("Invalid endpoint URL specified.", e);
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }


    // Fetches the first tweet from a given user's timeline
        public static ArrayList<Tweet> fetchSearchTweet(String endPointUrl, String aBearerToken)
                throws IOException {
            HttpsURLConnection connection = null;

            ArrayList<Tweet> tweets = new ArrayList<Tweet>();

            try {
                URL url = new URL(endPointUrl);
                connection = (HttpsURLConnection) url.openConnection();
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setRequestMethod("GET");
                connection.setRequestProperty("Host", "api.twitter.com");
                connection.setRequestProperty("User-Agent", "anyApplication");
                connection.setRequestProperty("Authorization", "Bearer " +  aBearerToken);
                connection.setUseCaches(false);

                String response = readResponse(connection);

                System.out.println("Response = " + response);
                System.out.println(connection.getResponseMessage());
                System.out.println(connection.getResponseCode());
                System.out.println("---------------------------------");

                // Parse the JSON response into a JSON mapped object to fetch fields from.
                JSONObject objSearch = (JSONObject) JSONValue.parse(response);
                JSONArray ja = (JSONArray) objSearch.get("statuses");

                if (ja != null) {
                    for (int i = 0; i < ja.size(); i++)
                    {
                        Tweet tweet = new Tweet((((JSONObject)((JSONObject) ja.get(i)).get("user")).get("screen_name").toString()), 
                                                ((JSONObject) ja.get(i)).get("text").toString(), 
                                                (((JSONObject)((JSONObject) ja.get(i)).get("user")).get("profile_image_url").toString()));
                        tweets.add(tweet);
                    }
                }
                return tweets;
            } catch (MalformedURLException e) {
                throw new IOException("Invalid endpoint URL specified.", e);
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
            }
        }

    // Writes a request to a connection
    private static boolean writeRequest(HttpURLConnection connection,
            String textBody) {
        try {
            BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(
                    connection.getOutputStream()));
            wr.write(textBody);
            wr.flush();
            wr.close();

            return true;
        } catch (IOException e) {
            return false;
        }
    }

    // Reads a response for a given connection and returns it as a string.
    private static String readResponse(HttpURLConnection connection) {
        try {
            StringBuilder str = new StringBuilder();

            BufferedReader br = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line = "";
            while ((line = br.readLine()) != null) {
                str.append(line + System.getProperty("line.separator"));
            }
            return str.toString();
        } catch (IOException e) {
            return new String();
        }
    }

    public static class Tweet {
        public String username;
        public String message;
        public String image_url;
        //public Bitmap image_bitmap;

        public Tweet(String username, String message, String url) {
            this.username  = username;
            this.message   = message;
            this.image_url = url;

            //this.image_bitmap = getBitmap(url);
        }
    }
}

Android Javaアプリケーション(最終的にこれが必要な場所)を作成すると、同じコードを呼び出すことができますが、機能しません。fetchSearchTweet リクエストに対して 400 の「Bad response」コードが表示されます。bearerToken は期待どおりに受信され、トークンと検索文字列を出力すると、すべて同じです。

Androidの場合、完全な新しいプロジェクトを作成し、インターネット接続をアクティブにし、同じtestSomethingクラスをコピーして実行しようとしました. しかし、残念ながらこれは機能しません (Twitter の応答 400)。私は見当もつかない。

import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


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

        try {
            String bearerToken = testSomething.requestBearerToken("https://api.twitter.com/oauth2/token");
            testSomething.fetchSearchTweet("https://api.twitter.com/1.1/search/tweets.json?q=%23PhuseKatja&count=20", bearerToken);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

ブログの例と便利な質問リソースを使用しました。


これが Android-Java で機能しない理由は、ピュア Java と Android Java で異なる「HttpsURLConnection」クラス内にあります。新しい Twitter API が Android が提供する HttpsURLConnection をサポートしていないのか、それとも Android からの HttpsURLConnection が必要な形式に準拠していないのかはわかりません。

私は現在、アプリケーション認証モードもサポートするTwitter4Jのスナップショット バージョンを使用しています。

4

2 に答える 2

2

URLEncoder.encode後で Base64 に変換されるため、キーを使用することは想定されていません。単に

return Base64.encodeToString((consumerKey + ":" + consumerSecret).getBytes(),
                    Base64.NO_WRAP);

あなたのencodeKeys方法で。(私はこの正確な方法を使用していますが、問題はありません。)

于 2013-07-19T07:57:55.650 に答える