|
|
@ -1,69 +1,91 @@ |
|
|
|
package acr.browser.lightning.async; |
|
|
|
package acr.browser.lightning.view; |
|
|
|
|
|
|
|
|
|
|
|
import android.app.Application; |
|
|
|
import android.app.Application; |
|
|
|
import android.graphics.Bitmap; |
|
|
|
import android.graphics.Bitmap; |
|
|
|
import android.graphics.BitmapFactory; |
|
|
|
import android.graphics.BitmapFactory; |
|
|
|
import android.net.Uri; |
|
|
|
import android.net.Uri; |
|
|
|
import android.os.AsyncTask; |
|
|
|
|
|
|
|
import android.support.annotation.NonNull; |
|
|
|
import android.support.annotation.NonNull; |
|
|
|
|
|
|
|
import android.support.annotation.Nullable; |
|
|
|
import android.util.Log; |
|
|
|
import android.util.Log; |
|
|
|
import android.widget.ImageView; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.anthonycr.bonsai.Schedulers; |
|
|
|
import com.anthonycr.bonsai.Single; |
|
|
|
|
|
|
|
import com.anthonycr.bonsai.SingleAction; |
|
|
|
|
|
|
|
import com.anthonycr.bonsai.SingleSubscriber; |
|
|
|
|
|
|
|
|
|
|
|
import java.io.File; |
|
|
|
import java.io.File; |
|
|
|
import java.io.FileOutputStream; |
|
|
|
import java.io.FileOutputStream; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.lang.ref.WeakReference; |
|
|
|
|
|
|
|
import java.net.HttpURLConnection; |
|
|
|
import java.net.HttpURLConnection; |
|
|
|
import java.net.URL; |
|
|
|
import java.net.URL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import javax.inject.Inject; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import acr.browser.lightning.app.BrowserApp; |
|
|
|
import acr.browser.lightning.constant.Constants; |
|
|
|
import acr.browser.lightning.constant.Constants; |
|
|
|
import acr.browser.lightning.database.HistoryItem; |
|
|
|
|
|
|
|
import acr.browser.lightning.utils.Utils; |
|
|
|
import acr.browser.lightning.utils.Utils; |
|
|
|
|
|
|
|
|
|
|
|
public class ImageDownloadTask extends AsyncTask<Void, Void, Bitmap> { |
|
|
|
/** |
|
|
|
|
|
|
|
* An ImageDownloader that creates image |
|
|
|
|
|
|
|
* loading requests on demand. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public class ImageDownloader { |
|
|
|
|
|
|
|
|
|
|
|
private static final String TAG = ImageDownloadTask.class.getSimpleName(); |
|
|
|
private static final String TAG = "ImageDownloader"; |
|
|
|
@NonNull private final WeakReference<ImageView> mFaviconImage; |
|
|
|
|
|
|
|
@NonNull private final Application mContext; |
|
|
|
|
|
|
|
@NonNull private final HistoryItem mWeb; |
|
|
|
|
|
|
|
private final String mUrl; |
|
|
|
|
|
|
|
@NonNull private final Bitmap mDefaultBitmap; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public ImageDownloadTask(@NonNull ImageView bmImage, |
|
|
|
@Inject Application mApp; |
|
|
|
@NonNull HistoryItem web, |
|
|
|
|
|
|
|
@NonNull Bitmap defaultBitmap, |
|
|
|
@NonNull private Bitmap mDefaultBitmap; |
|
|
|
@NonNull Application context) { |
|
|
|
|
|
|
|
// Set a tag on the ImageView so we know if the view
|
|
|
|
public ImageDownloader(@NonNull Bitmap defaultBitmap) { |
|
|
|
// has gone out of scope and should not be used
|
|
|
|
mDefaultBitmap = defaultBitmap; |
|
|
|
bmImage.setTag(web.getUrl().hashCode()); |
|
|
|
BrowserApp.getAppComponent().inject(this); |
|
|
|
this.mFaviconImage = new WeakReference<>(bmImage); |
|
|
|
|
|
|
|
this.mWeb = web; |
|
|
|
|
|
|
|
this.mUrl = web.getUrl(); |
|
|
|
|
|
|
|
this.mDefaultBitmap = defaultBitmap; |
|
|
|
|
|
|
|
this.mContext = context; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* 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 |
|
|
|
@NonNull |
|
|
|
|
|
|
|
public Single<Bitmap> newImageRequest(@Nullable final String url) { |
|
|
|
|
|
|
|
return Single.create(new SingleAction<Bitmap>() { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected Bitmap doInBackground(Void... params) { |
|
|
|
public void onSubscribe(@NonNull SingleSubscriber<Bitmap> subscriber) { |
|
|
|
Bitmap mIcon = null; |
|
|
|
Bitmap favicon = retrieveBitmap(mApp, mDefaultBitmap, url); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Bitmap paddedFavicon = Utils.padFavicon(favicon); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
subscriber.onItem(paddedFavicon); |
|
|
|
|
|
|
|
subscriber.onComplete(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@NonNull |
|
|
|
|
|
|
|
private static Bitmap retrieveBitmap(@NonNull Application app, |
|
|
|
|
|
|
|
@NonNull Bitmap defaultBitmap, |
|
|
|
|
|
|
|
@Nullable String url) { |
|
|
|
|
|
|
|
|
|
|
|
// unique path for each url that is bookmarked.
|
|
|
|
// unique path for each url that is bookmarked.
|
|
|
|
if (mUrl == null) { |
|
|
|
if (url == null) { |
|
|
|
return mDefaultBitmap; |
|
|
|
return defaultBitmap; |
|
|
|
} |
|
|
|
} |
|
|
|
File cache = mContext.getCacheDir(); |
|
|
|
|
|
|
|
final Uri uri = Uri.parse(mUrl); |
|
|
|
Bitmap icon = null; |
|
|
|
if (uri.getHost() == null || uri.getScheme() == null) { |
|
|
|
File cache = app.getCacheDir(); |
|
|
|
return mDefaultBitmap; |
|
|
|
final Uri uri = Uri.parse(url); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (uri.getHost() == null || uri.getScheme() == null || Constants.FILE.startsWith(uri.getScheme())) { |
|
|
|
|
|
|
|
return defaultBitmap; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
final String hash = String.valueOf(uri.getHost().hashCode()); |
|
|
|
final String hash = String.valueOf(uri.getHost().hashCode()); |
|
|
|
final File image = new File(cache, hash + ".png"); |
|
|
|
final File image = new File(cache, hash + ".png"); |
|
|
|
final String urlDisplay = uri.getScheme() + "://" + uri.getHost() + "/favicon.ico"; |
|
|
|
final String urlDisplay = uri.getScheme() + "://" + uri.getHost() + "/favicon.ico"; |
|
|
|
if (Constants.FILE.startsWith(uri.getScheme())) { |
|
|
|
|
|
|
|
return mDefaultBitmap; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// checks to see if the image exists
|
|
|
|
// checks to see if the image exists
|
|
|
|
if (!image.exists()) { |
|
|
|
if (!image.exists()) { |
|
|
|
FileOutputStream fos = null; |
|
|
|
FileOutputStream fos = null; |
|
|
@ -79,12 +101,12 @@ public class ImageDownloadTask extends AsyncTask<Void, Void, Bitmap> { |
|
|
|
in = connection.getInputStream(); |
|
|
|
in = connection.getInputStream(); |
|
|
|
|
|
|
|
|
|
|
|
if (in != null) { |
|
|
|
if (in != null) { |
|
|
|
mIcon = BitmapFactory.decodeStream(in); |
|
|
|
icon = BitmapFactory.decodeStream(in); |
|
|
|
} |
|
|
|
} |
|
|
|
// ...and cache it
|
|
|
|
// ...and cache it
|
|
|
|
if (mIcon != null) { |
|
|
|
if (icon != null) { |
|
|
|
fos = new FileOutputStream(image); |
|
|
|
fos = new FileOutputStream(image); |
|
|
|
mIcon.compress(Bitmap.CompressFormat.PNG, 100, fos); |
|
|
|
icon.compress(Bitmap.CompressFormat.PNG, 100, fos); |
|
|
|
fos.flush(); |
|
|
|
fos.flush(); |
|
|
|
Log.d(Constants.TAG, "Downloaded: " + urlDisplay); |
|
|
|
Log.d(Constants.TAG, "Downloaded: " + urlDisplay); |
|
|
|
} |
|
|
|
} |
|
|
@ -97,9 +119,10 @@ public class ImageDownloadTask extends AsyncTask<Void, Void, Bitmap> { |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// if it exists, retrieve it from the cache
|
|
|
|
// if it exists, retrieve it from the cache
|
|
|
|
mIcon = BitmapFactory.decodeFile(image.getPath()); |
|
|
|
icon = BitmapFactory.decodeFile(image.getPath()); |
|
|
|
} |
|
|
|
} |
|
|
|
if (mIcon == null) { |
|
|
|
|
|
|
|
|
|
|
|
if (icon == null) { |
|
|
|
InputStream in = null; |
|
|
|
InputStream in = null; |
|
|
|
FileOutputStream fos = null; |
|
|
|
FileOutputStream fos = null; |
|
|
|
try { |
|
|
|
try { |
|
|
@ -113,12 +136,12 @@ public class ImageDownloadTask extends AsyncTask<Void, Void, Bitmap> { |
|
|
|
in = connection.getInputStream(); |
|
|
|
in = connection.getInputStream(); |
|
|
|
|
|
|
|
|
|
|
|
if (in != null) { |
|
|
|
if (in != null) { |
|
|
|
mIcon = BitmapFactory.decodeStream(in); |
|
|
|
icon = BitmapFactory.decodeStream(in); |
|
|
|
} |
|
|
|
} |
|
|
|
// ...and cache it
|
|
|
|
// ...and cache it
|
|
|
|
if (mIcon != null) { |
|
|
|
if (icon != null) { |
|
|
|
fos = new FileOutputStream(image); |
|
|
|
fos = new FileOutputStream(image); |
|
|
|
mIcon.compress(Bitmap.CompressFormat.PNG, 100, fos); |
|
|
|
icon.compress(Bitmap.CompressFormat.PNG, 100, fos); |
|
|
|
fos.flush(); |
|
|
|
fos.flush(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -129,28 +152,11 @@ public class ImageDownloadTask extends AsyncTask<Void, Void, Bitmap> { |
|
|
|
Utils.close(fos); |
|
|
|
Utils.close(fos); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (mIcon == null) { |
|
|
|
|
|
|
|
return mDefaultBitmap; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return mIcon; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
if (icon == null) { |
|
|
|
protected void onPostExecute(Bitmap bitmap) { |
|
|
|
return defaultBitmap; |
|
|
|
super.onPostExecute(bitmap); |
|
|
|
} else { |
|
|
|
AsyncExecutor.getInstance().notifyThreadFinish(); |
|
|
|
return icon; |
|
|
|
final Bitmap fav = Utils.padFavicon(bitmap); |
|
|
|
|
|
|
|
final ImageView view = mFaviconImage.get(); |
|
|
|
|
|
|
|
if (view != null && view.getTag().equals(mWeb.getUrl().hashCode())) { |
|
|
|
|
|
|
|
Schedulers.main().execute(new Runnable() { |
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public void run() { |
|
|
|
|
|
|
|
view.setImageBitmap(fav); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
mWeb.setBitmap(fav); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |