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)) {
SupplementalInfoRetriever.maybeInvokeRetrieval(supplementTextView,
resultHandler.getResult(),
handler,
historyManager,
this);
}

View file

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

View file

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

View file

@ -30,8 +30,6 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import android.os.Handler;
import com.google.zxing.client.android.history.HistoryManager;
/**
@ -44,19 +42,15 @@ final class BookResultInfoRetriever extends SupplementalInfoRetriever {
private final String source;
private final Context context;
BookResultInfoRetriever(TextView textView,
String isbn,
Handler handler,
HistoryManager historyManager,
Context context) {
super(textView, handler, historyManager);
BookResultInfoRetriever(TextView textView, String isbn, HistoryManager historyManager, Context context) {
super(textView, historyManager);
this.isbn = isbn;
this.source = context.getString(R.string.msg_google_books);
this.context = context;
}
@Override
void retrieveSupplementalInfo() throws IOException, InterruptedException {
void retrieveSupplementalInfo() throws IOException {
String contents = HttpHelper.downloadViaHttp("https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbn,
HttpHelper.ContentType.JSON);
@ -87,7 +81,7 @@ final class BookResultInfoRetriever extends SupplementalInfoRetriever {
JSONArray authorsArray = volumeInfo.optJSONArray("authors");
if (authorsArray != null && !authorsArray.isNull(0)) {
authors = new ArrayList<String>();
authors = new ArrayList<String>(authorsArray.length());
for (int i = 0; i < authorsArray.length(); i++) {
authors.add(authorsArray.getString(i));
}
@ -121,7 +115,6 @@ final class BookResultInfoRetriever extends SupplementalInfoRetriever {
newTexts.add(pages + "pp.");
}
String baseBookUri = "http://www.google." + LocaleManager.getBookSearchCountryTLD(context)
+ "/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;
import android.content.Context;
import android.os.Handler;
import android.text.Html;
import android.widget.TextView;
import com.google.zxing.client.android.HttpHelper;
@ -32,39 +31,39 @@ import java.util.regex.Pattern;
final class ProductResultInfoRetriever extends SupplementalInfoRetriever {
private static final Pattern PRODUCT_NAME_PRICE_PATTERN =
Pattern.compile("owb63p\">([^<]+).+zdi3pb\">([^<]+)");
private static final Pattern[] PRODUCT_NAME_PRICE_PATTERNS = {
Pattern.compile(",event\\)\">([^<]+)</a></h3>.+<span class=psrp>([^<]+)</span>"),
Pattern.compile("owb63p\">([^<]+).+zdi3pb\">([^<]+)"),
};
private final String productID;
private final String source;
private final Context context;
ProductResultInfoRetriever(TextView textView,
String productID,
Handler handler,
HistoryManager historyManager,
Context context) {
super(textView, handler, historyManager);
ProductResultInfoRetriever(TextView textView, String productID, HistoryManager historyManager, Context context) {
super(textView, historyManager);
this.productID = productID;
this.source = context.getString(R.string.msg_google_product);
this.context = context;
}
@Override
void retrieveSupplementalInfo() throws IOException, InterruptedException {
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;
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);
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;
}
}
}

View file

@ -17,12 +17,14 @@
package com.google.zxing.client.android.result.supplement;
import android.content.Context;
import android.os.Handler;
import android.nfc.Tag;
import android.os.AsyncTask;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.URLSpan;
import android.util.Log;
import android.widget.TextView;
import com.google.zxing.client.result.ISBNParsedResult;
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.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
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;
import java.util.List;
public abstract class SupplementalInfoRetriever implements Callable<Void> {
public abstract class SupplementalInfoRetriever extends AsyncTask<Void,Void,Void> {
private static ExecutorService executorInstance = null;
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;
}
private static final String TAG = "SupplementalInfo";
public static void maybeInvokeRetrieval(TextView textView,
ParsedResult result,
Handler handler,
HistoryManager historyManager,
Context context) {
Collection<SupplementalInfoRetriever> retrievers = new ArrayList<SupplementalInfoRetriever>(1);
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) {
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) {
String isbn = ((ISBNParsedResult) result).getISBN();
retrievers.add(new ProductResultInfoRetriever(textView, isbn, handler, historyManager, context));
retrievers.add(new BookResultInfoRetriever(textView, isbn, handler, historyManager, context));
}
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));
new ProductResultInfoRetriever(textView, isbn, historyManager, context).execute();
new BookResultInfoRetriever(textView, isbn, historyManager, context).execute();
}
}
private final WeakReference<TextView> textViewRef;
private final Handler handler;
private final HistoryManager historyManager;
private final WeakReference<HistoryManager> historyManagerRef;
private final List<Spannable> newContents;
private final List<String[]> newHistories;
SupplementalInfoRetriever(TextView textView, Handler handler, HistoryManager historyManager) {
this.textViewRef = new WeakReference<TextView>(textView);
this.handler = handler;
this.historyManager = historyManager;
SupplementalInfoRetriever(TextView textView, HistoryManager historyManager) {
textViewRef = new WeakReference<TextView>(textView);
historyManagerRef = new WeakReference<HistoryManager>(historyManager);
newContents = new ArrayList<Spannable>();
newHistories = new ArrayList<String[]>();
}
@Override
public final Void call() throws IOException, InterruptedException {
retrieveSupplementalInfo();
public final Void doInBackground(Void... args) {
try {
retrieveSupplementalInfo();
} catch (IOException e) {
Log.w(TAG, e);
}
return null;
}
abstract void retrieveSupplementalInfo() throws IOException, InterruptedException;
final void append(String itemID, String source, String[] newTexts, String linkURL) throws InterruptedException {
final TextView textView = textViewRef.get();
if (textView == null) {
throw new InterruptedException();
@Override
protected void onPostExecute(Void arg) {
TextView textView = textViewRef.get();
if (textView != null) {
for (Spannable content : newContents) {
textView.append(content);
}
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();
@ -134,21 +123,13 @@ public abstract class SupplementalInfoRetriever implements Callable<Void> {
int linkEnd = newTextCombined.length();
String newText = newTextCombined.toString();
final Spannable content = new SpannableString(newText + "\n\n");
Spannable content = new SpannableString(newText + "\n\n");
if (linkURL != null) {
content.setSpan(new URLSpan(linkURL), linkStart, linkEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
handler.post(new Runnable() {
@Override
public void run() {
textView.append(content);
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
});
// Add the text to the history.
historyManager.addHistoryItemDetails(itemID, newText);
newContents.add(content);
newHistories.add(new String[] {itemID, newText});
}
}

View file

@ -17,7 +17,6 @@
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;
@ -35,18 +34,14 @@ final class URIResultInfoRetriever extends SupplementalInfoRetriever {
private final URIParsedResult result;
private final String redirectString;
URIResultInfoRetriever(TextView textView,
URIParsedResult result,
Handler handler,
HistoryManager historyManager,
Context context) {
super(textView, handler, historyManager);
URIResultInfoRetriever(TextView textView, URIParsedResult result, HistoryManager historyManager, Context context) {
super(textView, historyManager);
redirectString = context.getString(R.string.msg_redirect);
this.result = result;
}
@Override
void retrieveSupplementalInfo() throws IOException, InterruptedException {
void retrieveSupplementalInfo() throws IOException {
URI oldURI;
try {
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.WifiManager;
import android.os.AsyncTask;
import android.util.Log;
import java.util.List;
@ -29,68 +30,68 @@ import com.google.zxing.client.result.WifiParsedResult;
* @author Vikram Aggarwal
* @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 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
public void run() {
// Start WiFi, otherwise nothing will work
if (!wifiManager.isWifiEnabled()) {
Log.i(TAG, "Enabling wi-fi...");
if (wifiManager.setWifiEnabled(true)) {
Log.i(TAG, "Wi-fi enabled");
} else {
Log.w(TAG, "Wi-fi could not be enabled!");
return;
}
// This happens very quickly, but need to wait for it to enable. A little busy wait?
int count = 0;
while (!wifiManager.isWifiEnabled()) {
if (count >= 10) {
Log.i(TAG, "Took too long to enable wi-fi, quitting");
return;
}
Log.i(TAG, "Still waiting for wi-fi to enable...");
try {
Thread.sleep(1000L);
} catch (InterruptedException ie) {
// continue
}
count++;
}
}
String networkTypeString = wifiResult.getNetworkEncryption();
NetworkType networkType;
try {
networkType = NetworkType.forIntentValue(networkTypeString);
} catch (IllegalArgumentException iae) {
Log.w(TAG, "Bad network type; see NetworkType values: " + networkTypeString);
return;
}
if (networkType == NetworkType.NO_PASSWORD) {
changeNetworkUnEncrypted(wifiManager, wifiResult);
} else {
String password = wifiResult.getPassword();
if (password == null || password.length() == 0) {
throw new IllegalArgumentException();
}
if (networkType == NetworkType.WEP) {
changeNetworkWEP(wifiManager, wifiResult);
} else if (networkType == NetworkType.WPA) {
changeNetworkWPA(wifiManager, wifiResult);
}
}
@Override
protected Void doInBackground(WifiParsedResult... args) {
WifiParsedResult theWifiResult = args[0];
// Start WiFi, otherwise nothing will work
if (!wifiManager.isWifiEnabled()) {
Log.i(TAG, "Enabling wi-fi...");
if (wifiManager.setWifiEnabled(true)) {
Log.i(TAG, "Wi-fi enabled");
} else {
Log.w(TAG, "Wi-fi could not be enabled!");
return null;
}
};
new Thread(configureRunnable).start();
// This happens very quickly, but need to wait for it to enable. A little busy wait?
int count = 0;
while (!wifiManager.isWifiEnabled()) {
if (count >= 10) {
Log.i(TAG, "Took too long to enable wi-fi, quitting");
return null;
}
Log.i(TAG, "Still waiting for wi-fi to enable...");
try {
Thread.sleep(1000L);
} catch (InterruptedException ie) {
// continue
}
count++;
}
}
String networkTypeString = theWifiResult.getNetworkEncryption();
NetworkType networkType;
try {
networkType = NetworkType.forIntentValue(networkTypeString);
} catch (IllegalArgumentException iae) {
Log.w(TAG, "Bad network type; see NetworkType values: " + networkTypeString);
return null;
}
if (networkType == NetworkType.NO_PASSWORD) {
changeNetworkUnEncrypted(wifiManager, theWifiResult);
} else {
String password = theWifiResult.getPassword();
if (password == null || password.length() == 0) {
throw new IllegalArgumentException();
}
if (networkType == NetworkType.WEP) {
changeNetworkWEP(wifiManager, theWifiResult);
} else if (networkType == NetworkType.WPA) {
changeNetworkWPA(wifiManager, theWifiResult);
}
}
return null;
}
/**