mirror of
https://github.com/zxing/zxing.git
synced 2024-11-10 13:04:05 -08:00
Merge from "Barcode Scanner Plus": avoid deprecated AndroidHttpClient and use java.net for networking; better HTTP headers, better redirect handling
git-svn-id: https://zxing.googlecode.com/svn/trunk@1958 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
3bd4e1e903
commit
d2ed7976ef
|
@ -1,170 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.zxing.client.android;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpRequestInterceptor;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.ResponseHandler;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.client.params.HttpClientParams;
|
||||
import org.apache.http.client.protocol.ClientContext;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.conn.scheme.PlainSocketFactory;
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
import org.apache.http.conn.scheme.SchemeRegistry;
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
|
||||
import org.apache.http.params.BasicHttpParams;
|
||||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
import org.apache.http.params.HttpProtocolParams;
|
||||
import org.apache.http.protocol.BasicHttpContext;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* <p>Subclass of the Apache {@link DefaultHttpClient} that is configured with
|
||||
* reasonable default settings and registered schemes for Android, and
|
||||
* also lets the user add {@link HttpRequestInterceptor} classes.
|
||||
* Don't create this directly, use the {@link #newInstance} factory method.</p>
|
||||
* <p/>
|
||||
* <p>This client processes cookies but does not retain them by default.
|
||||
* To retain cookies, simply add a cookie store to the HttpContext:
|
||||
* <pre>context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);</pre>
|
||||
* </p>
|
||||
*/
|
||||
public final class AndroidHttpClient implements HttpClient {
|
||||
|
||||
/**
|
||||
* Create a new HttpClient with reasonable defaults (which you can update).
|
||||
*
|
||||
* @param userAgent to report in your HTTP requests.
|
||||
* @return AndroidHttpClient for you to use for all your requests.
|
||||
*/
|
||||
public static AndroidHttpClient newInstance(String userAgent) {
|
||||
HttpParams params = new BasicHttpParams();
|
||||
|
||||
// Turn off stale checking. Our connections break all the time anyway,
|
||||
// and it's not worth it to pay the penalty of checking every time.
|
||||
HttpConnectionParams.setStaleCheckingEnabled(params, false);
|
||||
|
||||
// Default connection and socket timeout of 20 seconds. Tweak to taste.
|
||||
HttpConnectionParams.setConnectionTimeout(params, 20 * 1000);
|
||||
HttpConnectionParams.setSoTimeout(params, 20 * 1000);
|
||||
HttpConnectionParams.setSocketBufferSize(params, 8192);
|
||||
|
||||
// Don't handle redirects -- return them to the caller. Our code
|
||||
// often wants to re-POST after a redirect, which we must do ourselves.
|
||||
HttpClientParams.setRedirecting(params, false);
|
||||
|
||||
// Set the specified user agent and register standard protocols.
|
||||
if (userAgent != null) {
|
||||
HttpProtocolParams.setUserAgent(params, userAgent);
|
||||
}
|
||||
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
||||
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
|
||||
schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
|
||||
ClientConnectionManager manager = new ThreadSafeClientConnManager(params, schemeRegistry);
|
||||
|
||||
// We use a factory method to modify superclass initialization
|
||||
// parameters without the funny call-a-static-method dance.
|
||||
return new AndroidHttpClient(manager, params);
|
||||
}
|
||||
|
||||
private final HttpClient delegate;
|
||||
|
||||
|
||||
private AndroidHttpClient(ClientConnectionManager ccm, HttpParams params) {
|
||||
this.delegate = new DelegateHttpClient(ccm, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release resources associated with this client. You must call this,
|
||||
* or significant resources (sockets and memory) may be leaked.
|
||||
*/
|
||||
public void close() {
|
||||
getConnectionManager().shutdown();
|
||||
}
|
||||
|
||||
public HttpParams getParams() {
|
||||
return delegate.getParams();
|
||||
}
|
||||
|
||||
public ClientConnectionManager getConnectionManager() {
|
||||
return delegate.getConnectionManager();
|
||||
}
|
||||
|
||||
public HttpResponse execute(HttpUriRequest request) throws IOException {
|
||||
return delegate.execute(request);
|
||||
}
|
||||
|
||||
public HttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException {
|
||||
return delegate.execute(request, context);
|
||||
}
|
||||
|
||||
public HttpResponse execute(HttpHost target, HttpRequest request) throws IOException {
|
||||
return delegate.execute(target, request);
|
||||
}
|
||||
|
||||
public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException {
|
||||
return delegate.execute(target, request, context);
|
||||
}
|
||||
|
||||
public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler) throws IOException {
|
||||
return delegate.execute(request, responseHandler);
|
||||
}
|
||||
|
||||
public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
|
||||
throws IOException {
|
||||
return delegate.execute(request, responseHandler, context);
|
||||
}
|
||||
|
||||
public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler)
|
||||
throws IOException {
|
||||
return delegate.execute(target, request, responseHandler);
|
||||
}
|
||||
|
||||
public <T> T execute(HttpHost target, HttpRequest request,
|
||||
ResponseHandler<? extends T> responseHandler,
|
||||
HttpContext context) throws IOException {
|
||||
return delegate.execute(target, request, responseHandler, context);
|
||||
}
|
||||
|
||||
private static class DelegateHttpClient extends DefaultHttpClient {
|
||||
|
||||
private DelegateHttpClient(ClientConnectionManager ccm, HttpParams params) {
|
||||
super(ccm, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpContext createHttpContext() {
|
||||
// Same as DefaultHttpClient.createHttpContext() minus the
|
||||
// cookie store.
|
||||
HttpContext context = new BasicHttpContext();
|
||||
context.setAttribute(ClientContext.AUTHSCHEME_REGISTRY, getAuthSchemes());
|
||||
context.setAttribute(ClientContext.COOKIESPEC_REGISTRY, getCookieSpecs());
|
||||
context.setAttribute(ClientContext.CREDS_PROVIDER, getCredentialsProvider());
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
168
android/src/com/google/zxing/client/android/HttpHelper.java
Normal file
168
android/src/com/google/zxing/client/android/HttpHelper.java
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright 2011 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.zxing.client.android;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* Utility methods for retrieving content over HTTP using the more-supported {@code java.net} classes
|
||||
* in Android.
|
||||
*/
|
||||
public final class HttpHelper {
|
||||
|
||||
private static final Collection<String> REDIRECTOR_DOMAINS = new HashSet<String>(Arrays.asList(
|
||||
"amzn.to", "bit.ly", "bitly.com", "fb.me", "goo.gl", "is.gd", "j.mp", "lnkd.in", "ow.ly",
|
||||
"SCN.BY", "su.pr", "t.co", "tinyurl.com", "tr.im"
|
||||
));
|
||||
|
||||
private HttpHelper() {
|
||||
}
|
||||
|
||||
public enum ContentType {
|
||||
/** HTML-like content type, including HTML, XHTML, etc. */
|
||||
HTML,
|
||||
/** JSON content */
|
||||
JSON,
|
||||
/** Plain text content */
|
||||
TEXT,
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uri URI to retrieve
|
||||
* @param type expected text-like MIME type of that content
|
||||
* @return content as a {@code String}
|
||||
* @throws IOException if the content can't be retrieved because of a bad URI, network problem, etc.
|
||||
*/
|
||||
public static String downloadViaHttp(String uri, ContentType type) throws IOException {
|
||||
String contentTypes;
|
||||
switch (type) {
|
||||
case HTML:
|
||||
contentTypes = "application/xhtml+xml,text/html,text/*,*/*";
|
||||
break;
|
||||
case JSON:
|
||||
contentTypes = "application/json,text/*,*/*";
|
||||
break;
|
||||
case TEXT:
|
||||
default:
|
||||
contentTypes = "text/*,*/*";
|
||||
}
|
||||
return downloadViaHttp(uri, contentTypes);
|
||||
}
|
||||
|
||||
private static String downloadViaHttp(String uri, String contentTypes) throws IOException {
|
||||
URL url = new URL(uri);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestProperty("Accept", contentTypes);
|
||||
connection.setRequestProperty("Accept-Charset", "utf-8,*");
|
||||
connection.setRequestProperty("User-Agent", "ZXing (Android)");
|
||||
try {
|
||||
connection.connect();
|
||||
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||
throw new IOException("Bad HTTP response: " + connection.getResponseCode());
|
||||
}
|
||||
return consume(connection);
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getEncoding(HttpURLConnection connection) {
|
||||
String contentTypeHeader = connection.getHeaderField("Content-Type");
|
||||
if (contentTypeHeader != null) {
|
||||
int charsetStart = contentTypeHeader.indexOf("charset=");
|
||||
if (charsetStart >= 0) {
|
||||
return contentTypeHeader.substring(charsetStart + "charset=".length());
|
||||
}
|
||||
}
|
||||
return "UTF-8";
|
||||
}
|
||||
|
||||
private static String consume(HttpURLConnection connection) throws IOException {
|
||||
String encoding = getEncoding(connection);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
InputStream in = connection.getInputStream();
|
||||
try {
|
||||
in = connection.getInputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException ioe) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
try {
|
||||
return new String(out.toByteArray(), encoding);
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
try {
|
||||
return new String(out.toByteArray(), "UTF-8");
|
||||
} catch (UnsupportedEncodingException uee2) {
|
||||
// can't happen
|
||||
throw new IllegalStateException(uee2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static URI unredirect(URI uri) throws IOException {
|
||||
if (!REDIRECTOR_DOMAINS.contains(uri.getHost())) {
|
||||
return uri;
|
||||
}
|
||||
URL url = uri.toURL();
|
||||
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setInstanceFollowRedirects(false);
|
||||
connection.setDoInput(false);
|
||||
connection.setRequestMethod("HEAD");
|
||||
connection.setRequestProperty("User-Agent", "ZXing (Android)");
|
||||
try {
|
||||
connection.connect();
|
||||
switch (connection.getResponseCode()) {
|
||||
case HttpURLConnection.HTTP_MULT_CHOICE:
|
||||
case HttpURLConnection.HTTP_MOVED_PERM:
|
||||
case HttpURLConnection.HTTP_MOVED_TEMP:
|
||||
case HttpURLConnection.HTTP_SEE_OTHER:
|
||||
case 307: // No constant for 307 Temporary Redirect ?
|
||||
String location = connection.getHeaderField("Location");
|
||||
if (location != null) {
|
||||
try {
|
||||
return new URI(location);
|
||||
} catch (URISyntaxException e) {
|
||||
// nevermind
|
||||
}
|
||||
}
|
||||
}
|
||||
return uri;
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (C) 2010 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.zxing.client.android.book;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import com.google.zxing.client.android.HttpHelper;
|
||||
import com.google.zxing.client.android.LocaleManager;
|
||||
import com.google.zxing.client.android.R;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
final class NetworkWorker implements Runnable {
|
||||
|
||||
private static final String TAG = NetworkWorker.class.getSimpleName();
|
||||
|
||||
private final String isbn;
|
||||
private final String query;
|
||||
private final Handler handler;
|
||||
|
||||
NetworkWorker(String isbn, String query, Handler handler) {
|
||||
this.isbn = isbn;
|
||||
this.query = query;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
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 uri;
|
||||
if (LocaleManager.isBookSearchUrl(isbn)) {
|
||||
int equals = isbn.indexOf('=');
|
||||
String volumeId = isbn.substring(equals + 1);
|
||||
uri = "http://www.google.com/books?id=" + volumeId + "&jscmd=SearchWithinVolume2&q=" + query;
|
||||
} else {
|
||||
uri = "http://www.google.com/books?vid=isbn" + isbn + "&jscmd=SearchWithinVolume2&q=" + query;
|
||||
}
|
||||
|
||||
try {
|
||||
String content = HttpHelper.downloadViaHttp(uri, HttpHelper.ContentType.JSON);
|
||||
JSONObject json = new JSONObject(content);
|
||||
Message message = Message.obtain(handler, R.id.search_book_contents_succeeded);
|
||||
message.obj = json;
|
||||
message.sendToTarget();
|
||||
} catch (IOException ioe) {
|
||||
Message message = Message.obtain(handler, R.id.search_book_contents_failed);
|
||||
message.sendToTarget();
|
||||
}
|
||||
} catch (JSONException je) {
|
||||
Log.w(TAG, "Error accessing book search", je);
|
||||
Message message = Message.obtain(handler, R.id.search_book_contents_failed);
|
||||
message.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -31,19 +31,10 @@ import android.widget.Button;
|
|||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpHead;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -51,7 +42,6 @@ import java.util.regex.Pattern;
|
|||
import com.google.zxing.client.android.LocaleManager;
|
||||
import com.google.zxing.client.android.R;
|
||||
import com.google.zxing.client.android.Intents;
|
||||
import com.google.zxing.client.android.AndroidHttpClient;
|
||||
|
||||
/**
|
||||
* Uses Google Book Search to find a word or phrase in the requested book.
|
||||
|
@ -59,16 +49,16 @@ import com.google.zxing.client.android.AndroidHttpClient;
|
|||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
public final class SearchBookContentsActivity extends Activity {
|
||||
|
||||
private static final String TAG = SearchBookContentsActivity.class.getSimpleName();
|
||||
|
||||
private static final String USER_AGENT = "ZXing (Android)";
|
||||
private static final Pattern TAG_PATTERN = Pattern.compile("\\<.*?\\>");
|
||||
private static final Pattern LT_ENTITY_PATTERN = Pattern.compile("<");
|
||||
private static final Pattern GT_ENTITY_PATTERN = Pattern.compile(">");
|
||||
private static final Pattern QUOTE_ENTITY_PATTERN = Pattern.compile("'");
|
||||
private static final Pattern QUOT_ENTITY_PATTERN = Pattern.compile(""");
|
||||
|
||||
private NetworkThread networkThread;
|
||||
private Thread networkThread;
|
||||
private String isbn;
|
||||
private EditText queryTextView;
|
||||
private Button queryButton;
|
||||
|
@ -169,7 +159,7 @@ public final class SearchBookContentsActivity extends Activity {
|
|||
if (networkThread == null) {
|
||||
String query = queryTextView.getText().toString();
|
||||
if (query != null && query.length() > 0) {
|
||||
networkThread = new NetworkThread(isbn, query, handler);
|
||||
networkThread = new Thread(new NetworkWorker(isbn, query, handler));
|
||||
networkThread.start();
|
||||
headerView.setText(R.string.msg_sbc_searching_book);
|
||||
resultListView.setAdapter(null);
|
||||
|
@ -240,105 +230,4 @@ public final class SearchBookContentsActivity extends Activity {
|
|||
}
|
||||
}
|
||||
|
||||
private static final class NetworkThread extends Thread {
|
||||
private final String isbn;
|
||||
private final String query;
|
||||
private final Handler handler;
|
||||
|
||||
NetworkThread(String isbn, String query, Handler handler) {
|
||||
this.isbn = isbn;
|
||||
this.query = query;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
AndroidHttpClient client = null;
|
||||
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.
|
||||
URI uri;
|
||||
if (LocaleManager.isBookSearchUrl(isbn)) {
|
||||
int equals = isbn.indexOf('=');
|
||||
String volumeId = isbn.substring(equals + 1);
|
||||
uri = new URI("http", null, "www.google.com", -1, "/books", "id=" + volumeId +
|
||||
"&jscmd=SearchWithinVolume2&q=" + query, null);
|
||||
} else {
|
||||
uri = new URI("http", null, "www.google.com", -1, "/books", "vid=isbn" + isbn +
|
||||
"&jscmd=SearchWithinVolume2&q=" + query, null);
|
||||
}
|
||||
HttpUriRequest get = new HttpGet(uri);
|
||||
get.setHeader("cookie", getCookie(uri.toString()));
|
||||
client = AndroidHttpClient.newInstance(USER_AGENT);
|
||||
HttpResponse response = client.execute(get);
|
||||
if (response.getStatusLine().getStatusCode() == 200) {
|
||||
HttpEntity entity = response.getEntity();
|
||||
ByteArrayOutputStream jsonHolder = new ByteArrayOutputStream();
|
||||
entity.writeTo(jsonHolder);
|
||||
jsonHolder.flush();
|
||||
JSONObject json = new JSONObject(jsonHolder.toString(getEncoding(entity)));
|
||||
jsonHolder.close();
|
||||
|
||||
Message message = Message.obtain(handler, R.id.search_book_contents_succeeded);
|
||||
message.obj = json;
|
||||
message.sendToTarget();
|
||||
} else {
|
||||
Log.w(TAG, "HTTP returned " + response.getStatusLine().getStatusCode() + " for " + uri);
|
||||
Message message = Message.obtain(handler, R.id.search_book_contents_failed);
|
||||
message.sendToTarget();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error accessing book search", e);
|
||||
Message message = Message.obtain(handler, R.id.search_book_contents_failed);
|
||||
message.sendToTarget();
|
||||
} finally {
|
||||
if (client != null) {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Book Search requires a cookie to work, which we store persistently. If the cookie does
|
||||
// not exist, this could be the first search or it has expired. Either way, do a quick HEAD
|
||||
// request to fetch it, save it via the CookieSyncManager to flash, then return it.
|
||||
private static String getCookie(String url) {
|
||||
String cookie = CookieManager.getInstance().getCookie(url);
|
||||
if (cookie == null || cookie.length() == 0) {
|
||||
Log.d(TAG, "Book Search cookie was missing or expired");
|
||||
HttpUriRequest head = new HttpHead(url);
|
||||
AndroidHttpClient client = AndroidHttpClient.newInstance(USER_AGENT);
|
||||
try {
|
||||
HttpResponse response = client.execute(head);
|
||||
if (response.getStatusLine().getStatusCode() == 200) {
|
||||
Header[] cookies = response.getHeaders("set-cookie");
|
||||
for (Header theCookie : cookies) {
|
||||
CookieManager.getInstance().setCookie(url, theCookie.getValue());
|
||||
}
|
||||
CookieSyncManager.getInstance().sync();
|
||||
cookie = CookieManager.getInstance().getCookie(url);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Error setting book search cookie", e);
|
||||
}
|
||||
client.close();
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
|
||||
private static String getEncoding(HttpEntity entity) {
|
||||
// FIXME: The server is returning ISO-8859-1 but the content is actually windows-1252.
|
||||
// Once Jeff fixes the HTTP response, remove this hardcoded value and go back to getting
|
||||
// the encoding dynamically.
|
||||
return "windows-1252";
|
||||
// HeaderElement[] elements = entity.getContentType().getElements();
|
||||
// if (elements != null && elements.length > 0) {
|
||||
// String encoding = elements[0].getParameterByName("charset").getValue();
|
||||
// if (encoding != null && encoding.length() > 0) {
|
||||
// return encoding;
|
||||
// }
|
||||
// }
|
||||
// return "UTF-8";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Collection;
|
|||
|
||||
import android.content.Context;
|
||||
import android.widget.TextView;
|
||||
import com.google.zxing.client.android.HttpHelper;
|
||||
import com.google.zxing.client.android.LocaleManager;
|
||||
import com.google.zxing.client.android.R;
|
||||
import org.json.JSONArray;
|
||||
|
@ -58,7 +59,8 @@ public final class BookResultInfoRetriever extends SupplementalInfoRetriever {
|
|||
@Override
|
||||
void retrieveSupplementalInfo() throws IOException, InterruptedException {
|
||||
|
||||
String contents = downloadViaHttp("https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbn);
|
||||
String contents = HttpHelper.downloadViaHttp("https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbn,
|
||||
HttpHelper.ContentType.JSON);
|
||||
|
||||
if (contents.length() == 0) {
|
||||
return;
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.content.Context;
|
|||
import android.os.Handler;
|
||||
import android.text.Html;
|
||||
import android.widget.TextView;
|
||||
import com.google.zxing.client.android.HttpHelper;
|
||||
import com.google.zxing.client.android.R;
|
||||
import com.google.zxing.client.android.history.HistoryManager;
|
||||
import com.google.zxing.client.android.LocaleManager;
|
||||
|
@ -56,7 +57,7 @@ final class ProductResultInfoRetriever extends SupplementalInfoRetriever {
|
|||
|
||||
String encodedProductID = URLEncoder.encode(productID, "UTF-8");
|
||||
String uri = BASE_PRODUCT_URI + encodedProductID;
|
||||
String content = downloadViaHttp(uri);
|
||||
String content = HttpHelper.downloadViaHttp(uri, HttpHelper.ContentType.HTML);
|
||||
|
||||
Matcher matcher = PRODUCT_NAME_PRICE_PATTERN.matcher(content);
|
||||
if (matcher.find()) {
|
||||
|
|
|
@ -24,21 +24,13 @@ import android.text.Spanned;
|
|||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.URLSpan;
|
||||
import android.widget.TextView;
|
||||
import com.google.zxing.client.android.AndroidHttpClient;
|
||||
import com.google.zxing.client.result.ISBNParsedResult;
|
||||
import com.google.zxing.client.result.ParsedResult;
|
||||
import com.google.zxing.client.result.ProductParsedResult;
|
||||
import com.google.zxing.client.result.URIParsedResult;
|
||||
import com.google.zxing.client.android.history.HistoryManager;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -156,42 +148,4 @@ public abstract class SupplementalInfoRetriever implements Callable<Void> {
|
|||
historyManager.addHistoryItemDetails(itemID, newText);
|
||||
}
|
||||
|
||||
protected static String downloadViaHttp(String uri) throws IOException {
|
||||
HttpUriRequest get = new HttpGet(uri);
|
||||
AndroidHttpClient client = AndroidHttpClient.newInstance(null);
|
||||
HttpResponse response = client.execute(get);
|
||||
int status = response.getStatusLine().getStatusCode();
|
||||
if (status != 200) {
|
||||
throw new IOException();
|
||||
}
|
||||
return consume(response.getEntity());
|
||||
}
|
||||
|
||||
private static String consume(HttpEntity entity) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = entity.getContent();
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
}
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException ioe) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
return new String(out.toByteArray(), "UTF-8");
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
// can't happen
|
||||
throw new IllegalStateException(uee);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,26 +19,18 @@ package com.google.zxing.client.android.result.supplement;
|
|||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.widget.TextView;
|
||||
import com.google.zxing.client.android.HttpHelper;
|
||||
import com.google.zxing.client.android.history.HistoryManager;
|
||||
import com.google.zxing.client.android.AndroidHttpClient;
|
||||
import com.google.zxing.client.android.R;
|
||||
import com.google.zxing.client.result.URIParsedResult;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpHead;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
final class URIResultInfoRetriever extends SupplementalInfoRetriever {
|
||||
|
||||
private static final String[] REDIRECTOR_HOSTS = {
|
||||
"http://bit.ly/",
|
||||
"http://tinyurl.com/",
|
||||
"http://tr.im/",
|
||||
"http://goo.gl/",
|
||||
"http://ow.ly/",
|
||||
};
|
||||
private static final int MAX_REDIRECTS = 5;
|
||||
|
||||
private final URIParsedResult result;
|
||||
private final String redirectString;
|
||||
|
@ -55,44 +47,22 @@ final class URIResultInfoRetriever extends SupplementalInfoRetriever {
|
|||
|
||||
@Override
|
||||
void retrieveSupplementalInfo() throws IOException, InterruptedException {
|
||||
String oldURI = result.getURI();
|
||||
String newURI = unredirect(oldURI);
|
||||
URI oldURI;
|
||||
try {
|
||||
oldURI = new URI(result.getURI());
|
||||
} catch (URISyntaxException e) {
|
||||
return;
|
||||
}
|
||||
URI newURI = HttpHelper.unredirect(oldURI);
|
||||
int count = 0;
|
||||
while (count < 3 && !oldURI.equals(newURI)) {
|
||||
append(result.getDisplayResult(), null, new String[] { redirectString + " : " + newURI }, newURI);
|
||||
count++;
|
||||
while (count++ < MAX_REDIRECTS && !oldURI.equals(newURI)) {
|
||||
append(result.getDisplayResult(),
|
||||
null,
|
||||
new String[] { redirectString + " : " + newURI },
|
||||
newURI.toString());
|
||||
oldURI = newURI;
|
||||
newURI = unredirect(newURI);
|
||||
newURI = HttpHelper.unredirect(newURI);
|
||||
}
|
||||
}
|
||||
|
||||
private static String unredirect(String uri) throws IOException {
|
||||
if (!isRedirector(uri)) {
|
||||
return uri;
|
||||
}
|
||||
HttpUriRequest head = new HttpHead(uri);
|
||||
AndroidHttpClient client = AndroidHttpClient.newInstance(null);
|
||||
HttpResponse response = client.execute(head);
|
||||
int status = response.getStatusLine().getStatusCode();
|
||||
if (status == 301 || status == 302) {
|
||||
Header redirect = response.getFirstHeader("Location");
|
||||
if (redirect != null) {
|
||||
String location = redirect.getValue();
|
||||
if (location != null) {
|
||||
return location;
|
||||
}
|
||||
}
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
private static boolean isRedirector(String uri) {
|
||||
for (String redirectorHost : REDIRECTOR_HOSTS) {
|
||||
if (uri.startsWith(redirectorHost)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue