3

在我的 Android 应用程序中,我有一个EditText、一个Button和一个Listview。当我在我的EditText字段中输入电影名称并按下 时Button,我希望ListViewRotten Tomatoes 网站上的电影名称与我在EditText字段中输入的内容相匹配。

但我不知道如何使用烂番茄 JSON API来获取电影数据。我该怎么做?

4

2 回答 2

15

基本上,你需要做四件事:

  1. 为您的 Android 应用程序获取一个烂番茄 API 密钥,您可以在此处进行操作。此密钥将您的应用程序识别到他们的服务并授予您授权的访问权限。每次向他们的 API 发出请求时都必须使用它。就是这样,没什么复杂的。
  2. 向其 API 的 Web 服务器发出HTTP请求。请求的 URL 将取决于您尝试获取的数据。例如,要获取电影列表,URL 是:http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=[your_api_key]&q=[search_keyword]&page_limit=[page_limit],如本页所示。
  3. 从他们的网络服务器读取响应。如我刚刚链接的最后一页所示,响应将是一个JSON对象,因为这是 Rotten Tomatoes 选择用于其 API 的数据格式。
  4. 从 JSON 对象中获取您想要的任何值(例如电影标题)并相应地更新您的应用程序的 UI。

我已经组装了一个小型演示应用程序来执行此操作。请尝试以下代码。

MainActivity.java

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class MainActivity extends Activity
{
    // the Rotten Tomatoes API key of your application! get this from their website
    private static final String API_KEY = <your api key!>; 

    // the number of movies you want to get in a single request to their web server
    private static final int MOVIE_PAGE_LIMIT = 10; 

    private EditText searchBox;
    private Button searchButton;
    private ListView moviesList;

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

        searchBox = (EditText) findViewById(R.id.text_search_box);
        searchButton = (Button) findViewById(R.id.button_search);
        searchButton.setOnClickListener(new OnClickListener()
        {
            // send an API request when the button is pressed
            @Override
            public void onClick(View arg0)
            {
                new RequestTask().execute("http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=" + API_KEY + "&q=" + searchBox.getText().toString().trim() + "&page_limit=" + MOVIE_PAGE_LIMIT);
            }
        });
        moviesList = (ListView) findViewById(R.id.list_movies);
    }

    private void refreshMoviesList(String[] movieTitles)
    {
        moviesList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, movieTitles));
    }

    private class RequestTask extends AsyncTask<String, String, String>
    {
        // make a request to the specified url
        @Override
        protected String doInBackground(String... uri)
        {
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response;
            String responseString = null;
            try
            {
                // make a HTTP request
                response = httpclient.execute(new HttpGet(uri[0]));
                StatusLine statusLine = response.getStatusLine();
                if (statusLine.getStatusCode() == HttpStatus.SC_OK)
                {
                    // request successful - read the response and close the connection
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    response.getEntity().writeTo(out);
                    out.close();
                    responseString = out.toString();
                }
                else
                {
                    // request failed - close the connection
                    response.getEntity().getContent().close();
                    throw new IOException(statusLine.getReasonPhrase());
                }
            }
            catch (Exception e)
            {
                Log.d("Test", "Couldn't make a successful request!");
            }
            return responseString;
        }

        // if the request above completed successfully, this method will 
        // automatically run so you can do something with the response
        @Override
        protected void onPostExecute(String response)
        {
            super.onPostExecute(response);

            if (response != null)
            {
                try
                {
                    // convert the String response to a JSON object,
                    // because JSON is the response format Rotten Tomatoes uses
                    JSONObject jsonResponse = new JSONObject(response);

                    // fetch the array of movies in the response
                    JSONArray movies = jsonResponse.getJSONArray("movies");

                    // add each movie's title to an array
                    String[] movieTitles = new String[movies.length()];
                    for (int i = 0; i < movies.length(); i++)
                    {
                        JSONObject movie = movies.getJSONObject(i);
                        movieTitles[i] = movie.getString("title");
                    }

                    // update the UI
                    refreshMoviesList(movieTitles);
                }
                catch (JSONException e)
                {
                    Log.d("Test", "Failed to parse the JSON response!");
                }
            }
        }
    }
}

资源/布局/activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#E9E9E9"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:orientation="horizontal"
        android:padding="3dip" >

        <EditText
            android:id="@+id/text_search_box"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1.0"
            android:gravity="center" />

        <Button
            android:id="@+id/button_search"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableRight="@android:drawable/ic_search_category_default" />
    </LinearLayout>

    <ListView
        android:id="@+id/list_movies"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1.0" />

</LinearLayout>

并将这一行添加到您的AndroidManifest.xml(它授予您的 Android 应用程序使用 Internet 的权限,您显然需要向 Rotten Tomatoes 的网络服务器发出请求):

<uses-permission android:name="android.permission.INTERNET" />

奖励答案:

如果您在 EditText 字段中键入搜索关键字时想要“实时”搜索结果,请通过 EditText 的addTextChangedListener()方法添加一个 TextWatcher,并使其在onTextChanged().

于 2013-01-05T15:53:40.123 回答
0

解决此类问题的典型方法是:

创建一个AsyncTask处理请求和响应的网络和解析,因为在主(或 UI)线程中长时间运行的操作是一个坏主意。在 AsyncTask 中,您使用 HttpClient 与 API 服务器通信,并使用 JSON 解析器库(例如Google 的 gson)解析 JSON 请求/响应。

你可以找到很多关于如何使用 HttpClient 与远程服务器通信的教程,这里是其中之一(我不能保证它的质量):

http://www.mysamplecode.com/2011/09/android-asynctask-httpclient-with.html

于 2013-01-05T14:44:01.097 回答