Cleaning up image request logic
This commit is contained in:
parent
1d6ef194d1
commit
cca39aa3d2
@ -7,7 +7,6 @@ import acr.browser.lightning.activity.ReadingActivity;
|
||||
import acr.browser.lightning.activity.TabsManager;
|
||||
import acr.browser.lightning.activity.ThemableBrowserActivity;
|
||||
import acr.browser.lightning.activity.ThemableSettingsActivity;
|
||||
import acr.browser.lightning.view.ImageDownloader;
|
||||
import acr.browser.lightning.browser.BrowserPresenter;
|
||||
import acr.browser.lightning.constant.BookmarkPage;
|
||||
import acr.browser.lightning.constant.HistoryPage;
|
||||
@ -77,6 +76,4 @@ public interface AppComponent {
|
||||
|
||||
void inject(SuggestionsAdapter suggestionsAdapter);
|
||||
|
||||
void inject(ImageDownloader imageDownloader);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,139 @@
|
||||
package acr.browser.lightning.favicon;
|
||||
|
||||
import android.app.Application;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import com.anthonycr.bonsai.Completable;
|
||||
import com.anthonycr.bonsai.CompletableAction;
|
||||
import com.anthonycr.bonsai.CompletableSubscriber;
|
||||
import com.anthonycr.bonsai.Single;
|
||||
import com.anthonycr.bonsai.SingleAction;
|
||||
import com.anthonycr.bonsai.SingleSubscriber;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import acr.browser.lightning.app.BrowserApp;
|
||||
import acr.browser.lightning.utils.Utils;
|
||||
|
||||
/**
|
||||
* Reactive model that can fetch favicons
|
||||
* from URLs and also cache them.
|
||||
*/
|
||||
public class FaviconModel {
|
||||
|
||||
private static final String TAG = "FaviconModel";
|
||||
|
||||
private final ImageFetcher mImageFetcher;
|
||||
|
||||
public FaviconModel() {
|
||||
mImageFetcher = new ImageFetcher();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static File createFaviconCacheFile(@NonNull Application app, @NonNull Uri uri) {
|
||||
FaviconUtils.assertUriSafe(uri);
|
||||
|
||||
String hash = String.valueOf(uri.getHost().hashCode());
|
||||
|
||||
return new File(app.getCacheDir(), hash + ".png");
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
public Single<Bitmap> faviconForUrl(@NonNull final String url,
|
||||
@NonNull final Bitmap defaultFavicon,
|
||||
final boolean allowGoogleService) {
|
||||
return Single.create(new SingleAction<Bitmap>() {
|
||||
@Override
|
||||
public void onSubscribe(@NonNull SingleSubscriber<Bitmap> subscriber) {
|
||||
Uri uri = FaviconUtils.safeUri(url);
|
||||
|
||||
if (uri == null) {
|
||||
|
||||
Bitmap newFavicon = Utils.padFavicon(defaultFavicon);
|
||||
|
||||
subscriber.onItem(newFavicon);
|
||||
subscriber.onComplete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Application app = BrowserApp.getApplication();
|
||||
|
||||
File faviconCacheFile = createFaviconCacheFile(app, uri);
|
||||
|
||||
Bitmap favicon = null;
|
||||
|
||||
if (faviconCacheFile.exists()) {
|
||||
favicon = mImageFetcher.retrieveFaviconFromCache(faviconCacheFile);
|
||||
}
|
||||
|
||||
if (favicon == null) {
|
||||
favicon = mImageFetcher.retrieveBitmapFromDomain(uri);
|
||||
} else {
|
||||
Bitmap newFavicon = Utils.padFavicon(favicon);
|
||||
|
||||
subscriber.onItem(newFavicon);
|
||||
subscriber.onComplete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (favicon == null && allowGoogleService) {
|
||||
favicon = mImageFetcher.retrieveBitmapFromGoogle(uri);
|
||||
}
|
||||
|
||||
if (favicon != null) {
|
||||
cacheFaviconForUrl(favicon, url).subscribe();
|
||||
}
|
||||
|
||||
if (favicon == null) {
|
||||
favicon = defaultFavicon;
|
||||
}
|
||||
|
||||
Bitmap newFavicon = Utils.padFavicon(favicon);
|
||||
|
||||
subscriber.onItem(newFavicon);
|
||||
subscriber.onComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Completable cacheFaviconForUrl(@NonNull final Bitmap favicon,
|
||||
@NonNull final String url) {
|
||||
return Completable.create(new CompletableAction() {
|
||||
@Override
|
||||
public void onSubscribe(@NonNull CompletableSubscriber subscriber) {
|
||||
Uri uri = FaviconUtils.safeUri(url);
|
||||
|
||||
if (uri == null) {
|
||||
subscriber.onComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
Application app = BrowserApp.getApplication();
|
||||
|
||||
Log.d(TAG, "Caching icon for " + uri.getHost());
|
||||
FileOutputStream fos = null;
|
||||
|
||||
try {
|
||||
File image = createFaviconCacheFile(app, uri);
|
||||
fos = new FileOutputStream(image);
|
||||
favicon.compress(Bitmap.CompressFormat.PNG, 100, fos);
|
||||
fos.flush();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Unable to cache favicon", e);
|
||||
} finally {
|
||||
Utils.close(fos);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package acr.browser.lightning.favicon;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* Created by anthonycr on 4/13/17.
|
||||
*/
|
||||
|
||||
class FaviconUtils {
|
||||
@Nullable
|
||||
static Uri safeUri(@NonNull String url) {
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Uri uri = Uri.parse(url);
|
||||
|
||||
if (uri.getHost() == null || uri.getScheme() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
static void assertUriSafe(@Nullable Uri uri) {
|
||||
if (uri == null || TextUtils.isEmpty(uri.getScheme()) || TextUtils.isEmpty(uri.getHost())) {
|
||||
throw new RuntimeException("Unsafe uri provided");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package acr.browser.lightning.favicon;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import acr.browser.lightning.utils.Utils;
|
||||
|
||||
/**
|
||||
* An image fetcher that creates image
|
||||
* loading requests on demand.
|
||||
*/
|
||||
class ImageFetcher {
|
||||
|
||||
private static final String TAG = "ImageFetcher";
|
||||
|
||||
@NonNull private final BitmapFactory.Options mLoaderOptions = new BitmapFactory.Options();
|
||||
|
||||
ImageFetcher() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Bitmap retrieveFaviconFromCache(@NonNull File cacheFile) {
|
||||
return BitmapFactory.decodeFile(cacheFile.getPath(), mLoaderOptions);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Bitmap retrieveBitmapFromDomain(@NonNull Uri uri) {
|
||||
FaviconUtils.assertUriSafe(uri);
|
||||
|
||||
String faviconUrlGuess = uri.getScheme() + "://" + uri.getHost() + "/favicon.ico";
|
||||
|
||||
return retrieveBitmapFromUrl(faviconUrlGuess);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Bitmap retrieveBitmapFromGoogle(@NonNull Uri uri) {
|
||||
FaviconUtils.assertUriSafe(uri);
|
||||
|
||||
String googleFaviconUrl = "https://www.google.com/s2/favicons?domain_url=" + uri.toString();
|
||||
|
||||
return retrieveBitmapFromUrl(googleFaviconUrl);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private Bitmap retrieveBitmapFromUrl(@NonNull String url) {
|
||||
InputStream in = null;
|
||||
Bitmap icon = null;
|
||||
|
||||
try {
|
||||
final URL urlDownload = new URL(url);
|
||||
final HttpURLConnection connection = (HttpURLConnection) urlDownload.openConnection();
|
||||
connection.setDoInput(true);
|
||||
connection.setConnectTimeout(1000);
|
||||
connection.setReadTimeout(1000);
|
||||
connection.connect();
|
||||
in = connection.getInputStream();
|
||||
|
||||
if (in != null) {
|
||||
icon = BitmapFactory.decodeStream(in, null, mLoaderOptions);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
Log.d(TAG, "Could not download icon from: " + url);
|
||||
} finally {
|
||||
Utils.close(in);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -45,7 +45,7 @@ import acr.browser.lightning.R;
|
||||
import acr.browser.lightning.activity.ReadingActivity;
|
||||
import acr.browser.lightning.activity.TabsManager;
|
||||
import acr.browser.lightning.app.BrowserApp;
|
||||
import acr.browser.lightning.view.ImageDownloader;
|
||||
import acr.browser.lightning.favicon.FaviconModel;
|
||||
import acr.browser.lightning.browser.BookmarksView;
|
||||
import acr.browser.lightning.bus.BookmarkEvents;
|
||||
import acr.browser.lightning.constant.Constants;
|
||||
@ -74,7 +74,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
|
||||
|
||||
@Inject PreferenceManager mPreferenceManager;
|
||||
|
||||
private ImageDownloader mImageDownloader;
|
||||
private FaviconModel mFaviconModel;
|
||||
|
||||
private TabsManager mTabsManager;
|
||||
|
||||
@ -128,7 +128,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
|
||||
mIconColor = darkTheme ? ThemeUtils.getIconDarkThemeColor(context) :
|
||||
ThemeUtils.getIconLightThemeColor(context);
|
||||
|
||||
mImageDownloader = new ImageDownloader(mWebpageBitmap);
|
||||
mFaviconModel = new FaviconModel();
|
||||
}
|
||||
|
||||
private TabsManager getTabsManager() {
|
||||
@ -228,7 +228,7 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
|
||||
mIconColor = darkTheme ? ThemeUtils.getIconDarkThemeColor(activity) :
|
||||
ThemeUtils.getIconLightThemeColor(activity);
|
||||
|
||||
mImageDownloader = new ImageDownloader(mWebpageBitmap);
|
||||
mFaviconModel = new FaviconModel();
|
||||
}
|
||||
|
||||
private void updateBookmarkIndicator(final String url) {
|
||||
@ -405,7 +405,8 @@ public class BookmarksFragment extends Fragment implements View.OnClickListener,
|
||||
|
||||
final String url = web.getUrl();
|
||||
final WeakReference<ImageView> imageViewReference = new WeakReference<>(holder.favicon);
|
||||
mImageDownloader.newImageRequest(url)
|
||||
|
||||
mFaviconModel.faviconForUrl(url, mWebpageBitmap, true)
|
||||
.subscribeOn(Schedulers.worker())
|
||||
.observeOn(Schedulers.main())
|
||||
.subscribe(new SingleOnSubscribe<Bitmap>() {
|
||||
|
@ -14,6 +14,7 @@ import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.LinearGradient;
|
||||
@ -74,7 +75,7 @@ public final class Utils {
|
||||
public static void downloadFile(final Activity activity, final PreferenceManager manager, final String url,
|
||||
final String userAgent, final String contentDisposition) {
|
||||
PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(activity, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE}, new PermissionsResultAction() {
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE}, new PermissionsResultAction() {
|
||||
@Override
|
||||
public void onGranted() {
|
||||
String fileName = URLUtil.guessFileName(url, null, null);
|
||||
@ -124,13 +125,13 @@ public final class Utils {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle(title);
|
||||
builder.setMessage(message)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(activity.getResources().getString(R.string.action_ok),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
}
|
||||
});
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(activity.getResources().getString(R.string.action_ok),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
}
|
||||
});
|
||||
AlertDialog alert = builder.create();
|
||||
alert.show();
|
||||
BrowserDialog.setDialogSize(activity, alert);
|
||||
@ -259,7 +260,7 @@ public final class Utils {
|
||||
int padding = Utils.dpToPx(4);
|
||||
|
||||
Bitmap paddedBitmap = Bitmap.createBitmap(bitmap.getWidth() + padding, bitmap.getHeight()
|
||||
+ padding, Bitmap.Config.ARGB_8888);
|
||||
+ padding, Bitmap.Config.ARGB_8888);
|
||||
|
||||
Canvas canvas = new Canvas(paddedBitmap);
|
||||
canvas.drawARGB(0x00, 0x00, 0x00, 0x00); // this represents white color
|
||||
@ -303,10 +304,10 @@ public final class Utils {
|
||||
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
||||
String imageFileName = "JPEG_" + timeStamp + '_';
|
||||
File storageDir = Environment
|
||||
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
||||
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
||||
return File.createTempFile(imageFileName, /* prefix */
|
||||
".jpg", /* suffix */
|
||||
storageDir /* directory */
|
||||
".jpg", /* suffix */
|
||||
storageDir /* directory */
|
||||
);
|
||||
}
|
||||
|
||||
@ -380,9 +381,9 @@ public final class Utils {
|
||||
paint.setDither(true);
|
||||
if (withShader) {
|
||||
paint.setShader(new LinearGradient(0, 0.9f * canvas.getHeight(),
|
||||
0, canvas.getHeight(),
|
||||
color, mixTwoColors(Color.BLACK, color, 0.5f),
|
||||
Shader.TileMode.CLAMP));
|
||||
0, canvas.getHeight(),
|
||||
color, mixTwoColors(Color.BLACK, color, 0.5f),
|
||||
Shader.TileMode.CLAMP));
|
||||
} else {
|
||||
paint.setShader(null);
|
||||
}
|
||||
@ -431,4 +432,27 @@ public final class Utils {
|
||||
Utils.showSnackbar(activity, R.string.message_added_to_homescreen);
|
||||
}
|
||||
|
||||
public static int calculateInSampleSize(@NonNull BitmapFactory.Options options,
|
||||
int reqWidth, int reqHeight) {
|
||||
// Raw height and width of image
|
||||
final int height = options.outHeight;
|
||||
final int width = options.outWidth;
|
||||
int inSampleSize = 1;
|
||||
|
||||
if (height > reqHeight || width > reqWidth) {
|
||||
|
||||
final int halfHeight = height / 2;
|
||||
final int halfWidth = width / 2;
|
||||
|
||||
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
|
||||
// height and width larger than the requested height and width.
|
||||
while ((halfHeight / inSampleSize) >= reqHeight
|
||||
&& (halfWidth / inSampleSize) >= reqWidth) {
|
||||
inSampleSize *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
return inSampleSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
package acr.browser.lightning.view;
|
||||
|
||||
import android.app.Application;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import acr.browser.lightning.constant.Constants;
|
||||
import acr.browser.lightning.utils.Utils;
|
||||
|
||||
class IconCacheTask implements Runnable {
|
||||
private final Uri uri;
|
||||
private final Bitmap icon;
|
||||
private final Application app;
|
||||
|
||||
public IconCacheTask(final Uri uri, final Bitmap icon, final Application app) {
|
||||
this.uri = uri;
|
||||
this.icon = icon;
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
String hash = String.valueOf(uri.getHost().hashCode());
|
||||
Log.d(Constants.TAG, "Caching icon for " + uri.getHost());
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
File image = new File(app.getCacheDir(), hash + ".png");
|
||||
fos = new FileOutputStream(image);
|
||||
icon.compress(Bitmap.CompressFormat.PNG, 100, fos);
|
||||
fos.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
Utils.close(fos);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
package acr.browser.lightning.view;
|
||||
|
||||
import android.app.Application;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.anthonycr.bonsai.Single;
|
||||
import com.anthonycr.bonsai.SingleAction;
|
||||
import com.anthonycr.bonsai.SingleSubscriber;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import acr.browser.lightning.app.BrowserApp;
|
||||
import acr.browser.lightning.constant.Constants;
|
||||
import acr.browser.lightning.utils.Utils;
|
||||
|
||||
/**
|
||||
* An ImageDownloader that creates image
|
||||
* loading requests on demand.
|
||||
*/
|
||||
public class ImageDownloader {
|
||||
|
||||
private static final String TAG = "ImageDownloader";
|
||||
|
||||
@Inject Application mApp;
|
||||
|
||||
@NonNull private final Bitmap mDefaultBitmap;
|
||||
@NonNull private final BitmapFactory.Options mLoaderOptions = new BitmapFactory.Options();
|
||||
|
||||
public ImageDownloader(@NonNull Bitmap defaultBitmap) {
|
||||
BrowserApp.getAppComponent().inject(this);
|
||||
mDefaultBitmap = defaultBitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new image request for the given url.
|
||||
* Emits the bitmap associated with that url, or
|
||||
* the default bitmap if none was found.
|
||||
*
|
||||
* @param url the url for which to retrieve the bitmap.
|
||||
* @return a single that emits the bitmap that was found.
|
||||
*/
|
||||
@NonNull
|
||||
public Single<Bitmap> newImageRequest(@Nullable final String url) {
|
||||
return Single.create(new SingleAction<Bitmap>() {
|
||||
@Override
|
||||
public void onSubscribe(@NonNull SingleSubscriber<Bitmap> subscriber) {
|
||||
Bitmap favicon = retrieveFaviconForUrl(url);
|
||||
|
||||
Bitmap paddedFavicon = Utils.padFavicon(favicon);
|
||||
|
||||
subscriber.onItem(paddedFavicon);
|
||||
subscriber.onComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Bitmap retrieveFaviconForUrl(@Nullable String url) {
|
||||
|
||||
// unique path for each url that is bookmarked.
|
||||
if (url == null) {
|
||||
return mDefaultBitmap;
|
||||
}
|
||||
|
||||
Bitmap icon;
|
||||
File cache = mApp.getCacheDir();
|
||||
Uri uri = Uri.parse(url);
|
||||
|
||||
if (uri.getHost() == null || uri.getScheme() == null || Constants.FILE.startsWith(uri.getScheme())) {
|
||||
return mDefaultBitmap;
|
||||
}
|
||||
|
||||
String hash = String.valueOf(uri.getHost().hashCode());
|
||||
File image = new File(cache, hash + ".png");
|
||||
String urlDisplay = uri.getScheme() + "://" + uri.getHost() + "/favicon.ico";
|
||||
|
||||
if (image.exists()) {
|
||||
// If image exists, pull it from the cache
|
||||
icon = BitmapFactory.decodeFile(image.getPath());
|
||||
} else {
|
||||
// Otherwise, load it from network
|
||||
icon = retrieveBitmapFromUrl(urlDisplay);
|
||||
}
|
||||
|
||||
if (icon == null) {
|
||||
String googleFaviconUrl = "https://www.google.com/s2/favicons?domain_url=" + uri.toString();
|
||||
icon = retrieveBitmapFromUrl(googleFaviconUrl);
|
||||
}
|
||||
|
||||
if (icon == null) {
|
||||
return mDefaultBitmap;
|
||||
} else {
|
||||
cacheBitmap(image, icon);
|
||||
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
||||
private void cacheBitmap(@NonNull File cacheFile, @NonNull Bitmap imageToCache) {
|
||||
FileOutputStream fos = null;
|
||||
|
||||
try {
|
||||
fos = new FileOutputStream(cacheFile);
|
||||
imageToCache.compress(Bitmap.CompressFormat.PNG, 100, fos);
|
||||
fos.flush();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Could not cache icon");
|
||||
} finally {
|
||||
Utils.close(fos);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Bitmap retrieveBitmapFromUrl(@NonNull String url) {
|
||||
InputStream in = null;
|
||||
Bitmap icon = null;
|
||||
|
||||
try {
|
||||
final URL urlDownload = new URL(url);
|
||||
final HttpURLConnection connection = (HttpURLConnection) urlDownload.openConnection();
|
||||
connection.setDoInput(true);
|
||||
connection.setConnectTimeout(1000);
|
||||
connection.setReadTimeout(1000);
|
||||
connection.connect();
|
||||
in = connection.getInputStream();
|
||||
|
||||
if (in != null) {
|
||||
icon = BitmapFactory.decodeStream(in, null, mLoaderOptions);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
Log.d(TAG, "Could not download icon from: " + url);
|
||||
} finally {
|
||||
Utils.close(in);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -2,7 +2,6 @@ package acr.browser.lightning.view;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
@ -19,13 +18,14 @@ import android.webkit.ValueCallback;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.anthonycr.bonsai.Schedulers;
|
||||
import com.anthonycr.grant.PermissionsManager;
|
||||
import com.anthonycr.grant.PermissionsResultAction;
|
||||
|
||||
import acr.browser.lightning.R;
|
||||
import acr.browser.lightning.app.BrowserApp;
|
||||
import acr.browser.lightning.controller.UIController;
|
||||
import acr.browser.lightning.dialog.BrowserDialog;
|
||||
import acr.browser.lightning.favicon.FaviconModel;
|
||||
import acr.browser.lightning.utils.Preconditions;
|
||||
|
||||
class LightningChromeClient extends WebChromeClient {
|
||||
@ -37,6 +37,7 @@ class LightningChromeClient extends WebChromeClient {
|
||||
@NonNull private final Activity mActivity;
|
||||
@NonNull private final LightningView mLightningView;
|
||||
@NonNull private final UIController mUIController;
|
||||
@NonNull private final FaviconModel mFaviconModel;
|
||||
|
||||
LightningChromeClient(@NonNull Activity activity, @NonNull LightningView lightningView) {
|
||||
Preconditions.checkNonNull(activity);
|
||||
@ -44,6 +45,7 @@ class LightningChromeClient extends WebChromeClient {
|
||||
mActivity = activity;
|
||||
mUIController = (UIController) activity;
|
||||
mLightningView = lightningView;
|
||||
mFaviconModel = new FaviconModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -57,7 +59,7 @@ class LightningChromeClient extends WebChromeClient {
|
||||
public void onReceivedIcon(@NonNull WebView view, Bitmap icon) {
|
||||
mLightningView.getTitleInfo().setFavicon(icon);
|
||||
mUIController.tabChanged(mLightningView);
|
||||
cacheFavicon(view.getUrl(), icon, mActivity);
|
||||
cacheFavicon(view.getUrl(), icon);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,13 +67,20 @@ class LightningChromeClient extends WebChromeClient {
|
||||
*
|
||||
* @param icon the icon to cache
|
||||
*/
|
||||
private static void cacheFavicon(@Nullable final String url, @Nullable final Bitmap icon, @NonNull final Context context) {
|
||||
if (icon == null || url == null) return;
|
||||
final Uri uri = Uri.parse(url);
|
||||
private void cacheFavicon(@Nullable final String url, @Nullable final Bitmap icon) {
|
||||
if (icon == null || url == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Uri uri = Uri.parse(url);
|
||||
|
||||
if (uri.getHost() == null) {
|
||||
return;
|
||||
}
|
||||
BrowserApp.getIOThread().execute(new IconCacheTask(uri, icon, BrowserApp.get(context)));
|
||||
|
||||
mFaviconModel.cacheFaviconForUrl(icon, url)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user