Index: src/org/adblockplus/android/AdblockPlus.java |
=================================================================== |
--- a/src/org/adblockplus/android/AdblockPlus.java |
+++ b/src/org/adblockplus/android/AdblockPlus.java |
@@ -19,36 +19,15 @@ |
import java.io.BufferedReader; |
import java.io.File; |
-import java.io.FileInputStream; |
import java.io.FileNotFoundException; |
-import java.io.FileOutputStream; |
import java.io.IOException; |
import java.io.InputStream; |
import java.io.InputStreamReader; |
-import java.net.HttpURLConnection; |
-import java.net.URL; |
-import java.util.ArrayList; |
import java.util.Calendar; |
-import java.util.LinkedList; |
-import java.util.List; |
-import java.util.Locale; |
-import java.util.Map; |
import java.util.TimeZone; |
-import java.util.concurrent.Callable; |
-import java.util.concurrent.ExecutionException; |
-import java.util.concurrent.Future; |
-import java.util.concurrent.FutureTask; |
- |
-import javax.xml.parsers.ParserConfigurationException; |
-import javax.xml.parsers.SAXParser; |
-import javax.xml.parsers.SAXParserFactory; |
+import java.util.regex.Pattern; |
import org.adblockplus.android.updater.AlarmReceiver; |
-import org.apache.commons.lang.StringEscapeUtils; |
-import org.apache.commons.lang.StringUtils; |
-import org.json.JSONException; |
-import org.json.JSONObject; |
-import org.xml.sax.SAXException; |
import android.app.ActivityManager; |
import android.app.ActivityManager.RunningServiceInfo; |
@@ -57,30 +36,24 @@ |
import android.app.PendingIntent; |
import android.content.Context; |
import android.content.Intent; |
-import android.content.SharedPreferences; |
import android.content.pm.PackageInfo; |
import android.content.pm.PackageManager; |
import android.content.pm.PackageManager.NameNotFoundException; |
-import android.content.res.AssetManager; |
import android.net.ConnectivityManager; |
import android.net.NetworkInfo; |
import android.net.Uri; |
-import android.os.AsyncTask; |
import android.os.Build; |
-import android.os.Bundle; |
-import android.os.Handler; |
-import android.os.Message; |
-import android.os.SystemClock; |
-import android.preference.PreferenceManager; |
import android.provider.Settings; |
import android.util.Log; |
-import android.widget.Toast; |
public class AdblockPlus extends Application |
{ |
private final static String TAG = "Application"; |
- private final static int MSG_TOAST = 1; |
+ private final static Pattern RE_JS = Pattern.compile(".*\\.js$", Pattern.CASE_INSENSITIVE); |
+ private final static Pattern RE_CSS = Pattern.compile(".*\\.css$", Pattern.CASE_INSENSITIVE); |
+ private final static Pattern RE_IMAGE = Pattern.compile(".*\\.(?:gif|png|jpe?g|bmp|ico)$", Pattern.CASE_INSENSITIVE); |
+ private final static Pattern RE_FONT = Pattern.compile(".*\\.(?:ttf|woff)$", Pattern.CASE_INSENSITIVE); |
Wladimir Palant
2013/09/12 11:31:14
Wouldn't it make sense to drop .* at the beginning
|
/** |
* Broadcasted when filtering is enabled or disabled. |
@@ -95,20 +68,14 @@ |
*/ |
public final static String BROADCAST_FILTER_MATCHES = "org.adblockplus.android.filter.matches"; |
- private List<Subscription> subscriptions; |
- |
- private JSThread js; |
- |
- /** |
- * Indicates interactive mode (used to listen for subscription status |
- * changes). |
- */ |
- private boolean interactive = false; |
+ private Subscription[] subscriptions; |
Wladimir Palant
2013/09/12 11:31:14
Add a comment explaining that this is the cached l
|
/** |
* Indicates whether filtering is enabled or not. |
*/ |
private boolean filteringEnabled = false; |
+ |
+ private ABPEngine abpEngine; |
private static AdblockPlus instance; |
@@ -244,184 +211,65 @@ |
return res == PackageManager.PERMISSION_GRANTED; |
} |
+ public boolean isFirstRun() |
+ { |
+ return abpEngine.isFirstRun(); |
+ } |
+ |
/** |
* Returns list of known subscriptions. |
*/ |
- public List<Subscription> getSubscriptions() |
+ public Subscription[] getRecommendedSubscriptions() |
{ |
if (subscriptions == null) |
- { |
- subscriptions = new ArrayList<Subscription>(); |
- |
- SAXParserFactory factory = SAXParserFactory.newInstance(); |
- SAXParser parser; |
- try |
- { |
- parser = factory.newSAXParser(); |
- parser.parse(getAssets().open("subscriptions.xml"), new SubscriptionParser(subscriptions)); |
- } |
- catch (ParserConfigurationException e) |
- { |
- // TODO Auto-generated catch block |
- Log.e(TAG, e.getMessage(), e); |
- } |
- catch (SAXException e) |
- { |
- // TODO Auto-generated catch block |
- Log.e(TAG, e.getMessage(), e); |
- } |
- catch (IOException e) |
- { |
- // TODO Auto-generated catch block |
- Log.e(TAG, e.getMessage(), e); |
- } |
- } |
+ subscriptions = abpEngine.getRecommendedSubscriptions(); |
return subscriptions; |
} |
/** |
- * Returns subscription information. |
- * |
- * @param url |
- * subscription url |
+ * Returns list of enabled subscriptions. |
*/ |
- public Subscription getSubscription(String url) |
+ public Subscription[] getListedSubscriptions() |
{ |
- List<Subscription> subscriptions = getSubscriptions(); |
- |
- for (Subscription subscription : subscriptions) |
- { |
- if (subscription.url.equals(url)) |
- return subscription; |
- } |
- return null; |
+ return abpEngine.getListedSubscriptions(); |
} |
/** |
* Adds provided subscription and removes previous subscriptions if any. |
* |
- * @param subscription |
- * Subscription to add |
+ * @param url |
+ * URL of subscription to add |
*/ |
- public void setSubscription(Subscription subscription) |
+ public void setSubscription(String url) |
{ |
- if (subscription != null) |
+ Subscription[] subscriptions = abpEngine.getListedSubscriptions(); |
+ for (Subscription subscription : subscriptions) |
{ |
- final JSONObject jsonSub = new JSONObject(); |
- try |
- { |
- jsonSub.put("url", subscription.url); |
- jsonSub.put("title", subscription.title); |
- jsonSub.put("homepage", subscription.homepage); |
- js.execute(new Runnable() |
- { |
- @Override |
- public void run() |
- { |
- js.evaluate("clearSubscriptions()"); |
- js.evaluate("addSubscription(\"" + StringEscapeUtils.escapeJavaScript(jsonSub.toString()) + "\")"); |
- } |
- }); |
- } |
- catch (JSONException e) |
- { |
- // TODO Auto-generated catch block |
- Log.e(TAG, e.getMessage(), e); |
- } |
+ abpEngine.removeSubscription(subscription.url); |
} |
+ abpEngine.addSubscription(url); |
} |
/** |
* Forces subscriptions refresh. |
*/ |
- public void refreshSubscription() |
+ public void refreshSubscriptions() |
{ |
- js.execute(new Runnable() |
+ Subscription[] subscriptions = abpEngine.getListedSubscriptions(); |
+ for (Subscription subscription : subscriptions) |
{ |
- @Override |
- public void run() |
- { |
- js.evaluate("refreshSubscriptions()"); |
- } |
- }); |
+ abpEngine.refreshSubscription(subscription.url); |
+ } |
} |
- |
+ |
/** |
- * Selects which subscription to offer for the first time. |
+ * Enforces subscription status update. |
* |
- * @return offered subscription |
+ * @param url Subscription url |
*/ |
- public Subscription offerSubscription() |
+ public void actualizeSubscriptionStatus(String url) |
{ |
- Subscription selectedItem = null; |
- String selectedPrefix = null; |
- int matchCount = 0; |
- for (Subscription subscription : getSubscriptions()) |
- { |
- if (selectedItem == null) |
- selectedItem = subscription; |
- |
- String prefix = checkLocalePrefixMatch(subscription.prefixes); |
- if (prefix != null) |
- { |
- if (selectedPrefix == null || selectedPrefix.length() < prefix.length()) |
- { |
- selectedItem = subscription; |
- selectedPrefix = prefix; |
- matchCount = 1; |
- } |
- else if (selectedPrefix != null && selectedPrefix.length() == prefix.length()) |
- { |
- matchCount++; |
- |
- // If multiple items have a matching prefix of the |
- // same length select one of the items randomly, |
- // probability should be the same for all items. |
- // So we replace the previous match here with |
- // probability 1/N (N being the number of matches). |
- if (Math.random() * matchCount < 1) |
- { |
- selectedItem = subscription; |
- selectedPrefix = prefix; |
- } |
- } |
- } |
- } |
- return selectedItem; |
- } |
- |
- /** |
- * Verifies that subscriptions are loaded and returns flag of subscription |
- * presence. |
- * |
- * @return true if at least one subscription is present and downloaded |
- */ |
- public boolean verifySubscriptions() |
- { |
- Future<Boolean> future = js.submit(new Callable<Boolean>() |
- { |
- @Override |
- public Boolean call() throws Exception |
- { |
- Boolean result = (Boolean) js.evaluate("verifySubscriptions()"); |
- return result; |
- } |
- }); |
- try |
- { |
- return future.get().booleanValue(); |
- } |
- catch (InterruptedException e) |
- { |
- // TODO Auto-generated catch block |
- Log.e(TAG, e.getMessage(), e); |
- } |
- catch (ExecutionException e) |
- { |
- // TODO Auto-generated catch block |
- Log.e(TAG, e.getMessage(), e); |
- } |
- return false; |
+ abpEngine.actualizeSubscriptionStatus(url); |
} |
/** |
@@ -429,60 +277,12 @@ |
* |
* @return ready to use HTML element with CSS selectors |
Wladimir Palant
2013/09/12 11:31:14
This comment doesn't seem to match the actual retu
|
*/ |
- public String getSelectorsForDomain(final String domain) |
+ public String[] getSelectorsForDomain(final String domain) |
{ |
if (!filteringEnabled) |
return null; |
- Future<String> future = js.submit(new Callable<String>() |
- { |
- @Override |
- public String call() throws Exception |
- { |
- String result = (String) js.evaluate("ElemHide.getSelectorsForDomain('" + domain + "')"); |
- return result; |
- } |
- }); |
- try |
- { |
- return future.get(); |
- } |
- catch (InterruptedException e) |
- { |
- // TODO Auto-generated catch block |
- Log.e(TAG, e.getMessage(), e); |
- } |
- catch (ExecutionException e) |
- { |
- // TODO Auto-generated catch block |
- Log.e(TAG, e.getMessage(), e); |
- } |
- return null; |
- } |
- |
- private class MatchesCallable implements Callable<Boolean> |
- { |
- private String url; |
- private String query; |
- private String reqHost; |
- private String refHost; |
- private String accept; |
- |
- MatchesCallable(String url, String query, String reqHost, String refHost, String accept) |
- { |
- this.url = StringEscapeUtils.escapeJavaScript(url); |
- this.query = StringEscapeUtils.escapeJavaScript(query); |
- this.reqHost = reqHost != null ? StringEscapeUtils.escapeJavaScript(reqHost) : ""; |
- this.refHost = refHost != null ? StringEscapeUtils.escapeJavaScript(refHost) : ""; |
- this.accept = accept != null ? StringEscapeUtils.escapeJavaScript(accept) : ""; |
- } |
- |
- @Override |
- public Boolean call() throws Exception |
- { |
- Boolean result = (Boolean) js.evaluate("matchesAny('" + url + "', '" + query + "', '" + reqHost + "', '" + refHost + "', '" + accept + "');"); |
- return result; |
- } |
+ return abpEngine.getSelectorsForDomain(domain); |
} |
/** |
@@ -492,25 +292,46 @@ |
* Request URL |
* @param query |
* Request query string |
- * @param reqHost |
- * Request host |
- * @param refHost |
+ * @param referrer |
* Request referrer header |
* @param accept |
* Request accept header |
* @return true if matched filter was found |
* @throws Exception |
*/ |
- public boolean matches(String url, String query, String reqHost, String refHost, String accept) throws Exception |
+ public boolean matches(String url, String query, String referrer, String accept) |
{ |
if (!filteringEnabled) |
return false; |
+ |
+ String contentType = null; |
- Callable<Boolean> callable = new MatchesCallable(url, query, reqHost, refHost, accept); |
- Future<Boolean> future = js.submit(callable); |
- boolean matches = future.get().booleanValue(); |
- sendBroadcast(new Intent(BROADCAST_FILTER_MATCHES).putExtra("url", url).putExtra("matches", matches)); |
- return matches; |
+ if (accept != null) |
+ { |
+ if (accept.contains("text/css")) |
+ contentType = "STYLESHEET"; |
+ else if (accept.contains("image/*")) |
+ contentType = "IMAGE"; |
+ } |
+ |
+ if (contentType == null) |
+ { |
+ if (RE_JS.matcher(url).matches()) |
+ contentType = "SCRIPT"; |
+ else if (RE_CSS.matcher(url).matches()) |
+ contentType = "STYLESHEET"; |
+ else if (RE_IMAGE.matcher(url).matches()) |
+ contentType = "IMAGE"; |
+ else if (RE_FONT.matcher(url).matches()) |
+ contentType = "FONT"; |
+ } |
+ if (contentType == null) |
+ contentType = "OTHER"; |
+ |
+ if (!"".equals(query)) |
+ url = url + "?" + query; |
+ |
+ return abpEngine.matches(url, contentType, referrer); |
} |
/** |
@@ -531,65 +352,21 @@ |
} |
/** |
- * Notifies JS code that application entered interactive mode. |
- */ |
- public void startInteractive() |
- { |
- js.execute(new Runnable() |
- { |
- @Override |
- public void run() |
- { |
- js.evaluate("startInteractive()"); |
- } |
- }); |
- interactive = true; |
- } |
- |
- /** |
- * Notifies JS code that application quit interactive mode. |
- */ |
- public void stopInteractive() |
- { |
- // onStop is sometimes called without prior calling onStart |
- // by Android system |
- if (js == null) |
- return; |
- |
- js.execute(new Runnable() |
- { |
- @Override |
- public void run() |
- { |
- js.evaluate("stopInteractive()"); |
- } |
- }); |
- interactive = false; |
- } |
- |
- /** |
- * Returns prefixes that match current user locale. |
- */ |
- public String checkLocalePrefixMatch(String[] prefixes) |
- { |
- if (prefixes == null || prefixes.length == 0) |
- return null; |
- |
- String locale = Locale.getDefault().toString().toLowerCase(); |
- |
- for (int i = 0; i < prefixes.length; i++) |
- if (locale.startsWith(prefixes[i].toLowerCase())) |
- return prefixes[i]; |
- |
- return null; |
- } |
- |
- /** |
- * Starts JS engine. It also initiates subscription refresh if it is enabled |
+ * Starts ABP engine. It also initiates subscription refresh if it is enabled |
* in user settings. |
*/ |
public void startEngine() |
{ |
+ if (abpEngine == null) |
+ { |
+ File basePath = getFilesDir(); |
+// jsEngine.put("_locale", Locale.getDefault().toString()); |
+// jsEngine.put("_datapath", getFilesDir().getAbsolutePath()); |
+// jsEngine.put("_separator", File.separator); |
+// jsEngine.put("_version", getVersion()); |
Wladimir Palant
2013/09/12 11:31:14
I guess you intend to remove that code or replace
|
+ abpEngine = new ABPEngine(this, basePath.getAbsolutePath()); |
+ } |
+ /* |
if (js == null) |
{ |
Log.i(TAG, "startEngine"); |
@@ -602,33 +379,22 @@ |
// Refresh if user selected refresh on each start |
if (refresh == 1 && (!wifionly || isWiFiConnected(this))) |
{ |
- refreshSubscription(); |
+ refreshSubscriptions(); |
} |
} |
+ */ |
Wladimir Palant
2013/09/12 11:31:14
I guess you intend to remove that code?
|
} |
/** |
- * Stops JS engine. |
- * |
- * @param implicitly |
- * stop even in interactive mode |
+ * Stops ABP engine. |
*/ |
- public void stopEngine(boolean implicitly) |
+ public void stopEngine() |
{ |
- if ((implicitly || !interactive) && js != null) |
+ if (abpEngine != null) |
{ |
+ abpEngine.release(); |
+ abpEngine = null; |
Log.i(TAG, "stopEngine"); |
- js.stopEngine(); |
- try |
- { |
- js.join(); |
- } |
- catch (InterruptedException e) |
- { |
- Log.e(TAG, e.getMessage(), e); |
- } |
- Log.i(TAG, "Engine stopped"); |
- js = null; |
} |
} |
@@ -712,442 +478,4 @@ |
// Initiate update check |
scheduleUpdater(0); |
} |
- |
- /** |
- * Handler for showing toast messages from JS code. |
- */ |
- private static final Handler messageHandler = new Handler() |
- { |
- public void handleMessage(Message msg) |
- { |
- if (msg.what == MSG_TOAST) |
- { |
- Toast.makeText(AdblockPlus.getApplication(), msg.getData().getString("message"), Toast.LENGTH_LONG).show(); |
- } |
- } |
- }; |
- |
- /** |
- * JS execution thread. |
- */ |
- private final class JSThread extends Thread |
- { |
- private JSEngine jsEngine; |
- private volatile boolean run = true; |
- private Context context; |
- private final LinkedList<Runnable> queue = new LinkedList<Runnable>(); |
- private long delay = -1; |
- |
- JSThread(Context context) |
- { |
- this.context = context; |
- } |
- |
- // JS helper |
- @SuppressWarnings("unused") |
- public String readJSFile(String name) |
- { |
- String result = ""; |
- AssetManager assetManager = getAssets(); |
- try |
- { |
- InputStreamReader reader = new InputStreamReader(assetManager.open("js" + File.separator + name)); |
- final char[] buffer = new char[0x10000]; |
- StringBuilder out = new StringBuilder(); |
- int read; |
- do |
- { |
- read = reader.read(buffer, 0, buffer.length); |
- if (read > 0) |
- out.append(buffer, 0, read); |
- } |
- while (read >= 0); |
- result = out.toString(); |
- } |
- catch (IOException e) |
- { |
- Log.e(TAG, e.getMessage(), e); |
- } |
- return result; |
- } |
- |
- // JS helper |
- public FileInputStream getInputStream(String path) |
- { |
- Log.d(TAG, path); |
- File f = new File(path); |
- try |
- { |
- return openFileInput(f.getName()); |
- } |
- catch (FileNotFoundException e) |
- { |
- Log.e(TAG, e.getMessage(), e); |
- } |
- return null; |
- } |
- |
- // JS helper |
- public FileOutputStream getOutputStream(String path) |
- { |
- Log.d(TAG, path); |
- File f = new File(path); |
- try |
- { |
- return openFileOutput(f.getName(), MODE_PRIVATE); |
- } |
- catch (FileNotFoundException e) |
- { |
- Log.e(TAG, e.getMessage(), e); |
- } |
- return null; |
- } |
- |
- // JS helper |
- public String getVersion() |
- { |
- String versionName = null; |
- try |
- { |
- versionName = getPackageManager().getPackageInfo(getPackageName(), 0).versionName; |
- } |
- catch (NameNotFoundException ex) |
- { |
- versionName = "n/a"; |
- } |
- return versionName; |
- } |
- |
- // JS helper |
- @SuppressWarnings("unused") |
- public boolean canAutoupdate() |
- { |
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); |
- final int refresh = Integer.valueOf(prefs.getString(getString(R.string.pref_refresh), Integer.toString(context.getResources().getInteger(R.integer.def_refresh)))); |
- final boolean wifionly = prefs.getBoolean(getString(R.string.pref_wifirefresh), getResources().getBoolean(R.bool.def_wifirefresh)); |
- return refresh == 2 && (!wifionly || isWiFiConnected(context)); |
- } |
- |
- // JS helper |
- @SuppressWarnings("unused") |
- public void httpSend(final String method, final String url, final String[][] headers, final boolean async, final long callback) |
- { |
- Log.d(TAG, "httpSend('" + method + "', '" + url + "')"); |
- messageHandler.post(new Runnable() |
- { |
- @Override |
- public void run() |
- { |
- try |
- { |
- Task task = new Task(); |
- task.callback = callback; |
- task.connection = (HttpURLConnection) new URL(url).openConnection(); |
- task.connection.setRequestMethod(method); |
- for (int i = 0; i < headers.length; i++) |
- { |
- task.connection.setRequestProperty(headers[i][0], headers[i][1]); |
- } |
- DownloadTask downloadTask = new DownloadTask(context); |
- downloadTask.execute(task); |
- if (!async) |
- { |
- downloadTask.get(); |
- } |
- } |
- catch (Exception e) |
- { |
- Log.e(TAG, e.getMessage(), e); |
- js.callback(callback, null); |
- } |
- } |
- }); |
- } |
- |
- // JS helper |
- @SuppressWarnings("unused") |
- public void setStatus(String text, long time) |
- { |
- sendBroadcast(new Intent(BROADCAST_SUBSCRIPTION_STATUS).putExtra("text", text).putExtra("time", time)); |
- } |
- |
- // JS helper |
- @SuppressWarnings("unused") |
- public void showToast(String text) |
- { |
- Log.d(TAG, "Toast: " + text); |
- Message msg = messageHandler.obtainMessage(MSG_TOAST); |
- Bundle data = new Bundle(); |
- data.putString("message", text); |
- msg.setData(data); |
- messageHandler.sendMessage(msg); |
- } |
- |
- // JS helper |
- @SuppressWarnings("unused") |
- public void notify(long delay) |
- { |
- if (this.delay < 0 || delay < this.delay) |
- { |
- this.delay = delay; |
- synchronized (queue) |
- { |
- queue.notify(); |
- } |
- } |
- } |
- |
- public Object evaluate(String script) |
- { |
- return jsEngine.evaluate(script); |
- } |
- |
- public void callback(long callback, Object[] params) |
- { |
- jsEngine.callback(callback, params); |
- } |
- |
- public final void stopEngine() |
- { |
- run = false; |
- synchronized (queue) |
- { |
- queue.notify(); |
- } |
- } |
- |
- public void execute(Runnable r) |
- { |
- synchronized (queue) |
- { |
- queue.addLast(r); |
- queue.notify(); |
- } |
- } |
- |
- public <T> Future<T> submit(Callable<T> callable) |
- { |
- FutureTask<T> ftask = new FutureTask<T>(callable); |
- execute(ftask); |
- return ftask; |
- } |
- |
- @Override |
- public final void run() |
- { |
- if (Thread.currentThread().getName().startsWith("Thread-")) |
- { |
- Thread.currentThread().setName("javascript"); |
- } |
- |
- jsEngine = new JSEngine(this); |
- |
- jsEngine.put("_locale", Locale.getDefault().toString()); |
- jsEngine.put("_datapath", getFilesDir().getAbsolutePath()); |
- jsEngine.put("_separator", File.separator); |
- jsEngine.put("_version", getVersion()); |
- |
- try |
- { |
- jsEngine.evaluate("Android.load(\"start.js\");"); |
- } |
- catch (Exception e) |
- { |
- Log.e(TAG, e.getMessage(), e); |
- } |
- |
- while (run) |
- { |
- try |
- { |
- Runnable r = null; |
- synchronized (queue) |
- { |
- r = queue.poll(); |
- } |
- if (r != null) |
- { |
- r.run(); |
- } |
- else if (delay > 0) |
- { |
- long t = SystemClock.uptimeMillis(); |
- synchronized (queue) |
- { |
- try |
- { |
- queue.wait(delay); |
- } |
- catch (InterruptedException e) |
- { |
- } |
- } |
- delay -= SystemClock.uptimeMillis() - t; |
- } |
- else if (delay <= 0) |
- { |
- delay = jsEngine.runCallbacks(); |
- } |
- else |
- { |
- synchronized (queue) |
- { |
- try |
- { |
- queue.wait(); |
- } |
- catch (InterruptedException e) |
- { |
- Log.e(TAG, e.getMessage(), e); |
- } |
- } |
- } |
- } |
- catch (Exception e) |
- { |
- Log.e(TAG, e.getMessage(), e); |
- } |
- } |
- |
- jsEngine.release(); |
- } |
- } |
- |
- /** |
- * Helper class for XMLHttpRequest implementation. |
- */ |
- private class Task |
- { |
- HttpURLConnection connection; |
- long callback; |
- } |
- |
- /** |
- * Helper class for XMLHttpRequest implementation. |
- */ |
- private class Result |
- { |
- long callback; |
- int code; |
- String message; |
- String data; |
- Map<String, List<String>> headers; |
- } |
- |
- /** |
- * Helper class for XMLHttpRequest implementation. |
- */ |
- private class DownloadTask extends AsyncTask<Task, Integer, Result> |
- { |
- public DownloadTask(Context context) |
- { |
- } |
- |
- @Override |
- protected void onPreExecute() |
- { |
- } |
- |
- @Override |
- protected void onPostExecute(Result result) |
- { |
- if (result != null) |
- { |
- final long callback = result.callback; |
- final Object[] params = new Object[4]; |
- |
- String[][] headers = null; |
- if (result.headers != null) |
- { |
- headers = new String[result.headers.size()][2]; |
- int i = 0; |
- for (String header : result.headers.keySet()) |
- { |
- headers[i][0] = header; |
- headers[i][1] = StringUtils.join(result.headers.get(header).toArray(), "; "); |
- i++; |
- } |
- } |
- params[0] = result.code; |
- params[1] = result.message; |
- params[2] = headers; |
- params[3] = result.data; |
- |
- // Do not run callback if engine was stopped |
- if (js == null) |
- return; |
- |
- js.execute(new Runnable() |
- { |
- @Override |
- public void run() |
- { |
- js.callback(callback, params); |
- } |
- |
- }); |
- } |
- } |
- |
- @Override |
- protected void onCancelled() |
- { |
- } |
- |
- @Override |
- protected Result doInBackground(Task... tasks) |
- { |
- Task task = tasks[0]; |
- Result result = new Result(); |
- result.callback = task.callback; |
- try |
- { |
- HttpURLConnection connection = task.connection; |
- connection.connect(); |
- int lenghtOfFile = connection.getContentLength(); |
- Log.d("D", "S: " + lenghtOfFile); |
- |
- result.code = connection.getResponseCode(); |
- result.message = connection.getResponseMessage(); |
- result.headers = connection.getHeaderFields(); |
- |
- // download the file |
- String encoding = connection.getContentEncoding(); |
- if (encoding == null) |
- encoding = "utf-8"; |
- BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding)); |
- |
- final char[] buffer = new char[0x10000]; |
- StringBuilder out = new StringBuilder(); |
- long total = 0; |
- int read; |
- do |
- { |
- read = in.read(buffer, 0, buffer.length); |
- if (read > 0) |
- { |
- out.append(buffer, 0, read); |
- total += read; |
- publishProgress((int) (total * 100. / lenghtOfFile)); |
- } |
- } |
- while (!isCancelled() && read >= 0); |
- result.data = out.toString(); |
- in.close(); |
- } |
- catch (Exception e) |
- { |
- Log.e(TAG, e.getMessage(), e); |
- result.data = ""; |
- result.code = HttpURLConnection.HTTP_INTERNAL_ERROR; |
- result.message = e.toString(); |
- } |
- return result; |
- } |
- |
- protected void onProgressUpdate(Integer... progress) |
- { |
- Log.d("HTTP", "Progress: " + progress[0].intValue()); |
- } |
- } |
} |