我如何获得搜索结果?解析错误

时间:2017-01-07 19:43:07

标签: android api search onclicklistener

我收到了解析错误。请帮忙!如果有人知道Google Books API会很棒。如果你能解释我的错误在哪里;这会非常有帮助。谢谢。

E/QueryUtils: Problem parsing the library JSON results
          org.json.JSONException: No value for items
              at org.json.JSONObject.get(JSONObject.java:389)
              at org.json.JSONObject.getJSONObject(JSONObject.java:609)
              at com.example.android.booklisting.QueryUtils.extractFeatureFromJson(QueryUtils.java:172)
              at com.example.android.booklisting.QueryUtils.fetchLibraryData(QueryUtils.java:57)
              at com.example.android.booklisting.LibraryLoader.loadInBackground(LibraryLoader.java:50)
              at com.example.android.booklisting.LibraryLoader.loadInBackground(LibraryLoader.java:16)
              at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:312)
              at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:69)
              at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:57)
              at android.os.AsyncTask$2.call(AsyncTask.java:295)
              at java.util.concurrent.FutureTask.run(FutureTask.java:237)
              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
              at java.lang.Thread.run(Thread.java:818)

SearchActivity类

package com.example.android.booklisting;

import android.app.LoaderManager;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;


public class SearchActivity extends AppCompatActivity
    implements LoaderManager.LoaderCallbacks<List<Library>> {

Button search;
EditText find;

private static final String LOG_TAG = SearchActivity.class.getName();

/**
 * URL for Library data from the Google Books dataset
 */
 private static String BOOKS_REQUEST_URL =
        "https://www.googleapis.com/books/v1/volumes?q=";

/**
 * Constant value for the earthquake loader ID. We can choose any integer.
 * This really only comes into play if you're using multiple loaders.
 */
private static final int LIBRARY_LOADER_ID = 1;

private LibraryAdapter mAdapter;
private TextView mEmptyStateTextView;

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

    search = (Button) findViewById(R.id.search_button);
    search.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            BOOKS_REQUEST_URL =BOOKS_REQUEST_URL+ find.getText().toString();
            getLoaderManager().restartLoader();
        }

    });

    find = (EditText) findViewById(R.id.search_text);}
    });


    // Find a reference to the {@link ListView} in the layout
    ListView libraryListView = (ListView) findViewById(R.id.list);

    mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
    libraryListView.setEmptyView(mEmptyStateTextView);

    // Create a new adapter that takes an empty list of earthquakes as input
    mAdapter = new LibraryAdapter(this, new ArrayList<Library>());

    // Set the adapter on the {@link ListView}
    // so the list can be populated in the user interface
    libraryListView.setAdapter(mAdapter);


    // Set an item click listener on the ListView, which sends an intent to a web browser
    // to open a website with more information about the selected library.
    libraryListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            // Find the current book that was clicked on
            Library currentLibrary = mAdapter.getItem(position);
            // Convert the String URL into a URI object (to pass into the Intent constructor)
            Uri libraryUri = Uri.parse(currentLibrary.getUrl());
            // Create a new intent to view the book URI
            Intent websiteIntent = new Intent(Intent.ACTION_VIEW, libraryUri);
            // Send the intent to launch a new activity
            startActivity(websiteIntent);
        }
    });

    // Get a reference to the ConnectivityManager to check state of network connectivity
    ConnectivityManager connMgr = (ConnectivityManager)
            getSystemService(Context.CONNECTIVITY_SERVICE);

    // Get details on the currently active default data network
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

    // If there is a network connection, fetch data
    if (networkInfo != null && networkInfo.isConnected()) {
        // Get a reference to the LoaderManager, in order to interact with loaders.
        LoaderManager loaderManager = getLoaderManager();

        // Initialize the loader. Pass in the int ID constant defined above and pass in null for
        // the bundle. Pass in this activity for the LoaderCallbacks parameter (which is valid
        // because this activity implements the LoaderCallbacks interface).
        loaderManager.initLoader(LIBRARY_LOADER_ID, null, this);
    } else {
        // Otherwise, display error
        // First, hide loading indicator so error message will be visible
        View loadingIndicator = findViewById(R.id.loading_indicator);
        loadingIndicator.setVisibility(View.GONE);

        // Update empty state with no connection error message
        mEmptyStateTextView.setText(R.string.no_internet_connection);
    }
}

@Override
public Loader<List<Library>> onCreateLoader(int i, Bundle bundle) {
    // Create a new loader for the given URL
    return new LibraryLoader(this, BOOKS_REQUEST_URL);
}

@Override
public void onLoadFinished(Loader<List<Library>> loader, List<Library> libraries) {
    // Hide loading indicator because the data has been loaded
    View loadingIndicator = findViewById(R.id.loading_indicator);
    loadingIndicator.setVisibility(View.GONE);

    // Set empty state text to display "No books found."
    mEmptyStateTextView.setText(R.string.no_libraries);

    // Clear the adapter of previous library data
    mAdapter.clear();

    // If there is a valid list of {@link Library}s, then add them to the adapter's
    // data set. This will trigger the ListView to update.
    if (libraries != null && !libraries.isEmpty()) {
        mAdapter.addAll(libraries);
    }
}

@Override
public void onLoaderReset(Loader<List<Library>> loader) {
    // Loader reset, so we can clear out our existing data.
    mAdapter.clear();
}

}

QueryUtils类:

import android.text.TextUtils;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * Helper methods related to requesting and receiving library data from      Google Books.
 */
