Fetch favicons parallel

This commit is contained in:
M66B 2020-07-01 10:49:09 +02:00
parent 674d60243a
commit eefa6dfa6b
1 changed files with 60 additions and 43 deletions

View File

@ -49,17 +49,21 @@ import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.ConnectException; import java.net.ConnectException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL; import java.net.URL;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.mail.Address; import javax.mail.Address;
import javax.mail.internet.InternetAddress; import javax.mail.internet.InternetAddress;
@ -81,9 +85,12 @@ public class ContactInfo {
private static final Map<String, ContactInfo> emailContactInfo = new HashMap<>(); private static final Map<String, ContactInfo> emailContactInfo = new HashMap<>();
private static final Map<String, Avatar> emailGravatar = new HashMap<>(); private static final Map<String, Avatar> emailGravatar = new HashMap<>();
private static final ExecutorService executor = private static final ExecutorService executorLookup =
Helper.getBackgroundExecutor(1, "contact"); Helper.getBackgroundExecutor(1, "contact");
private static final ExecutorService executorFavicon =
Helper.getBackgroundExecutor(0, "favicon");
private static final int GRAVATAR_TIMEOUT = 5 * 1000; // milliseconds private static final int GRAVATAR_TIMEOUT = 5 * 1000; // milliseconds
private static final int FAVICON_CONNECT_TIMEOUT = 5 * 1000; // milliseconds private static final int FAVICON_CONNECT_TIMEOUT = 5 * 1000; // milliseconds
private static final int FAVICON_READ_TIMEOUT = 10 * 1000; // milliseconds private static final int FAVICON_READ_TIMEOUT = 10 * 1000; // milliseconds
@ -133,7 +140,7 @@ public class ContactInfo {
final File dir = new File(context.getCacheDir(), "favicons"); final File dir = new File(context.getCacheDir(), "favicons");
executor.submit(new Runnable() { executorFavicon.submit(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
@ -305,48 +312,53 @@ public class ContactInfo {
else else
info.bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); info.bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
else { else {
URL base = new URL("https://" + domain); final URL base = new URL("https://" + domain);
URL www = new URL("https://www." + domain); final URL www = new URL("https://www." + domain);
List<Future<Bitmap>> futures = new ArrayList<>();
futures.add(executorFavicon.submit(new Callable<Bitmap>() {
@Override
public Bitmap call() throws Exception {
return parseFavicon(base);
}
}));
futures.add(executorFavicon.submit(new Callable<Bitmap>() {
@Override
public Bitmap call() throws Exception {
return parseFavicon(www);
}
}));
futures.add(executorFavicon.submit(new Callable<Bitmap>() {
@Override
public Bitmap call() throws Exception {
return getFavicon(new URL(base, "favicon.ico"));
}
}));
futures.add(executorFavicon.submit(new Callable<Bitmap>() {
@Override
public Bitmap call() throws Exception {
return getFavicon(new URL(www, "favicon.ico"));
}
}));
Throwable ex = null;
for (Future<Bitmap> future : futures)
try { try {
info.bitmap = parseFavicon(base); info.bitmap = future.get();
} catch (IOException ex) { } catch (ExecutionException exex) {
if (ex instanceof SocketTimeoutException) ex = exex.getCause();
throw ex; } catch (Throwable exex) {
Log.i("Favicon ex=" + ex.getClass().getName() + " " + ex.getMessage()); ex = exex;
} }
if (info.bitmap == null) if (info.bitmap == null)
try {
info.bitmap = parseFavicon(www);
} catch (IOException ex) {
if (ex instanceof SocketTimeoutException)
throw ex; throw ex;
Log.i("Favicon ex=" + ex.getClass().getName() + " " + ex.getMessage());
}
if (info.bitmap == null)
try {
info.bitmap = getFavicon(new URL(base, "favicon.ico"));
} catch (IOException ex) {
if (ex instanceof SocketTimeoutException)
throw ex;
Log.i("Favicon ex=" + ex.getClass().getName() + " " + ex.getMessage());
}
if (info.bitmap == null)
try {
info.bitmap = getFavicon(new URL(www, "favicon.ico"));
} catch (IOException ex) {
if (ex instanceof SocketTimeoutException)
throw ex;
Log.i("Favicon ex=" + ex.getClass().getName() + " " + ex.getMessage());
}
// Add to cache // Add to cache
if (info.bitmap == null)
throw new FileNotFoundException("decode");
else
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) { try (OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) {
info.bitmap.compress(Bitmap.CompressFormat.PNG, 90, os); info.bitmap.compress(Bitmap.CompressFormat.PNG, 90, os);
} }
@ -440,6 +452,7 @@ public class ContactInfo {
return null; return null;
} }
@NonNull
private static Bitmap getFavicon(URL url) throws IOException { private static Bitmap getFavicon(URL url) throws IOException {
Log.i("GET favicon " + url); Log.i("GET favicon " + url);
@ -451,7 +464,11 @@ public class ContactInfo {
connection.connect(); connection.connect();
try { try {
return BitmapFactory.decodeStream(connection.getInputStream()); Bitmap bitmap = BitmapFactory.decodeStream(connection.getInputStream());
if (bitmap == null)
throw new FileNotFoundException("decodeStream");
else
return bitmap;
} finally { } finally {
connection.disconnect(); connection.disconnect();
} }
@ -481,7 +498,7 @@ public class ContactInfo {
@Override @Override
public void onChange(boolean selfChange, Uri uri) { public void onChange(boolean selfChange, Uri uri) {
Log.i("Contact changed uri=" + uri); Log.i("Contact changed uri=" + uri);
executor.submit(new Runnable() { executorLookup.submit(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
@ -494,7 +511,7 @@ public class ContactInfo {
} }
}; };
executor.submit(new Runnable() { executorLookup.submit(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {