@Override
 protected JSONObject doInBackground(String... args) {
   try {
     // These return a JSON result which describes if and where the query was found. This API may
     // break or disappear at any time in the future. Since this is an API call rather than a
     // website, we don't use LocaleManager to change the TLD.
     String theQuery = args[0];
     String theIsbn = args[1];
     String uri;
     if (LocaleManager.isBookSearchUrl(theIsbn)) {
       int equals = theIsbn.indexOf('=');
       String volumeId = theIsbn.substring(equals + 1);
       uri =
           "http://www.google.com/books?id="
               + volumeId
               + "&jscmd=SearchWithinVolume2&q="
               + theQuery;
     } else {
       uri =
           "http://www.google.com/books?vid=isbn"
               + theIsbn
               + "&jscmd=SearchWithinVolume2&q="
               + theQuery;
     }
     CharSequence content = HttpHelper.downloadViaHttp(uri, HttpHelper.ContentType.JSON);
     return new JSONObject(content.toString());
   } catch (IOException ioe) {
     Log.w(TAG, "Error accessing book search", ioe);
     return null;
   } catch (JSONException je) {
     Log.w(TAG, "Error accessing book search", je);
     return null;
   }
 }
  @Override
  void retrieveSupplementalInfo() throws IOException {

    CharSequence contents =
        HttpHelper.downloadViaHttp(
            "https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbn,
            HttpHelper.ContentType.JSON);

    if (contents.length() == 0) {
      return;
    }

    String title;
    String pages;
    Collection<String> authors = null;

    try {

      JSONObject topLevel = (JSONObject) new JSONTokener(contents.toString()).nextValue();
      JSONArray items = topLevel.optJSONArray("items");
      if (items == null || items.isNull(0)) {
        return;
      }

      JSONObject volumeInfo = ((JSONObject) items.get(0)).getJSONObject("volumeInfo");
      if (volumeInfo == null) {
        return;
      }

      title = volumeInfo.optString("title");
      pages = volumeInfo.optString("pageCount");

      JSONArray authorsArray = volumeInfo.optJSONArray("authors");
      if (authorsArray != null && !authorsArray.isNull(0)) {
        authors = new ArrayList<String>(authorsArray.length());
        for (int i = 0; i < authorsArray.length(); i++) {
          authors.add(authorsArray.getString(i));
        }
      }

    } catch (JSONException e) {
      throw new IOException(e.toString());
    }

    Collection<String> newTexts = new ArrayList<String>();
    maybeAddText(title, newTexts);
    maybeAddTextSeries(authors, newTexts);
    maybeAddText(pages == null || pages.length() == 0 ? null : pages + "pp.", newTexts);

    String baseBookUri =
        "http://www.google."
            + LocaleManager.getBookSearchCountryTLD(context)
            + "/search?tbm=bks&source=zxing&q=";

    append(isbn, source, newTexts.toArray(new String[newTexts.size()]), baseBookUri + isbn);
  }
 @Override
 void retrieveSupplementalInfo() throws IOException {
   URI oldURI;
   try {
     oldURI = new URI(result.getURI());
   } catch (URISyntaxException e) {
     return;
   }
   URI newURI = HttpHelper.unredirect(oldURI);
   int count = 0;
   while (count++ < MAX_REDIRECTS && !oldURI.equals(newURI)) {
     append(
         result.getDisplayResult(),
         null,
         new String[] {redirectString + " : " + newURI},
         newURI.toString());
     oldURI = newURI;
     newURI = HttpHelper.unredirect(newURI);
   }
 }
  @Override
  void retrieveSupplementalInfo() throws IOException, InterruptedException {

    String encodedProductID = URLEncoder.encode(productID, "UTF-8");
    String uri = BASE_PRODUCT_URI + encodedProductID;
    String content = HttpHelper.downloadViaHttp(uri, HttpHelper.ContentType.HTML);

    Matcher matcher = PRODUCT_NAME_PRICE_PATTERN.matcher(content);
    if (matcher.find()) {
      append(
          productID,
          source,
          new String[] {unescapeHTML(matcher.group(1)), unescapeHTML(matcher.group(2))},
          uri);
    }
  }
  @Override
  void retrieveSupplementalInfo() throws IOException {

    String encodedProductID = URLEncoder.encode(productID, "UTF-8");
    String uri =
        "http://www.google."
            + LocaleManager.getProductSearchCountryTLD(context)
            + "/m/products?ie=utf8&oe=utf8&scoring=p&source=zxing&q="
            + encodedProductID;
    CharSequence content = HttpHelper.downloadViaHttp(uri, HttpHelper.ContentType.HTML);

    for (Pattern p : PRODUCT_NAME_PRICE_PATTERNS) {
      Matcher matcher = p.matcher(content);
      if (matcher.find()) {
        append(
            productID,
            source,
            new String[] {unescapeHTML(matcher.group(1)), unescapeHTML(matcher.group(2))},
            uri);
        break;
      }
    }
  }
  @Override
  void retrieveSupplementalInfo() throws IOException {

    CharSequence contents =
        HttpHelper.downloadViaHttp(
            "https://bsplus.srowen.com/ss?c=" + country + "&t=" + type + "&i=" + productID,
            HttpHelper.ContentType.XML);

    String detailPageURL = null;
    Collection<String> authors = new ArrayList<String>();
    String title = null;
    String formattedNewPrice = null;
    String formattedUsedPrice = null;
    boolean error = false;

    try {
      XmlPullParser xpp = buildParser(contents);

      boolean seenItem = false;
      boolean seenLowestNewPrice = false;
      boolean seenLowestUsedPrice = false;

      for (int eventType = xpp.getEventType();
          eventType != XmlPullParser.END_DOCUMENT;
          eventType = xpp.next()) {
        if (eventType == XmlPullParser.START_TAG) {
          String name = xpp.getName();
          if ("Item".equals(name)) {
            if (seenItem) {
              break;
            } else {
              seenItem = true;
            }
          } else if ("DetailPageURL".equals(name)) {
            assertTextNext(xpp);
            detailPageURL = xpp.getText();
          } else if ("Author".equals(name)) {
            assertTextNext(xpp);
            authors.add(xpp.getText());
          } else if ("Title".equals(name)) {
            assertTextNext(xpp);
            title = xpp.getText();
          } else if ("LowestNewPrice".equals(name)) {
            seenLowestNewPrice = true;
            seenLowestUsedPrice = false;
          } else if ("LowestUsedPrice".equals(name)) {
            seenLowestNewPrice = false;
            seenLowestUsedPrice = true;
          } else if ("FormattedPrice".equals(name)) {
            if (seenLowestNewPrice || seenLowestUsedPrice) {
              assertTextNext(xpp);
              String theText = xpp.getText();
              if (seenLowestNewPrice) {
                formattedNewPrice = theText;
              } else {
                formattedUsedPrice = theText;
              }
              seenLowestNewPrice = false;
              seenLowestUsedPrice = false;
            }
          } else if ("Errors".equals(name)) {
            error = true;
            break;
          }
        }
      }

    } catch (XmlPullParserException xppe) {
      throw new IOException(xppe.toString());
    }

    if (error || detailPageURL == null) {
      return;
    }

    Collection<String> newTexts = new ArrayList<String>();
    maybeAddText(title, newTexts);
    maybeAddTextSeries(authors, newTexts);
    if (formattedNewPrice != null) {
      maybeAddText(formattedNewPrice, newTexts);
    } else if (formattedUsedPrice != null) {
      maybeAddText(formattedUsedPrice, newTexts);
    }

    append(productID, "Amazon", newTexts.toArray(new String[newTexts.size()]), detailPageURL);
  }