How to request movie data from Rotten Tomatoes usi

2019-05-12 19:14发布

问题:

In my Android application I have one EditText, one Button, and one Listview. When I type a movie name into my EditText field and press on the Button, I want the ListView to be populated with movie names from the Rotten Tomatoes website that match what I entered into the EditText field.

But I can't figure out how to use the Rotten Tomatoes JSON API to get the movie data. How do I do it?

回答1:

Basically, you need to do four things:

  1. Get a Rotten Tomatoes API key for your Android application, which you can do here. This key identifies your app to their service and gives you authorized access. You must use it every time you make a request to their API. That's all, nothing complicated.
  2. Make a HTTP request to their API's web server. The URL of the request will depend on what data you're trying to fetch. For example, to get a list of movies the URL is: http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=[your_api_key]&q=[search_keyword]&page_limit=[page_limit], as shown on this page.
  3. Read the response from their web server. As shown on the last page I just linked, the response will be a JSON object, because that's the data format Rotten Tomatoes' chose to use for their API.
  4. Get whatever values from the JSON object that you want (e.g. movie title) and update your app's UI accordingly.

I've put together a small demo app that will do this. Please try out the code below.

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!");
                }
            }
        }
    }
}

res/layouts/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>

And add this line to your AndroidManifest.xml (it gives your Android app permission to use the Internet, which you obviously need to make the request to Rotten Tomatoes' web server):

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

Bonus answer:

If you want "live" search results as you type the search keyword into the EditText field, add a TextWatcher via EditText's addTextChangedListener() method, and make it do the HTTP request in onTextChanged().



回答2:

A typical approach to this kind of problem would be:

Create an AsyncTask that handles the networking and parsing of your request and the response, since long running operations in the main (or UI) thread is a bad idea. In the AsyncTask you communicate to the API server using a HttpClient and parse the JSON request/response using a JSON parser library, such as Google's gson.

You can find plenty of tutorials on how to communicate with remote servers using the HttpClient, here is one of them (I can't vouch for it's quality):

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