Use AsyncTask in network, supplemental info task. Fix product search scrape.

git-svn-id: https://zxing.googlecode.com/svn/trunk@2375 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2012-08-06 20:41:04 +00:00
parent 5384255cae
commit 65c5ef40b3
9 changed files with 126 additions and 204 deletions

View file

@ -563,7 +563,6 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal
PreferencesActivity.KEY_SUPPLEMENTAL, true)) { PreferencesActivity.KEY_SUPPLEMENTAL, true)) {
SupplementalInfoRetriever.maybeInvokeRetrieval(supplementTextView, SupplementalInfoRetriever.maybeInvokeRetrieval(supplementTextView,
resultHandler.getResult(), resultHandler.getResult(),
handler,
historyManager, historyManager,
this); this);
} }

View file

@ -90,6 +90,7 @@ public final class HttpHelper {
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IOException("Bad HTTP response: " + connection.getResponseCode()); throw new IOException("Bad HTTP response: " + connection.getResponseCode());
} }
Log.i(TAG, "Consuming " + uri);
return consume(connection); return consume(connection);
} finally { } finally {
connection.disconnect(); connection.disconnect();

View file

@ -57,7 +57,7 @@ public final class WifiResultHandler extends ResultHandler {
WifiParsedResult wifiResult = (WifiParsedResult) getResult(); WifiParsedResult wifiResult = (WifiParsedResult) getResult();
WifiManager wifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE); WifiManager wifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE);
Toast.makeText(getActivity(), R.string.wifi_changing_network, Toast.LENGTH_LONG).show(); Toast.makeText(getActivity(), R.string.wifi_changing_network, Toast.LENGTH_LONG).show();
WifiConfigManager.configure(wifiManager, wifiResult); new WifiConfigManager(wifiManager).execute(wifiResult);
parent.restartPreviewAfterDelay(0L); parent.restartPreviewAfterDelay(0L);
} }
} }

View file