public class QueryUtils {
/** Tag for the log messages */
private static final String LOG_TAG = QueryUtils.class.getSimpleName();

/**
 * Create a private constructor because no one should ever create a {@link QueryUtils} object.
 * This class is only meant to hold static variables and methods, which can be accessed
 * directly from the class name QueryUtils (and an object instance of QueryUtils is not needed).
 */
private QueryUtils() {
}

/**
 * Query the USGS dataset and return a list of {@link Library} objects.
 */
public static List<Library> fetchLibraryData(String requestUrl) {
    // Create URL object
    URL url = createUrl(requestUrl);

    // Perform HTTP request to the URL and receive a JSON response back
    String jsonResponse = null;
    try {
        jsonResponse = makeHttpRequest(url);
    } catch (IOException e) {
        Log.e(LOG_TAG, "Problem making the HTTP request.", e);
    }

    // Extract relevant fields from the JSON response and create a list of {@link Library}s
    List<Library> libraries = extractFeatureFromJson(jsonResponse);

    // Return the list of {@link Earthquake}s
    return libraries;
}

/**
 * Returns new URL object from the given string URL.
 */
private static URL createUrl(String stringUrl) {
    URL url = null;
    try {
        url = new URL(stringUrl);
    } catch (MalformedURLException e) {
        Log.e(LOG_TAG, "Problem building the URL ", e);
    }
    return url;
}

/**
 * Make an HTTP request to the given URL and return a String as the response.
 */
private static String makeHttpRequest(URL url) throws IOException {
    String jsonResponse = "";

    // If the URL is null, then return early.
    if (url == null) {
        return jsonResponse;
    }

    HttpURLConnection urlConnection = null;
    InputStream inputStream = null;
    try {
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setReadTimeout(10000 /* milliseconds */);
        urlConnection.setConnectTimeout(15000 /* milliseconds */);
        urlConnection.setRequestMethod("GET");
        urlConnection.connect();

        // If the request was successful (response code 200),
        // then read the input stream and parse the response.
        if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            inputStream = urlConnection.getInputStream();
            jsonResponse = readFromStream(inputStream);
        } else {
            Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
        }
    } catch (IOException e) {
        Log.e(LOG_TAG, "Problem retrieving the earthquake JSON results.", e);
    } finally {
        if (urlConnection != null) {
            urlConnection.disconnect();
        }
        if (inputStream != null) {
            // Closing the input stream could throw an IOException, which is why
            // the makeHttpRequest(URL url) method signature specifies than an IOException
            // could be thrown.
            inputStream.close();
        }
    }
    return jsonResponse;
}

/**
 * Convert the {@link InputStream} into a String which contains the
 * whole JSON response from the server.
 */
private static String readFromStream(InputStream inputStream) throws IOException {
    StringBuilder output = new StringBuilder();
    if (inputStream != null) {
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
        BufferedReader reader = new BufferedReader(inputStreamReader);
        String line = reader.readLine();
        while (line != null) {
            output.append(line);
            line = reader.readLine();
        }
    }
    return output.toString();
}

/**
 * Return a list of {@link Library} objects that has been built up from
 * parsing the given JSON response.
 */
private static List<Library> extractFeatureFromJson(String libraryJSON) {
    // If the JSON string is empty or null, then return early.
    if (TextUtils.isEmpty(libraryJSON)) {
        return null;
    }

    // Create an empty ArrayList that we can start adding earthquakes to
    List<Library> libraries = new ArrayList<>();

    // Try to parse the JSON response string. If there's a problem with the way the JSON
    // is formatted, a JSONException exception object will be thrown.
    // Catch the exception so the app doesn't crash, and print the error message to the logs.
    try {

        // Create a JSONObject from the JSON response string
        JSONObject baseJsonResponse = new JSONObject(libraryJSON);

        // Extract the JSONArray associated with the key called "features",
        // which represents a list of features (or libraries).
        JSONArray libraryArray = baseJsonResponse.getJSONArray("items");

        // For each book in the earthquakeArray, create an {@link Library} object
        for (int i = 0; i < libraryArray.length(); i++) {

            // Get a single book at position i within the list of books
            JSONObject currentLibrary = libraryArray.getJSONObject(i);

            // For a given book, extract the JSONObject associated with the
            // key called "properties", which represents a list of all properties
            // for that book.
            JSONObject query = currentLibrary.getJSONObject("q");

            // Extract the value for the key called "intitle"
            String title = query.getString("intitle");

            // Extract the value for the key called "inauthor"
            String author = query.getString("inauthor");

            String url = query.getString("info_url");

            // Create a new {@link Library} object with the title, author,
            // and url from the JSON response.
            Library library = new Library(title, author, url);

            // Add the new {@link Library} to the list of libraries.
            libraries.add(library);
        }

    } catch (JSONException e) {
        // If an error is thrown when executing any of the above statements in the "try" block,
        // catch the exception here, so the app doesn't crash. Print a log message
        // with the message from the exception.
        Log.e("QueryUtils", "Problem parsing the library JSON results", e);
    }

    // Return the list of books
    return libraries;
}

1 个答案:

答案 0 :(得分:0)

  

我是否还需要在EditText上设置OnClickListener?

不,只需在点击按钮时从EditText获取输入数据,然后在发出新请求之前将其添加到Google Books API

1。从EditText获取输入文本并将其添加到BOOKS_REQUEST_URL

BOOKS_REQUEST_URL=BOOKS_REQUEST_URL+ find.getText().toString();

注意:BOOKS_REQUEST_URL删除最终版并将网址更改为:

  BOOKS_REQUEST_URL =
        "https://www.googleapis.com/books/v1/volumes?q=";

2。最后在onCreateLoader方法中调用触发器onClick

    @Override
    public void onClick(View view) {
      BOOKS_REQUEST_URL=BOOKS_REQUEST_URL+ find.getText().toString();
      getLoaderManager().initLoader(0, null, SearchActivity.this);
    }