@ -30,8 +30,6 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.json.JSONTokener; import org.json.JSONTokener;
import android.os.Handler;
import com.google.zxing.client.android.history.HistoryManager; import com.google.zxing.client.android.history.HistoryManager;
/** /**
@ -44,19 +42,15 @@ final class BookResultInfoRetriever extends SupplementalInfoRetriever {
private final String source; private final String source;
private final Context context; private final Context context;
BookResultInfoRetriever(TextView textView, BookResultInfoRetriever(TextView textView, String isbn, HistoryManager historyManager, Context context) {
String isbn, super(textView, historyManager);
Handler handler,
HistoryManager historyManager,
Context context) {
super(textView, handler, historyManager);
this.isbn = isbn; this.isbn = isbn;
this.source = context.getString(R.string.msg_google_books); this.source = context.getString(R.string.msg_google_books);
this.context = context; this.context = context;
} }
@Override @Override
void retrieveSupplementalInfo() throws IOException, InterruptedException { void retrieveSupplementalInfo() throws IOException {
String contents = HttpHelper.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); HttpHelper.ContentType.JSON);
@ -87,7 +81,7 @@ final class BookResultInfoRetriever extends SupplementalInfoRetriever {
JSONArray authorsArray = volumeInfo.optJSONArray("authors"); JSONArray authorsArray = volumeInfo.optJSONArray("authors");
if (authorsArray != null && !authorsArray.isNull(0)) { if (authorsArray != null && !authorsArray.isNull(0)) {
authors = new ArrayList<String>(); authors = new ArrayList<String>(authorsArray.length());
for (int i = 0; i < authorsArray.length(); i++) { for (int i = 0; i < authorsArray.length(); i++) {
authors.add(authorsArray.getString(i)); authors.add(authorsArray.getString(i));
} }
@ -121,7 +115,6 @@ final class BookResultInfoRetriever extends SupplementalInfoRetriever {
newTexts.add(pages + "pp."); newTexts.add(pages + "pp.");
} }
String baseBookUri = "http://www.google." + LocaleManager.getBookSearchCountryTLD(context) String baseBookUri = "http://www.google." + LocaleManager.getBookSearchCountryTLD(context)
+ "/search?tbm=bks&source=zxing&q="; + "/search?tbm=bks&source=zxing&q=";

View file

@ -1,47 +0,0 @@
/*
* 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.result.supplement;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
final class KillerCallable implements Callable<Void> {
private final Future<?> future;
private final long timeout;
private final TimeUnit unit;
KillerCallable(Future<?> future, long timeout, TimeUnit unit) {
this.future = future;
this.timeout = timeout;
this.unit = unit;
}
@Override
public Void call() throws ExecutionException, InterruptedException {
try {
future.get(timeout, unit);
} catch (TimeoutException te) {
future.cancel(true);
}
return null;
}
}

View file

@ -17,7 +17,6 @@
package com.google.zxing.client.android.result.supplement; package com.google.zxing.client.android.result.supplement;
import android.content.Context; import android.content.Context;
import android.os.Handler;
import android.text.Html; import android.text.Html;
import android.widget.TextView; import android.widget.TextView;
import com.google.zxing.client.android.HttpHelper; import com.google.zxing.client.android.HttpHelper;
@ -32,39 +31,39 @@ import java.util.regex.Pattern;
final class ProductResultInfoRetriever extends SupplementalInfoRetriever { final class ProductResultInfoRetriever extends SupplementalInfoRetriever {
private static final Pattern PRODUCT_NAME_PRICE_PATTERN = private static final Pattern[] PRODUCT_NAME_PRICE_PATTERNS = {
Pattern.compile("owb63p\">([^<]+).+zdi3pb\">([^<]+)"); Pattern.compile(",event\\)\">([^<]+)</a></h3>.+<span class=psrp>([^<]+)</span>"),
Pattern.compile("owb63p\">([^<]+).+zdi3pb\">([^<]+)"),
};
private final String productID; private final String productID;
private final String source; private final String source;
private final Context context; private final Context context;
ProductResultInfoRetriever(TextView textView, ProductResultInfoRetriever(TextView textView, String productID, HistoryManager historyManager, Context context) {
String productID, super(textView, historyManager);
Handler handler,
HistoryManager historyManager,
Context context) {
super(textView, handler, historyManager);
this.productID = productID; this.productID = productID;
this.source = context.getString(R.string.msg_google_product); this.source = context.getString(R.string.msg_google_product);
this.context = context; this.context = context;
} }
@Override @Override
void retrieveSupplementalInfo() throws IOException, InterruptedException { void retrieveSupplementalInfo() throws IOException {
String encodedProductID = URLEncoder.encode(productID, "UTF-8"); String encodedProductID = URLEncoder.encode(productID, "UTF-8");
String uri = "http://www.google." + LocaleManager.getProductSearchCountryTLD(context) String uri = "http://www.google." + LocaleManager.getProductSearchCountryTLD(context)
+ "/m/products?ie=utf8&oe=utf8&scoring=p&source=zxing&q=" + encodedProductID; + "/m/products?ie=utf8&oe=utf8&scoring=p&source=zxing&q=" + encodedProductID;
String content = HttpHelper.downloadViaHttp(uri, HttpHelper.ContentType.HTML); String content = HttpHelper.downloadViaHttp(uri, HttpHelper.ContentType.HTML);
Matcher matcher = PRODUCT_NAME_PRICE_PATTERN.matcher(content); for (Pattern p : PRODUCT_NAME_PRICE_PATTERNS) {
Matcher matcher = p.matcher(content);
if (matcher.find()) { if (matcher.find()) {
append(productID, append(productID,
source, source,
new String[] { unescapeHTML(matcher.group(1)), unescapeHTML(matcher.group(2)) }, new String[] { unescapeHTML(matcher.group(1)), unescapeHTML(matcher.group(2)) },
uri); uri);
break;
}
} }
} }

View file

@ -17,12 +17,14 @@
package com.google.zxing.client.android.result.supplement; package com.google.zxing.client.android.result.supplement;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.nfc.Tag;
import android.os.AsyncTask;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.text.style.URLSpan; import android.text.style.URLSpan;
import android.util.Log;
import android.widget.TextView; import android.widget.TextView;
import com.google.zxing.client.result.ISBNParsedResult; import com.google.zxing.client.result.ISBNParsedResult;
import com.google.zxing.client.result.ParsedResult; import com.google.zxing.client.result.ParsedResult;
@ -33,83 +35,70 @@ import com.google.zxing.client.android.history.HistoryManager;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
public abstract class SupplementalInfoRetriever implements Callable<Void> { public abstract class SupplementalInfoRetriever extends AsyncTask<Void,Void,Void> {
private static ExecutorService executorInstance = null; private static final String TAG = "SupplementalInfo";
private static synchronized ExecutorService getExecutorService() {
if (executorInstance == null) {
executorInstance = Executors.newCachedThreadPool(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
}
return executorInstance;
}
public static void maybeInvokeRetrieval(TextView textView, public static void maybeInvokeRetrieval(TextView textView,
ParsedResult result, ParsedResult result,
Handler handler,
HistoryManager historyManager, HistoryManager historyManager,
Context context) { Context context) {
Collection<SupplementalInfoRetriever> retrievers = new ArrayList<SupplementalInfoRetriever>(1);
if (result instanceof URIParsedResult) { if (result instanceof URIParsedResult) {
retrievers.add(new URIResultInfoRetriever(textView, (URIParsedResult) result, handler, historyManager, context)); new URIResultInfoRetriever(textView, (URIParsedResult) result, historyManager, context).execute();
} else if (result instanceof ProductParsedResult) { } else if (result instanceof ProductParsedResult) {
String productID = ((ProductParsedResult) result).getProductID(); String productID = ((ProductParsedResult) result).getProductID();
retrievers.add(new ProductResultInfoRetriever(textView, productID, handler, historyManager, context)); new ProductResultInfoRetriever(textView, productID, historyManager, context).execute();
} else if (result instanceof ISBNParsedResult) { } else if (result instanceof ISBNParsedResult) {
String isbn = ((ISBNParsedResult) result).getISBN(); String isbn = ((ISBNParsedResult) result).getISBN();
retrievers.add(new ProductResultInfoRetriever(textView, isbn, handler, historyManager, context)); new ProductResultInfoRetriever(textView, isbn, historyManager, context).execute();
retrievers.add(new BookResultInfoRetriever(textView, isbn, handler, historyManager, context)); new BookResultInfoRetriever(textView, isbn, historyManager, context).execute();
}
for (SupplementalInfoRetriever retriever : retrievers) {
ExecutorService executor = getExecutorService();
Future<?> future = executor.submit(retriever);
// Make sure it's interrupted after a short time though
executor.submit(new KillerCallable(future, 10, TimeUnit.SECONDS));
} }
} }
private final WeakReference<TextView> textViewRef; private final WeakReference<TextView> textViewRef;
private final Handler handler; private final WeakReference<HistoryManager> historyManagerRef;
private final HistoryManager historyManager; private final List<Spannable> newContents;
private final List<String[]> newHistories;
SupplementalInfoRetriever(TextView textView, Handler handler, HistoryManager historyManager) { SupplementalInfoRetriever(TextView textView, HistoryManager historyManager) {
this.textViewRef = new WeakReference<TextView>(textView); textViewRef = new WeakReference<TextView>(textView);
this.handler = handler; historyManagerRef = new WeakReference<HistoryManager>(historyManager);
this.historyManager = historyManager; newContents = new ArrayList<Spannable>();
newHistories = new ArrayList<String[]>();
} }
@Override @Override
public final Void call() throws IOException, InterruptedException { public final Void doInBackground(Void... args) {
try {
retrieveSupplementalInfo(); retrieveSupplementalInfo();
} catch (IOException e) {
Log.w(TAG, e);
}
return null; return null;
} }
abstract void retrieveSupplementalInfo() throws IOException, InterruptedException; @Override
protected void onPostExecute(Void arg) {
final void append(String itemID, String source, String[] newTexts, String linkURL) throws InterruptedException { TextView textView = textViewRef.get();
if (textView != null) {
final TextView textView = textViewRef.get(); for (Spannable content : newContents) {
if (textView == null) { textView.append(content);
throw new InterruptedException();
} }
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
HistoryManager historyManager = historyManagerRef.get();
if (historyManager != null) {
for (String[] text : newHistories) {
historyManager.addHistoryItemDetails(text[0], text[1]);
}
}
}
abstract void retrieveSupplementalInfo() throws IOException;
final void append(String itemID, String source, String[] newTexts, String linkURL) {
StringBuilder newTextCombined = new StringBuilder(); StringBuilder newTextCombined = new StringBuilder();
@ -134,21 +123,13 @@ public abstract class SupplementalInfoRetriever implements Callable<Void> {
int linkEnd = newTextCombined.length(); int linkEnd = newTextCombined.length();
String newText = newTextCombined.toString(); String newText = newTextCombined.toString();
final Spannable content = new SpannableString(newText + "\n\n"); Spannable content = new SpannableString(newText + "\n\n");
if (linkURL != null) { if (linkURL != null) {
content.setSpan(new URLSpan(linkURL), linkStart, linkEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); content.setSpan(new URLSpan(linkURL), linkStart, linkEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} }
handler.post(new Runnable() { newContents.add(content);
@Override newHistories.add(new String[] {itemID, newText});
public void run() {
textView.append(content);
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
});
// Add the text to the history.
historyManager.addHistoryItemDetails(itemID, newText);
} }
} }

View file

@ -17,7 +17,6 @@
package com.google.zxing.client.android.result.supplement; package com.google.zxing.client.android.result.supplement;
import android.content.Context; import android.content.Context;
import android.os.Handler;
import android.widget.TextView; import android.widget.TextView;
import com.google.zxing.client.android.HttpHelper; import com.google.zxing.client.android.HttpHelper;
import com.google.zxing.client.android.history.HistoryManager; import com.google.zxing.client.android.history.HistoryManager;
@ -35,18 +34,14 @@ final class URIResultInfoRetriever extends SupplementalInfoRetriever {
private final URIParsedResult result; private final URIParsedResult result;
private final String redirectString; private final String redirectString;
URIResultInfoRetriever(TextView textView, URIResultInfoRetriever(TextView textView, URIParsedResult result, HistoryManager historyManager, Context context) {
URIParsedResult result, super(textView, historyManager);
Handler handler,
HistoryManager historyManager,
Context context) {
super(textView, handler, historyManager);
redirectString = context.getString(R.string.msg_redirect); redirectString = context.getString(R.string.msg_redirect);
this.result = result; this.result = result;
} }
@Override @Override
void retrieveSupplementalInfo() throws IOException, InterruptedException { void retrieveSupplementalInfo() throws IOException {
URI oldURI; URI oldURI;
try { try {
oldURI = new URI(result.getURI()); oldURI = new URI(result.getURI());

View file

@ -18,6 +18,7 @@ package com.google.zxing.client.android.wifi;
import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.util.Log; import android.util.Log;
import java.util.List; import java.util.List;
@ -29,19 +30,21 @@ import com.google.zxing.client.result.WifiParsedResult;
* @author Vikram Aggarwal * @author Vikram Aggarwal
* @author Sean Owen * @author Sean Owen
*/ */
public final class WifiConfigManager { public final class WifiConfigManager extends AsyncTask<WifiParsedResult,Void,Void> {
private static final String TAG = WifiConfigManager.class.getSimpleName(); private static final String TAG = WifiConfigManager.class.getSimpleName();
private static final Pattern HEX_DIGITS = Pattern.compile("[0-9A-Fa-f]+"); private static final Pattern HEX_DIGITS = Pattern.compile("[0-9A-Fa-f]+");
private WifiConfigManager() { private final WifiManager wifiManager;
public WifiConfigManager(WifiManager wifiManager) {
this.wifiManager = wifiManager;
} }
public static void configure(final WifiManager wifiManager, final WifiParsedResult wifiResult) {
Runnable configureRunnable = new Runnable() {
@Override @Override
public void run() { protected Void doInBackground(WifiParsedResult... args) {
WifiParsedResult theWifiResult = args[0];
// Start WiFi, otherwise nothing will work // Start WiFi, otherwise nothing will work
if (!wifiManager.isWifiEnabled()) { if (!wifiManager.isWifiEnabled()) {
Log.i(TAG, "Enabling wi-fi..."); Log.i(TAG, "Enabling wi-fi...");
@ -49,14 +52,14 @@ public final class WifiConfigManager {
Log.i(TAG, "Wi-fi enabled"); Log.i(TAG, "Wi-fi enabled");
} else { } else {
Log.w(TAG, "Wi-fi could not be enabled!"); Log.w(TAG, "Wi-fi could not be enabled!");
return; return null;
} }
// This happens very quickly, but need to wait for it to enable. A little busy wait? // This happens very quickly, but need to wait for it to enable. A little busy wait?
int count = 0; int count = 0;
while (!wifiManager.isWifiEnabled()) { while (!wifiManager.isWifiEnabled()) {
if (count >= 10) { if (count >= 10) {
Log.i(TAG, "Took too long to enable wi-fi, quitting"); Log.i(TAG, "Took too long to enable wi-fi, quitting");
return; return null;
} }
Log.i(TAG, "Still waiting for wi-fi to enable..."); Log.i(TAG, "Still waiting for wi-fi to enable...");
try { try {
@ -67,30 +70,28 @@ public final class WifiConfigManager {
count++; count++;
} }
} }
String networkTypeString = wifiResult.getNetworkEncryption(); String networkTypeString = theWifiResult.getNetworkEncryption();
NetworkType networkType; NetworkType networkType;
try { try {
networkType = NetworkType.forIntentValue(networkTypeString); networkType = NetworkType.forIntentValue(networkTypeString);
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
Log.w(TAG, "Bad network type; see NetworkType values: " + networkTypeString); Log.w(TAG, "Bad network type; see NetworkType values: " + networkTypeString);
return; return null;
} }
if (networkType == NetworkType.NO_PASSWORD) { if (networkType == NetworkType.NO_PASSWORD) {
changeNetworkUnEncrypted(wifiManager, wifiResult); changeNetworkUnEncrypted(wifiManager, theWifiResult);
} else { } else {
String password = wifiResult.getPassword(); String password = theWifiResult.getPassword();
if (password == null || password.length() == 0) { if (password == null || password.length() == 0) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
if (networkType == NetworkType.WEP) { if (networkType == NetworkType.WEP) {
changeNetworkWEP(wifiManager, wifiResult); changeNetworkWEP(wifiManager, theWifiResult);
} else if (networkType == NetworkType.WPA) { } else if (networkType == NetworkType.WPA) {
changeNetworkWPA(wifiManager, wifiResult); changeNetworkWPA(wifiManager, theWifiResult);
} }
} }
} return null;
};
new Thread(configureRunnable).start();
} }
/** /**