2014-08-22 16:24:33 +02:00
|
|
|
/*
|
|
|
|
* This is the source code of Telegram for Android v. 1.7.x.
|
|
|
|
* It is licensed under GNU GPL v. 2 or later.
|
|
|
|
* You should have received a copy of the license in this archive (see LICENSE).
|
|
|
|
*
|
|
|
|
* Copyright Nikolai Kudashov, 2013-2014.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package org.telegram.android;
|
|
|
|
|
|
|
|
import android.app.ActivityManager;
|
2014-10-01 21:55:24 +02:00
|
|
|
import android.content.BroadcastReceiver;
|
2014-08-22 16:24:33 +02:00
|
|
|
import android.content.Context;
|
2014-10-01 21:55:24 +02:00
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.IntentFilter;
|
2014-08-22 16:24:33 +02:00
|
|
|
import android.graphics.Bitmap;
|
|
|
|
import android.graphics.BitmapFactory;
|
|
|
|
import android.graphics.Matrix;
|
|
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
|
|
import android.media.ExifInterface;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.AsyncTask;
|
|
|
|
import android.os.Build;
|
2014-09-25 05:54:35 +02:00
|
|
|
import android.os.Environment;
|
2014-08-22 16:24:33 +02:00
|
|
|
import android.os.ParcelFileDescriptor;
|
|
|
|
import android.provider.MediaStore;
|
|
|
|
|
2014-09-14 01:40:36 +02:00
|
|
|
import org.telegram.messenger.DispatchQueue;
|
2014-08-22 16:24:33 +02:00
|
|
|
import org.telegram.messenger.FileLoader;
|
|
|
|
import org.telegram.messenger.FileLog;
|
2015-01-02 23:15:07 +01:00
|
|
|
import org.telegram.messenger.TLObject;
|
2014-08-22 16:24:33 +02:00
|
|
|
import org.telegram.messenger.TLRPC;
|
|
|
|
import org.telegram.messenger.UserConfig;
|
|
|
|
import org.telegram.messenger.Utilities;
|
2014-12-01 18:56:31 +01:00
|
|
|
import org.telegram.messenger.ApplicationLoader;
|
2014-08-22 16:24:33 +02:00
|
|
|
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileDescriptor;
|
|
|
|
import java.io.FileInputStream;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.RandomAccessFile;
|
|
|
|
import java.lang.reflect.Method;
|
2015-01-02 23:15:07 +01:00
|
|
|
import java.net.HttpURLConnection;
|
2014-08-22 16:24:33 +02:00
|
|
|
import java.net.URL;
|
|
|
|
import java.net.URLConnection;
|
2015-01-02 23:15:07 +01:00
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
import java.nio.channels.FileChannel;
|
2014-08-22 16:24:33 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.LinkedList;
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
|
|
|
public class ImageLoader {
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
private HashMap<String, Integer> bitmapUseCounts = new HashMap<>();
|
2014-08-22 16:24:33 +02:00
|
|
|
private LruCache memCache;
|
2015-01-02 23:15:07 +01:00
|
|
|
private ConcurrentHashMap<String, CacheImage> imageLoadingByUrl = new ConcurrentHashMap<>();
|
|
|
|
private ConcurrentHashMap<String, CacheImage> imageLoadingByKeys = new ConcurrentHashMap<>();
|
|
|
|
private HashMap<Integer, CacheImage> imageLoadingByTag = new HashMap<>();
|
|
|
|
private LinkedList<HttpImageTask> httpTasks = new LinkedList<>();
|
2014-09-14 01:40:36 +02:00
|
|
|
private DispatchQueue cacheOutQueue = new DispatchQueue("cacheOutQueue");
|
2015-01-02 23:15:07 +01:00
|
|
|
private ConcurrentHashMap<String, Float> fileProgresses = new ConcurrentHashMap<>();
|
2014-08-22 16:24:33 +02:00
|
|
|
private int currentHttpTasksCount = 0;
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
private LinkedList<HttpFileTask> httpFileLoadTasks = new LinkedList<>();
|
|
|
|
private HashMap<String, HttpFileTask> httpFileLoadTasksByKeys = new HashMap<>();
|
|
|
|
private HashMap<String, Runnable> retryHttpsTasks = new HashMap<>();
|
|
|
|
private int currentHttpFileLoadTasksCount = 0;
|
|
|
|
|
2014-08-22 16:24:33 +02:00
|
|
|
protected VMRuntimeHack runtimeHack = null;
|
|
|
|
private String ignoreRemoval = null;
|
|
|
|
|
|
|
|
private volatile long lastCacheOutTime = 0;
|
|
|
|
private int lastImageNum = 0;
|
|
|
|
private long lastProgressUpdateTime = 0;
|
|
|
|
|
2014-09-30 00:48:11 +02:00
|
|
|
private File telegramPath = null;
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
private class HttpFileTask extends AsyncTask<Void, Void, Boolean> {
|
2014-08-22 16:24:33 +02:00
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
private String url;
|
|
|
|
private File tempFile;
|
|
|
|
private String ext;
|
2014-08-22 16:24:33 +02:00
|
|
|
private RandomAccessFile fileOutputStream = null;
|
2015-01-02 23:15:07 +01:00
|
|
|
private boolean canRetry = true;
|
2014-08-22 16:24:33 +02:00
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
public HttpFileTask(String url, File tempFile, String ext) {
|
|
|
|
this.url = url;
|
|
|
|
this.tempFile = tempFile;
|
|
|
|
this.ext = ext;
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected Boolean doInBackground(Void... voids) {
|
|
|
|
InputStream httpConnectionStream = null;
|
|
|
|
boolean done = false;
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
URLConnection httpConnection = null;
|
2014-08-22 16:24:33 +02:00
|
|
|
try {
|
2015-01-02 23:15:07 +01:00
|
|
|
URL downloadUrl = new URL(url);
|
|
|
|
httpConnection = downloadUrl.openConnection();
|
2014-08-22 16:24:33 +02:00
|
|
|
httpConnection.setConnectTimeout(5000);
|
|
|
|
httpConnection.setReadTimeout(5000);
|
|
|
|
httpConnection.connect();
|
|
|
|
httpConnectionStream = httpConnection.getInputStream();
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
fileOutputStream = new RandomAccessFile(tempFile, "rws");
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2015-01-02 23:15:07 +01:00
|
|
|
if (httpConnection != null && httpConnection instanceof HttpURLConnection) {
|
|
|
|
int code = ((HttpURLConnection) httpConnection).getResponseCode();
|
|
|
|
if (code != HttpURLConnection.HTTP_OK && code != HttpURLConnection.HTTP_ACCEPTED && code != HttpURLConnection.HTTP_NOT_MODIFIED) {
|
|
|
|
canRetry = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
byte[] data = new byte[1024 * 4];
|
2014-08-22 16:24:33 +02:00
|
|
|
while (true) {
|
|
|
|
if (isCancelled()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
int readed = httpConnectionStream.read(data);
|
|
|
|
if (readed > 0) {
|
|
|
|
fileOutputStream.write(data, 0, readed);
|
|
|
|
} else if (readed == -1) {
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (fileOutputStream != null) {
|
|
|
|
fileOutputStream.close();
|
|
|
|
fileOutputStream = null;
|
|
|
|
}
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (httpConnectionStream != null) {
|
|
|
|
httpConnectionStream.close();
|
|
|
|
}
|
|
|
|
httpConnectionStream = null;
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPostExecute(Boolean result) {
|
|
|
|
runHttpFileLoadTasks(this, result ? 2 : 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onCancelled() {
|
|
|
|
runHttpFileLoadTasks(this, 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private class HttpImageTask extends AsyncTask<Void, Void, Boolean> {
|
|
|
|
|
|
|
|
private CacheImage cacheImage = null;
|
|
|
|
private RandomAccessFile fileOutputStream = null;
|
|
|
|
private int imageSize;
|
|
|
|
private long lastProgressTime;
|
|
|
|
private boolean canRetry = true;
|
|
|
|
private URLConnection httpConnection = null;
|
|
|
|
|
|
|
|
public HttpImageTask(CacheImage cacheImage, int size) {
|
|
|
|
this.cacheImage = cacheImage;
|
|
|
|
imageSize = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void reportProgress(final float progress) {
|
|
|
|
long currentTime = System.currentTimeMillis();
|
|
|
|
if (progress == 1 || lastProgressTime == 0 || lastProgressTime < currentTime - 500) {
|
|
|
|
lastProgressTime = currentTime;
|
|
|
|
Utilities.stageQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
fileProgresses.put(cacheImage.url, progress);
|
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileLoadProgressChanged, cacheImage.url, progress);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected Boolean doInBackground(Void... voids) {
|
|
|
|
InputStream httpConnectionStream = null;
|
|
|
|
boolean done = false;
|
|
|
|
|
|
|
|
if (!isCancelled()) {
|
|
|
|
try {
|
|
|
|
URL downloadUrl = new URL(cacheImage.httpUrl);
|
|
|
|
httpConnection = downloadUrl.openConnection();
|
|
|
|
httpConnection.setConnectTimeout(5000);
|
|
|
|
httpConnection.setReadTimeout(5000);
|
|
|
|
if (!isCancelled()) {
|
|
|
|
httpConnection.connect();
|
|
|
|
httpConnectionStream = httpConnection.getInputStream();
|
|
|
|
|
|
|
|
fileOutputStream = new RandomAccessFile(cacheImage.tempFilePath, "rws");
|
|
|
|
}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isCancelled()) {
|
|
|
|
try {
|
|
|
|
if (httpConnection != null && httpConnection instanceof HttpURLConnection) {
|
|
|
|
int code = ((HttpURLConnection) httpConnection).getResponseCode();
|
|
|
|
if (code != HttpURLConnection.HTTP_OK && code != HttpURLConnection.HTTP_ACCEPTED && code != HttpURLConnection.HTTP_NOT_MODIFIED) {
|
|
|
|
canRetry = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
byte[] data = new byte[1024 * 2];
|
|
|
|
int totalLoaded = 0;
|
|
|
|
while (true) {
|
|
|
|
if (isCancelled()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
int readed = httpConnectionStream.read(data);
|
|
|
|
if (readed > 0) {
|
|
|
|
totalLoaded += readed;
|
|
|
|
fileOutputStream.write(data, 0, readed);
|
|
|
|
if (imageSize != 0) {
|
|
|
|
reportProgress(totalLoaded / (float) imageSize);
|
|
|
|
}
|
|
|
|
} else if (readed == -1) {
|
|
|
|
done = true;
|
|
|
|
if (imageSize != 0) {
|
|
|
|
reportProgress(1.0f);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (fileOutputStream != null) {
|
|
|
|
fileOutputStream.close();
|
|
|
|
fileOutputStream = null;
|
|
|
|
}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (httpConnectionStream != null) {
|
|
|
|
httpConnectionStream.close();
|
|
|
|
}
|
|
|
|
httpConnectionStream = null;
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
2014-08-22 16:24:33 +02:00
|
|
|
if (done) {
|
|
|
|
if (cacheImage.tempFilePath != null) {
|
|
|
|
cacheImage.tempFilePath.renameTo(cacheImage.finalFilePath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-01-02 23:15:07 +01:00
|
|
|
protected void onPostExecute(final Boolean result) {
|
|
|
|
if (result || !canRetry) {
|
|
|
|
fileDidLoaded(cacheImage.url, cacheImage.finalFilePath, cacheImage.tempFilePath);
|
|
|
|
} else {
|
|
|
|
httpFileLoadError(cacheImage.url);
|
|
|
|
}
|
|
|
|
Utilities.stageQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
fileProgresses.remove(cacheImage.url);
|
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (result) {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidLoaded, cacheImage.url);
|
|
|
|
} else {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidFailedLoad, cacheImage.url, 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
runHttpTasks(true);
|
|
|
|
}
|
|
|
|
});
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onCancelled() {
|
2015-01-02 23:15:07 +01:00
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
runHttpTasks(true);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Utilities.stageQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
fileProgresses.remove(cacheImage.url);
|
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidFailedLoad, cacheImage.url, 1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-14 01:40:36 +02:00
|
|
|
private class CacheOutTask implements Runnable {
|
|
|
|
private Thread runningThread = null;
|
2014-10-05 23:23:57 +02:00
|
|
|
private final Object sync = new Object();
|
2014-08-22 16:24:33 +02:00
|
|
|
|
|
|
|
private CacheImage cacheImage = null;
|
2014-09-14 01:40:36 +02:00
|
|
|
private boolean isCancelled = false;
|
2014-08-22 16:24:33 +02:00
|
|
|
|
|
|
|
public CacheOutTask(CacheImage cacheImage) {
|
|
|
|
this.cacheImage = cacheImage;
|
|
|
|
}
|
|
|
|
|
2014-09-14 01:40:36 +02:00
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
synchronized (sync) {
|
|
|
|
runningThread = Thread.currentThread();
|
|
|
|
Thread.interrupted();
|
|
|
|
if (isCancelled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-22 16:24:33 +02:00
|
|
|
Long mediaId = null;
|
|
|
|
Bitmap image = null;
|
|
|
|
File cacheFileFinal = null;
|
|
|
|
boolean canDeleteFile = true;
|
2015-01-02 23:15:07 +01:00
|
|
|
boolean isWebp = false;
|
2014-08-22 16:24:33 +02:00
|
|
|
|
|
|
|
if (cacheImage.finalFilePath != null && cacheImage.finalFilePath.exists()) {
|
|
|
|
cacheFileFinal = cacheImage.finalFilePath;
|
|
|
|
} else if (cacheImage.tempFilePath != null && cacheImage.tempFilePath.exists()) {
|
|
|
|
cacheFileFinal = cacheImage.tempFilePath;
|
|
|
|
} else if (cacheImage.finalFilePath != null) {
|
|
|
|
cacheFileFinal = cacheImage.finalFilePath;
|
|
|
|
}
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
if (cacheFileFinal.toString().endsWith("webp")) {
|
|
|
|
isWebp = true;
|
|
|
|
}
|
|
|
|
|
2014-08-22 16:24:33 +02:00
|
|
|
try {
|
|
|
|
if (cacheImage.httpUrl != null) {
|
|
|
|
if (cacheImage.httpUrl.startsWith("thumb://")) {
|
|
|
|
int idx = cacheImage.httpUrl.indexOf(":", 8);
|
|
|
|
if (idx >= 0) {
|
|
|
|
mediaId = Long.parseLong(cacheImage.httpUrl.substring(8, idx));
|
|
|
|
}
|
|
|
|
canDeleteFile = false;
|
|
|
|
} else if (!cacheImage.httpUrl.startsWith("http")) {
|
|
|
|
canDeleteFile = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int delay = 20;
|
|
|
|
if (runtimeHack != null) {
|
|
|
|
delay = 60;
|
|
|
|
}
|
|
|
|
if (mediaId != null) {
|
|
|
|
delay = 0;
|
|
|
|
}
|
|
|
|
if (delay != 0 && lastCacheOutTime != 0 && lastCacheOutTime > System.currentTimeMillis() - delay) {
|
|
|
|
Thread.sleep(delay);
|
|
|
|
}
|
|
|
|
lastCacheOutTime = System.currentTimeMillis();
|
2014-09-14 01:40:36 +02:00
|
|
|
synchronized (sync) {
|
|
|
|
if (isCancelled) {
|
|
|
|
return;
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BitmapFactory.Options opts = new BitmapFactory.Options();
|
|
|
|
|
|
|
|
float w_filter = 0;
|
|
|
|
float h_filter = 0;
|
|
|
|
boolean blur = false;
|
|
|
|
if (cacheImage.filter != null) {
|
|
|
|
String args[] = cacheImage.filter.split("_");
|
|
|
|
w_filter = Float.parseFloat(args[0]) * AndroidUtilities.density;
|
|
|
|
h_filter = Float.parseFloat(args[1]) * AndroidUtilities.density;
|
|
|
|
if (args.length > 2) {
|
|
|
|
blur = true;
|
|
|
|
}
|
|
|
|
opts.inJustDecodeBounds = true;
|
|
|
|
|
|
|
|
if (mediaId != null) {
|
|
|
|
MediaStore.Images.Thumbnails.getThumbnail(ApplicationLoader.applicationContext.getContentResolver(), mediaId, MediaStore.Images.Thumbnails.MINI_KIND, opts);
|
|
|
|
} else {
|
|
|
|
if (cacheImage.finalFilePath != null && cacheImage.finalFilePath.exists()) {
|
|
|
|
BitmapFactory.decodeFile(cacheImage.finalFilePath.getAbsolutePath(), opts);
|
|
|
|
} else if (cacheImage.tempFilePath != null && cacheImage.tempFilePath.exists()) {
|
|
|
|
BitmapFactory.decodeFile(cacheImage.tempFilePath.getAbsolutePath(), opts);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float photoW = opts.outWidth;
|
|
|
|
float photoH = opts.outHeight;
|
|
|
|
float scaleFactor = Math.max(photoW / w_filter, photoH / h_filter);
|
|
|
|
if (scaleFactor < 1) {
|
|
|
|
scaleFactor = 1;
|
|
|
|
}
|
|
|
|
opts.inJustDecodeBounds = false;
|
|
|
|
opts.inSampleSize = (int)scaleFactor;
|
|
|
|
}
|
2014-09-14 01:40:36 +02:00
|
|
|
synchronized (sync) {
|
|
|
|
if (isCancelled) {
|
|
|
|
return;
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cacheImage.filter == null || blur) {
|
|
|
|
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
|
|
|
|
} else {
|
|
|
|
opts.inPreferredConfig = Bitmap.Config.RGB_565;
|
|
|
|
}
|
|
|
|
opts.inDither = false;
|
|
|
|
if (mediaId != null) {
|
|
|
|
image = MediaStore.Images.Thumbnails.getThumbnail(ApplicationLoader.applicationContext.getContentResolver(), mediaId, MediaStore.Images.Thumbnails.MINI_KIND, null);
|
|
|
|
}
|
|
|
|
if (image == null) {
|
2015-01-02 23:15:07 +01:00
|
|
|
if (isWebp) {
|
|
|
|
RandomAccessFile file = new RandomAccessFile(cacheFileFinal, "r");
|
|
|
|
ByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, cacheFileFinal.length());
|
|
|
|
image = Utilities.loadWebpImage(buffer, buffer.limit(), null);
|
|
|
|
file.close();
|
|
|
|
} else {
|
|
|
|
FileInputStream is = new FileInputStream(cacheFileFinal);
|
|
|
|
image = BitmapFactory.decodeStream(is, null, opts);
|
|
|
|
is.close();
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
if (image == null) {
|
|
|
|
if (canDeleteFile && (cacheFileFinal.length() == 0 || cacheImage.filter == null)) {
|
|
|
|
cacheFileFinal.delete();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (cacheImage.filter != null) {
|
|
|
|
float bitmapW = image.getWidth();
|
|
|
|
float bitmapH = image.getHeight();
|
|
|
|
if (bitmapW != w_filter && bitmapW > w_filter) {
|
|
|
|
float scaleFactor = bitmapW / w_filter;
|
|
|
|
Bitmap scaledBitmap = Bitmap.createScaledBitmap(image, (int)w_filter, (int)(bitmapH / scaleFactor), true);
|
|
|
|
if (image != scaledBitmap) {
|
|
|
|
image.recycle();
|
|
|
|
image = scaledBitmap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (image != null && blur && bitmapH < 100 && bitmapW < 100) {
|
2014-10-09 17:55:05 +02:00
|
|
|
Utilities.blurBitmap(image, 3);
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (runtimeHack != null) {
|
|
|
|
runtimeHack.trackFree(image.getRowBytes() * image.getHeight());
|
|
|
|
}
|
|
|
|
}
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-29 23:06:04 +02:00
|
|
|
//don't promt
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
2014-09-14 01:40:36 +02:00
|
|
|
Thread.interrupted();
|
|
|
|
onPostExecute(image != null ? new BitmapDrawable(image) : null);
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
|
2014-09-14 01:40:36 +02:00
|
|
|
private void onPostExecute(final BitmapDrawable bitmapDrawable) {
|
2014-11-06 22:34:47 +01:00
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
2014-09-14 01:40:36 +02:00
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (bitmapDrawable != null && memCache.get(cacheImage.key) == null) {
|
|
|
|
memCache.put(cacheImage.key, bitmapDrawable);
|
|
|
|
}
|
|
|
|
cacheImage.setImageAndClear(bitmapDrawable);
|
|
|
|
}
|
|
|
|
});
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
|
2014-09-14 01:40:36 +02:00
|
|
|
public void cancel() {
|
|
|
|
synchronized (sync) {
|
|
|
|
try {
|
|
|
|
isCancelled = true;
|
|
|
|
if (runningThread != null) {
|
|
|
|
runningThread.interrupt();
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
//don't promt
|
|
|
|
}
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class VMRuntimeHack {
|
|
|
|
private Object runtime = null;
|
|
|
|
private Method trackAllocation = null;
|
|
|
|
private Method trackFree = null;
|
|
|
|
|
|
|
|
public boolean trackAlloc(long size) {
|
|
|
|
if (runtime == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
Object res = trackAllocation.invoke(runtime, size);
|
|
|
|
return (res instanceof Boolean) ? (Boolean)res : true;
|
|
|
|
} catch (Exception e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean trackFree(long size) {
|
|
|
|
if (runtime == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
Object res = trackFree.invoke(runtime, size);
|
|
|
|
return (res instanceof Boolean) ? (Boolean)res : true;
|
|
|
|
} catch (Exception e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
public VMRuntimeHack() {
|
|
|
|
try {
|
|
|
|
Class cl = Class.forName("dalvik.system.VMRuntime");
|
|
|
|
Method getRt = cl.getMethod("getRuntime", new Class[0]);
|
|
|
|
Object[] objects = new Object[0];
|
|
|
|
runtime = getRt.invoke(null, objects);
|
|
|
|
trackAllocation = cl.getMethod("trackExternalAllocation", new Class[] {long.class});
|
|
|
|
trackFree = cl.getMethod("trackExternalFree", new Class[] {long.class});
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
runtime = null;
|
|
|
|
trackAllocation = null;
|
|
|
|
trackFree = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private class CacheImage {
|
|
|
|
protected String key = null;
|
|
|
|
protected String url = null;
|
|
|
|
protected String filter = null;
|
2015-01-02 23:15:07 +01:00
|
|
|
protected TLObject fileLocation = null;
|
2014-08-22 16:24:33 +02:00
|
|
|
protected String httpUrl = null;
|
|
|
|
protected File finalFilePath = null;
|
|
|
|
protected File tempFilePath = null;
|
|
|
|
protected CacheOutTask cacheTask;
|
2015-01-02 23:15:07 +01:00
|
|
|
protected HttpImageTask httpTask;
|
|
|
|
protected ArrayList<ImageReceiver> imageViewArray = new ArrayList<>();
|
2014-08-22 16:24:33 +02:00
|
|
|
|
|
|
|
public void addImageView(ImageReceiver imageView) {
|
|
|
|
boolean exist = false;
|
|
|
|
for (ImageReceiver v : imageViewArray) {
|
|
|
|
if (v == imageView) {
|
|
|
|
exist = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!exist) {
|
|
|
|
imageViewArray.add(imageView);
|
|
|
|
imageLoadingByTag.put(imageView.getTag(), this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeImageView(ImageReceiver imageView) {
|
|
|
|
for (int a = 0; a < imageViewArray.size(); a++) {
|
|
|
|
ImageReceiver obj = imageViewArray.get(a);
|
|
|
|
if (obj == null || obj == imageView) {
|
|
|
|
imageViewArray.remove(a);
|
|
|
|
if (obj != null) {
|
|
|
|
imageLoadingByTag.remove(obj.getTag());
|
|
|
|
}
|
|
|
|
a--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (imageViewArray.size() == 0) {
|
|
|
|
cancelAndClear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setImageAndClear(BitmapDrawable image) {
|
|
|
|
if (image != null) {
|
|
|
|
for (ImageReceiver imgView : imageViewArray) {
|
|
|
|
imgView.setImageBitmap(image, key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void cancelAndClear() {
|
|
|
|
if (fileLocation != null) {
|
2015-01-02 23:15:07 +01:00
|
|
|
if (fileLocation instanceof TLRPC.FileLocation) {
|
|
|
|
FileLoader.getInstance().cancelLoadFile((TLRPC.FileLocation) fileLocation);
|
|
|
|
} else if (fileLocation instanceof TLRPC.Document) {
|
|
|
|
FileLoader.getInstance().cancelLoadFile((TLRPC.Document) fileLocation);
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
if (cacheTask != null) {
|
2014-09-14 01:40:36 +02:00
|
|
|
cacheOutQueue.cancelRunnable(cacheTask);
|
|
|
|
cacheTask.cancel();
|
2014-08-22 16:24:33 +02:00
|
|
|
cacheTask = null;
|
|
|
|
}
|
|
|
|
if (httpTask != null) {
|
|
|
|
httpTasks.remove(httpTask);
|
|
|
|
httpTask.cancel(true);
|
|
|
|
httpTask = null;
|
|
|
|
}
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void clear() {
|
|
|
|
for (ImageReceiver imageReceiver : imageViewArray) {
|
|
|
|
imageLoadingByTag.remove(imageReceiver.getTag());
|
|
|
|
}
|
|
|
|
imageViewArray.clear();
|
|
|
|
if (url != null) {
|
|
|
|
imageLoadingByUrl.remove(url);
|
|
|
|
}
|
|
|
|
if (key != null) {
|
|
|
|
imageLoadingByKeys.remove(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static volatile ImageLoader Instance = null;
|
|
|
|
public static ImageLoader getInstance() {
|
|
|
|
ImageLoader localInstance = Instance;
|
|
|
|
if (localInstance == null) {
|
|
|
|
synchronized (ImageLoader.class) {
|
|
|
|
localInstance = Instance;
|
|
|
|
if (localInstance == null) {
|
|
|
|
Instance = localInstance = new ImageLoader();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return localInstance;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ImageLoader() {
|
|
|
|
int cacheSize = Math.min(15, ((ActivityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass() / 7) * 1024 * 1024;
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT < 11) {
|
|
|
|
runtimeHack = new VMRuntimeHack();
|
|
|
|
cacheSize = 1024 * 1024 * 3;
|
|
|
|
}
|
|
|
|
memCache = new LruCache(cacheSize) {
|
|
|
|
@Override
|
|
|
|
protected int sizeOf(String key, BitmapDrawable bitmap) {
|
|
|
|
Bitmap b = bitmap.getBitmap();
|
|
|
|
if(Build.VERSION.SDK_INT < 12) {
|
|
|
|
return b.getRowBytes() * b.getHeight();
|
|
|
|
} else {
|
|
|
|
return b.getByteCount();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
|
|
protected void entryRemoved(boolean evicted, String key, BitmapDrawable oldBitmap, BitmapDrawable newBitmap) {
|
|
|
|
if (ignoreRemoval != null && key != null && ignoreRemoval.equals(key)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Integer count = bitmapUseCounts.get(key);
|
|
|
|
if (count == null || count == 0) {
|
|
|
|
Bitmap b = oldBitmap.getBitmap();
|
|
|
|
if (runtimeHack != null) {
|
|
|
|
runtimeHack.trackAlloc(b.getRowBytes() * b.getHeight());
|
|
|
|
}
|
|
|
|
if (!b.isRecycled()) {
|
|
|
|
b.recycle();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
FileLoader.getInstance().setDelegate(new FileLoader.FileLoaderDelegate() {
|
|
|
|
@Override
|
|
|
|
public void fileUploadProgressChanged(final String location, final float progress, final boolean isEncrypted) {
|
2015-01-02 23:15:07 +01:00
|
|
|
fileProgresses.put(location, progress);
|
2014-08-22 16:24:33 +02:00
|
|
|
long currentTime = System.currentTimeMillis();
|
|
|
|
if (lastProgressUpdateTime == 0 || lastProgressUpdateTime < currentTime - 500) {
|
|
|
|
lastProgressUpdateTime = currentTime;
|
|
|
|
|
2014-11-06 22:34:47 +01:00
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
2014-08-22 16:24:33 +02:00
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileUploadProgressChanged, location, progress, isEncrypted);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void fileDidUploaded(final String location, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile) {
|
|
|
|
Utilities.stageQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidUpload, location, inputFile, inputEncryptedFile);
|
2015-01-02 23:15:07 +01:00
|
|
|
fileProgresses.remove(location);
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void fileDidFailedUpload(final String location, final boolean isEncrypted) {
|
|
|
|
Utilities.stageQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidFailUpload, location, isEncrypted);
|
2015-01-02 23:15:07 +01:00
|
|
|
fileProgresses.remove(location);
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void fileDidLoaded(final String location, final File finalFile, final File tempFile) {
|
2015-01-02 23:15:07 +01:00
|
|
|
fileProgresses.remove(location);
|
2014-11-06 22:34:47 +01:00
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
2014-08-22 16:24:33 +02:00
|
|
|
@Override
|
|
|
|
public void run() {
|
2014-09-30 00:48:11 +02:00
|
|
|
if (location != null) {
|
2014-10-01 00:36:18 +02:00
|
|
|
if (MediaController.getInstance().canSaveToGallery() && telegramPath != null && finalFile != null && finalFile.exists() && (location.endsWith(".mp4") || location.endsWith(".jpg"))) {
|
2014-09-30 00:48:11 +02:00
|
|
|
if (finalFile.toString().startsWith(telegramPath.toString())) {
|
|
|
|
Utilities.addMediaToGallery(finalFile.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
ImageLoader.this.fileDidLoaded(location, finalFile, tempFile);
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidLoaded, location);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-09-30 00:48:11 +02:00
|
|
|
public void fileDidFailedLoad(final String location, final int state) {
|
2015-01-02 23:15:07 +01:00
|
|
|
fileProgresses.remove(location);
|
2014-11-06 22:34:47 +01:00
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
2014-08-22 16:24:33 +02:00
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
ImageLoader.this.fileDidFailedLoad(location);
|
2014-09-30 00:48:11 +02:00
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidFailedLoad, location, state);
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void fileLoadProgressChanged(final String location, final float progress) {
|
2015-01-02 23:15:07 +01:00
|
|
|
fileProgresses.put(location, progress);
|
2014-08-22 16:24:33 +02:00
|
|
|
long currentTime = System.currentTimeMillis();
|
|
|
|
if (lastProgressUpdateTime == 0 || lastProgressUpdateTime < currentTime - 500) {
|
|
|
|
lastProgressUpdateTime = currentTime;
|
2014-11-06 22:34:47 +01:00
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
2014-08-22 16:24:33 +02:00
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileLoadProgressChanged, location, progress);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2014-09-25 05:54:35 +02:00
|
|
|
});
|
2014-08-22 16:24:33 +02:00
|
|
|
|
2014-10-01 21:55:24 +02:00
|
|
|
BroadcastReceiver receiver = new BroadcastReceiver() {
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context arg0, Intent intent) {
|
|
|
|
FileLog.e("tmessages", "file system changed");
|
|
|
|
Runnable r = new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
FileLoader.getInstance().setMediaDirs(createMediaPaths());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if (Intent.ACTION_MEDIA_UNMOUNTED.equals(intent.getAction())) {
|
2014-11-06 22:34:47 +01:00
|
|
|
AndroidUtilities.runOnUIThread(r, 1000);
|
2014-10-01 21:55:24 +02:00
|
|
|
} else {
|
|
|
|
r.run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
IntentFilter filter = new IntentFilter();
|
|
|
|
filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
|
|
|
|
filter.addAction(Intent.ACTION_MEDIA_CHECKING);
|
|
|
|
filter.addAction(Intent.ACTION_MEDIA_EJECT);
|
|
|
|
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
|
|
|
filter.addAction(Intent.ACTION_MEDIA_NOFS);
|
|
|
|
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
|
|
|
|
filter.addAction(Intent.ACTION_MEDIA_SHARED);
|
|
|
|
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTABLE);
|
|
|
|
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
|
|
|
|
filter.addDataScheme("file");
|
|
|
|
ApplicationLoader.applicationContext.registerReceiver(receiver, filter);
|
|
|
|
|
2014-09-25 05:54:35 +02:00
|
|
|
FileLoader.getInstance().setMediaDirs(createMediaPaths());
|
|
|
|
}
|
|
|
|
|
|
|
|
private HashMap<Integer, File> createMediaPaths() {
|
2015-01-02 23:15:07 +01:00
|
|
|
HashMap<Integer, File> mediaDirs = new HashMap<>();
|
2014-09-25 16:57:17 +02:00
|
|
|
File cachePath = AndroidUtilities.getCacheDir();
|
2014-09-28 15:37:26 +02:00
|
|
|
if (!cachePath.isDirectory()) {
|
|
|
|
try {
|
|
|
|
cachePath.mkdirs();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
2014-09-25 16:57:17 +02:00
|
|
|
}
|
|
|
|
mediaDirs.put(FileLoader.MEDIA_DIR_CACHE, cachePath);
|
2014-10-01 21:55:24 +02:00
|
|
|
FileLog.e("tmessages", "cache path = " + cachePath);
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2014-09-25 05:54:35 +02:00
|
|
|
try {
|
|
|
|
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
|
2014-10-07 22:14:27 +02:00
|
|
|
telegramPath = new File(Environment.getExternalStorageDirectory(), "Telegram");
|
2014-09-25 05:54:35 +02:00
|
|
|
telegramPath.mkdirs();
|
2014-10-07 22:14:27 +02:00
|
|
|
|
|
|
|
boolean canRename = false;
|
|
|
|
|
|
|
|
try {
|
|
|
|
for (int a = 0; a < 5; a++) {
|
|
|
|
File srcFile = new File(cachePath, "temp.file");
|
|
|
|
srcFile.createNewFile();
|
|
|
|
File dstFile = new File(telegramPath, "temp.file");
|
|
|
|
canRename = srcFile.renameTo(dstFile);
|
|
|
|
srcFile.delete();
|
|
|
|
dstFile.delete();
|
|
|
|
if (canRename) {
|
|
|
|
break;
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
}
|
2014-10-07 22:14:27 +02:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
2014-09-25 05:54:35 +02:00
|
|
|
|
2014-10-07 22:14:27 +02:00
|
|
|
if (canRename) {
|
|
|
|
if (telegramPath.isDirectory()) {
|
|
|
|
try {
|
|
|
|
File imagePath = new File(telegramPath, "Telegram Images");
|
|
|
|
imagePath.mkdir();
|
|
|
|
if (imagePath.isDirectory()) {
|
|
|
|
mediaDirs.put(FileLoader.MEDIA_DIR_IMAGE, imagePath);
|
|
|
|
FileLog.e("tmessages", "image path = " + imagePath);
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
2014-09-25 05:54:35 +02:00
|
|
|
|
2014-10-07 22:14:27 +02:00
|
|
|
try {
|
|
|
|
File videoPath = new File(telegramPath, "Telegram Video");
|
|
|
|
videoPath.mkdir();
|
|
|
|
if (videoPath.isDirectory()) {
|
|
|
|
mediaDirs.put(FileLoader.MEDIA_DIR_VIDEO, videoPath);
|
|
|
|
FileLog.e("tmessages", "video path = " + videoPath);
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
2014-09-25 05:54:35 +02:00
|
|
|
|
2014-10-07 22:14:27 +02:00
|
|
|
try {
|
|
|
|
File audioPath = new File(telegramPath, "Telegram Audio");
|
|
|
|
audioPath.mkdir();
|
|
|
|
if (audioPath.isDirectory()) {
|
|
|
|
new File(audioPath, ".nomedia").createNewFile();
|
|
|
|
mediaDirs.put(FileLoader.MEDIA_DIR_AUDIO, audioPath);
|
|
|
|
FileLog.e("tmessages", "audio path = " + audioPath);
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
File documentPath = new File(telegramPath, "Telegram Documents");
|
|
|
|
documentPath.mkdir();
|
|
|
|
if (documentPath.isDirectory()) {
|
|
|
|
new File(documentPath, ".nomedia").createNewFile();
|
|
|
|
mediaDirs.put(FileLoader.MEDIA_DIR_DOCUMENT, documentPath);
|
|
|
|
FileLog.e("tmessages", "documents path = " + documentPath);
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
}
|
2014-10-07 22:14:27 +02:00
|
|
|
} else {
|
|
|
|
FileLog.e("tmessages", "this Android can't rename files");
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
2014-10-01 21:55:24 +02:00
|
|
|
MediaController.getInstance().checkSaveToGalleryFiles();
|
2014-09-25 05:54:35 +02:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2014-09-25 05:54:35 +02:00
|
|
|
return mediaDirs;
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
public Float getFileProgress(String location) {
|
|
|
|
return fileProgresses.get(location);
|
|
|
|
}
|
|
|
|
|
2014-08-22 16:24:33 +02:00
|
|
|
private void performReplace(String oldKey, String newKey) {
|
|
|
|
BitmapDrawable b = memCache.get(oldKey);
|
|
|
|
if (b != null) {
|
|
|
|
ignoreRemoval = oldKey;
|
|
|
|
memCache.remove(oldKey);
|
|
|
|
memCache.put(newKey, b);
|
|
|
|
ignoreRemoval = null;
|
|
|
|
}
|
|
|
|
Integer val = bitmapUseCounts.get(oldKey);
|
|
|
|
if (val != null) {
|
|
|
|
bitmapUseCounts.put(newKey, val);
|
|
|
|
bitmapUseCounts.remove(oldKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void incrementUseCount(String key) {
|
|
|
|
Integer count = bitmapUseCounts.get(key);
|
|
|
|
if (count == null) {
|
|
|
|
bitmapUseCounts.put(key, 1);
|
|
|
|
} else {
|
|
|
|
bitmapUseCounts.put(key, count + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean decrementUseCount(String key) {
|
|
|
|
Integer count = bitmapUseCounts.get(key);
|
|
|
|
if (count == null) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (count == 1) {
|
|
|
|
bitmapUseCounts.remove(key);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
bitmapUseCounts.put(key, count - 1);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeImage(String key) {
|
|
|
|
bitmapUseCounts.remove(key);
|
|
|
|
memCache.remove(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isInCache(String key) {
|
|
|
|
return memCache.get(key) != null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void clearMemory() {
|
|
|
|
memCache.evictAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void cancelLoadingForImageView(ImageReceiver imageView) {
|
|
|
|
if (imageView == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Integer TAG = imageView.getTag();
|
|
|
|
if (TAG == null) {
|
|
|
|
imageView.setTag(TAG = lastImageNum);
|
|
|
|
lastImageNum++;
|
|
|
|
if (lastImageNum == Integer.MAX_VALUE) {
|
|
|
|
lastImageNum = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CacheImage ei = imageLoadingByTag.get(TAG);
|
|
|
|
if (ei != null) {
|
|
|
|
ei.removeImageView(imageView);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
public BitmapDrawable getImageFromMemory(TLObject fileLocation, String httpUrl, String filter, ImageReceiver imageReceiver) {
|
|
|
|
if (fileLocation == null && httpUrl == null) {
|
2014-08-22 16:24:33 +02:00
|
|
|
return null;
|
|
|
|
}
|
2015-01-02 23:15:07 +01:00
|
|
|
String key = null;
|
2014-08-22 16:24:33 +02:00
|
|
|
if (httpUrl != null) {
|
|
|
|
key = Utilities.MD5(httpUrl);
|
|
|
|
} else {
|
2015-01-02 23:15:07 +01:00
|
|
|
if (fileLocation instanceof TLRPC.FileLocation) {
|
|
|
|
TLRPC.FileLocation location = (TLRPC.FileLocation) fileLocation;
|
|
|
|
key = location.volume_id + "_" + location.local_id;
|
|
|
|
} else if (fileLocation instanceof TLRPC.Document) {
|
|
|
|
TLRPC.Document location = (TLRPC.Document) fileLocation;
|
|
|
|
key = location.dc_id + "_" + location.id;
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
if (filter != null) {
|
|
|
|
key += "@" + filter;
|
|
|
|
}
|
2014-08-29 23:06:04 +02:00
|
|
|
BitmapDrawable bitmapDrawable = memCache.get(key);
|
|
|
|
if (bitmapDrawable != null && imageReceiver != null) {
|
2014-08-27 00:26:25 +02:00
|
|
|
Integer TAG = imageReceiver.getTag();
|
|
|
|
if (TAG != null) {
|
|
|
|
CacheImage alreadyLoadingImage = imageLoadingByTag.get(TAG);
|
|
|
|
if (alreadyLoadingImage != null) {
|
|
|
|
alreadyLoadingImage.removeImageView(imageReceiver);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-08-29 23:06:04 +02:00
|
|
|
return bitmapDrawable;
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void replaceImageInCache(final String oldKey, final String newKey) {
|
2014-11-06 22:34:47 +01:00
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
2014-08-22 16:24:33 +02:00
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
ArrayList<String> arr = memCache.getFilterKeys(oldKey);
|
|
|
|
if (arr != null) {
|
|
|
|
for (String filter : arr) {
|
|
|
|
performReplace(oldKey + "@" + filter, newKey + "@" + filter);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
performReplace(oldKey, newKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2014-10-10 19:16:39 +02:00
|
|
|
public void putImageToCache(BitmapDrawable bitmap, String key) {
|
|
|
|
memCache.put(key, bitmap);
|
|
|
|
}
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
public void loadImage(final TLObject fileLocation, final String httpUrl, final ImageReceiver imageView, final int size, final boolean cacheOnly) {
|
|
|
|
if ((fileLocation == null && httpUrl == null) || imageView == null || (fileLocation != null && !(fileLocation instanceof TLRPC.TL_fileLocation) && !(fileLocation instanceof TLRPC.TL_fileEncryptedLocation) && !(fileLocation instanceof TLRPC.TL_document))) {
|
2014-08-22 16:24:33 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
String url = null;
|
|
|
|
String key = null;
|
|
|
|
boolean writeToCache = false;
|
2014-08-22 16:24:33 +02:00
|
|
|
if (httpUrl != null) {
|
|
|
|
key = Utilities.MD5(httpUrl);
|
2015-01-02 23:15:07 +01:00
|
|
|
url = key + "." + getHttpUrlExtension(httpUrl);
|
2014-08-22 16:24:33 +02:00
|
|
|
} else {
|
2015-01-02 23:15:07 +01:00
|
|
|
if (fileLocation instanceof TLRPC.FileLocation) {
|
|
|
|
TLRPC.FileLocation location = (TLRPC.FileLocation) fileLocation;
|
|
|
|
key = location.volume_id + "_" + location.local_id;
|
|
|
|
url = key + "." + (location.ext != null ? location.ext : "jpg");
|
|
|
|
if (location.ext != null) {
|
|
|
|
writeToCache = true;
|
|
|
|
}
|
|
|
|
if (!writeToCache) {
|
|
|
|
writeToCache = location.key != null || location.volume_id == Integer.MIN_VALUE && location.local_id < 0;
|
|
|
|
}
|
|
|
|
} else if (fileLocation instanceof TLRPC.Document) {
|
|
|
|
TLRPC.Document location = (TLRPC.Document) fileLocation;
|
|
|
|
if (location.id == 0 || location.dc_id == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
key = location.dc_id + "_" + location.id;
|
|
|
|
url = key + ".webp";
|
|
|
|
writeToCache = true;
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
String filter = imageView.getFilter();
|
|
|
|
if (filter != null) {
|
|
|
|
key += "@" + filter;
|
|
|
|
}
|
|
|
|
|
|
|
|
Integer TAG = imageView.getTag();
|
|
|
|
if (TAG == null) {
|
|
|
|
imageView.setTag(TAG = lastImageNum);
|
|
|
|
lastImageNum++;
|
|
|
|
if (lastImageNum == Integer.MAX_VALUE) {
|
|
|
|
lastImageNum = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean added = false;
|
|
|
|
CacheImage alreadyLoadingUrl = imageLoadingByUrl.get(url);
|
|
|
|
CacheImage alreadyLoadingCache = imageLoadingByKeys.get(key);
|
|
|
|
CacheImage alreadyLoadingImage = imageLoadingByTag.get(TAG);
|
|
|
|
if (alreadyLoadingImage != null) {
|
|
|
|
if (alreadyLoadingImage == alreadyLoadingUrl || alreadyLoadingImage == alreadyLoadingCache) {
|
|
|
|
added = true;
|
|
|
|
} else {
|
|
|
|
alreadyLoadingImage.removeImageView(imageView);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!added && alreadyLoadingCache != null) {
|
|
|
|
alreadyLoadingCache.addImageView(imageView);
|
|
|
|
added = true;
|
|
|
|
}
|
|
|
|
if (!added && alreadyLoadingUrl != null) {
|
|
|
|
alreadyLoadingUrl.addImageView(imageView);
|
|
|
|
added = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!added) {
|
|
|
|
boolean onlyCache = false;
|
2014-09-25 05:54:35 +02:00
|
|
|
File cacheFile = null;
|
2015-01-02 23:15:07 +01:00
|
|
|
if (cacheOnly || size == 0 || httpUrl != null || fileLocation != null && writeToCache) {
|
2014-09-25 05:54:35 +02:00
|
|
|
cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), url);
|
|
|
|
} else {
|
|
|
|
cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_IMAGE), url);
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
if (httpUrl != null) {
|
|
|
|
if (!httpUrl.startsWith("http")) {
|
|
|
|
onlyCache = true;
|
|
|
|
if (httpUrl.startsWith("thumb://")) {
|
|
|
|
int idx = httpUrl.indexOf(":", 8);
|
|
|
|
if (idx >= 0) {
|
|
|
|
cacheFile = new File(httpUrl.substring(idx + 1));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cacheFile = new File(httpUrl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CacheImage img = new CacheImage();
|
|
|
|
if (onlyCache || cacheFile.exists()) {
|
|
|
|
img.finalFilePath = cacheFile;
|
|
|
|
img.key = key;
|
|
|
|
img.httpUrl = httpUrl;
|
|
|
|
if (imageView.getFilter() != null) {
|
|
|
|
img.filter = imageView.getFilter();
|
|
|
|
}
|
|
|
|
img.addImageView(imageView);
|
|
|
|
imageLoadingByKeys.put(key, img);
|
2014-08-29 23:06:04 +02:00
|
|
|
img.cacheTask = new CacheOutTask(img);
|
2014-09-14 01:40:36 +02:00
|
|
|
cacheOutQueue.postRunnable(img.cacheTask);
|
2014-08-22 16:24:33 +02:00
|
|
|
} else {
|
|
|
|
img.url = url;
|
|
|
|
img.fileLocation = fileLocation;
|
|
|
|
img.httpUrl = httpUrl;
|
|
|
|
img.addImageView(imageView);
|
|
|
|
imageLoadingByUrl.put(url, img);
|
|
|
|
if (httpUrl == null) {
|
2015-01-02 23:15:07 +01:00
|
|
|
if (fileLocation instanceof TLRPC.FileLocation) {
|
|
|
|
TLRPC.FileLocation location = (TLRPC.FileLocation) fileLocation;
|
|
|
|
FileLoader.getInstance().loadFile(location, size, size == 0 || location.key != null || cacheOnly);
|
|
|
|
} else if (fileLocation instanceof TLRPC.Document) {
|
|
|
|
FileLoader.getInstance().loadFile((TLRPC.Document) fileLocation, true, true);
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
} else {
|
|
|
|
String file = Utilities.MD5(httpUrl);
|
2014-09-25 05:54:35 +02:00
|
|
|
File cacheDir = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE);
|
|
|
|
img.tempFilePath = new File(cacheDir, file + "_temp.jpg");
|
|
|
|
img.finalFilePath = cacheFile;
|
2015-01-02 23:15:07 +01:00
|
|
|
img.httpTask = new HttpImageTask(img, size);
|
2014-08-22 16:24:33 +02:00
|
|
|
httpTasks.add(img.httpTask);
|
|
|
|
runHttpTasks(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
private void httpFileLoadError(String location) {
|
|
|
|
CacheImage img = imageLoadingByUrl.get(location);
|
|
|
|
if (img == null) {
|
2014-08-22 16:24:33 +02:00
|
|
|
return;
|
|
|
|
}
|
2015-01-02 23:15:07 +01:00
|
|
|
HttpImageTask oldTask = img.httpTask;
|
|
|
|
img.httpTask = new HttpImageTask(oldTask.cacheImage, oldTask.imageSize);
|
|
|
|
httpTasks.add(img.httpTask);
|
|
|
|
runHttpTasks(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void fileDidLoaded(String location, File finalFile, File tempFile) {
|
2014-08-22 16:24:33 +02:00
|
|
|
CacheImage img = imageLoadingByUrl.get(location);
|
|
|
|
if (img == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
imageLoadingByUrl.remove(location);
|
|
|
|
for (ImageReceiver imageReceiver : img.imageViewArray) {
|
|
|
|
String key = imageReceiver.getKey();
|
|
|
|
if (key == null) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
CacheImage cacheImage = imageLoadingByKeys.get(key);
|
|
|
|
if (cacheImage == null) {
|
|
|
|
cacheImage = new CacheImage();
|
|
|
|
cacheImage.finalFilePath = finalFile;
|
|
|
|
cacheImage.tempFilePath = tempFile;
|
|
|
|
cacheImage.key = key;
|
|
|
|
cacheImage.httpUrl = img.httpUrl;
|
|
|
|
cacheImage.cacheTask = new CacheOutTask(cacheImage);
|
|
|
|
if (imageReceiver.getFilter() != null) {
|
|
|
|
cacheImage.filter = imageReceiver.getFilter();
|
|
|
|
}
|
|
|
|
imageLoadingByKeys.put(cacheImage.key, cacheImage);
|
2014-09-14 01:40:36 +02:00
|
|
|
cacheOutQueue.postRunnable(cacheImage.cacheTask);
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
cacheImage.addImageView(imageReceiver);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void fileDidFailedLoad(String location) {
|
|
|
|
CacheImage img = imageLoadingByUrl.get(location);
|
|
|
|
if (img != null) {
|
|
|
|
img.setImageAndClear(null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void runHttpTasks(boolean complete) {
|
|
|
|
if (complete) {
|
|
|
|
currentHttpTasksCount--;
|
|
|
|
}
|
|
|
|
while (currentHttpTasksCount < 1 && !httpTasks.isEmpty()) {
|
2015-01-02 23:15:07 +01:00
|
|
|
HttpImageTask task = httpTasks.poll();
|
2014-08-22 16:24:33 +02:00
|
|
|
if (android.os.Build.VERSION.SDK_INT >= 11) {
|
|
|
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
|
|
|
} else {
|
|
|
|
task.execute(null, null, null);
|
|
|
|
}
|
|
|
|
currentHttpTasksCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
public void loadHttpFile(String url, String extension) {
|
|
|
|
if (url == null || url.length() == 0 || httpFileLoadTasksByKeys.containsKey(url)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
String ext = extension;
|
|
|
|
if (ext == null) {
|
|
|
|
int idx = url.lastIndexOf(".");
|
|
|
|
if (idx != -1) {
|
|
|
|
ext = url.substring(idx + 1);
|
|
|
|
}
|
|
|
|
if (ext == null || ext.length() == 0 || ext.length() > 4) {
|
|
|
|
ext = "jpg";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
File file = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(url) + "_temp." + ext);
|
|
|
|
file.delete();
|
|
|
|
|
|
|
|
HttpFileTask task = new HttpFileTask(url, file, ext);
|
|
|
|
httpFileLoadTasks.add(task);
|
|
|
|
httpFileLoadTasksByKeys.put(url, task);
|
|
|
|
runHttpFileLoadTasks(null, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void cancelLoadHttpFile(String url) {
|
|
|
|
HttpFileTask task = httpFileLoadTasksByKeys.get(url);
|
|
|
|
if (task != null) {
|
|
|
|
task.cancel(true);
|
|
|
|
httpFileLoadTasksByKeys.remove(url);
|
|
|
|
httpFileLoadTasks.remove(task);
|
|
|
|
}
|
|
|
|
Runnable runnable = retryHttpsTasks.get(url);
|
|
|
|
if (runnable != null) {
|
|
|
|
AndroidUtilities.cancelRunOnUIThread(runnable);
|
|
|
|
}
|
|
|
|
runHttpFileLoadTasks(null, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void runHttpFileLoadTasks(HttpFileTask oldTask, int reason) {
|
|
|
|
if (oldTask != null) {
|
|
|
|
currentHttpFileLoadTasksCount--;
|
|
|
|
}
|
|
|
|
if (oldTask != null) {
|
|
|
|
if (reason == 1) {
|
|
|
|
if (oldTask.canRetry) {
|
|
|
|
final HttpFileTask newTask = new HttpFileTask(oldTask.url, oldTask.tempFile, oldTask.ext);
|
|
|
|
Runnable runnable = new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
httpFileLoadTasks.add(newTask);
|
|
|
|
runHttpFileLoadTasks(null, 0);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
retryHttpsTasks.put(oldTask.url, runnable);
|
|
|
|
AndroidUtilities.runOnUIThread(runnable, 1000);
|
|
|
|
} else {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.httpFileDidFailedLoad, oldTask.url);
|
|
|
|
}
|
|
|
|
} else if (reason == 2) {
|
|
|
|
httpFileLoadTasksByKeys.remove(oldTask.url);
|
|
|
|
File file = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(oldTask.url) + "." + oldTask.ext);
|
|
|
|
String result = oldTask.tempFile.renameTo(file) ? file.toString() : oldTask.tempFile.toString();
|
|
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.httpFileDidLoaded, oldTask.url, result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (currentHttpFileLoadTasksCount < 2 && !httpFileLoadTasks.isEmpty()) {
|
|
|
|
HttpFileTask task = httpFileLoadTasks.poll();
|
|
|
|
if (android.os.Build.VERSION.SDK_INT >= 11) {
|
|
|
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
|
|
|
} else {
|
|
|
|
task.execute(null, null, null);
|
|
|
|
}
|
|
|
|
currentHttpFileLoadTasksCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-22 16:24:33 +02:00
|
|
|
public static Bitmap loadBitmap(String path, Uri uri, float maxWidth, float maxHeight) {
|
|
|
|
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
|
|
|
|
bmOptions.inJustDecodeBounds = true;
|
|
|
|
FileDescriptor fileDescriptor = null;
|
|
|
|
ParcelFileDescriptor parcelFD = null;
|
|
|
|
|
|
|
|
if (path == null && uri != null && uri.getScheme() != null) {
|
|
|
|
String imageFilePath = null;
|
|
|
|
if (uri.getScheme().contains("file")) {
|
|
|
|
path = uri.getPath();
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
path = Utilities.getPath(uri);
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (path != null) {
|
|
|
|
BitmapFactory.decodeFile(path, bmOptions);
|
|
|
|
} else if (uri != null) {
|
|
|
|
boolean error = false;
|
|
|
|
try {
|
|
|
|
parcelFD = ApplicationLoader.applicationContext.getContentResolver().openFileDescriptor(uri, "r");
|
|
|
|
fileDescriptor = parcelFD.getFileDescriptor();
|
|
|
|
BitmapFactory.decodeFileDescriptor(fileDescriptor, null, bmOptions);
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
try {
|
|
|
|
if (parcelFD != null) {
|
|
|
|
parcelFD.close();
|
|
|
|
}
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e2) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
float photoW = bmOptions.outWidth;
|
|
|
|
float photoH = bmOptions.outHeight;
|
|
|
|
float scaleFactor = Math.max(photoW / maxWidth, photoH / maxHeight);
|
|
|
|
if (scaleFactor < 1) {
|
|
|
|
scaleFactor = 1;
|
|
|
|
}
|
|
|
|
bmOptions.inJustDecodeBounds = false;
|
|
|
|
bmOptions.inSampleSize = (int)scaleFactor;
|
|
|
|
|
|
|
|
String exifPath = null;
|
|
|
|
if (path != null) {
|
|
|
|
exifPath = path;
|
|
|
|
} else if (uri != null) {
|
|
|
|
exifPath = Utilities.getPath(uri);
|
|
|
|
}
|
|
|
|
|
|
|
|
Matrix matrix = null;
|
|
|
|
|
|
|
|
if (exifPath != null) {
|
|
|
|
ExifInterface exif;
|
|
|
|
try {
|
|
|
|
exif = new ExifInterface(exifPath);
|
|
|
|
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
|
|
|
|
matrix = new Matrix();
|
|
|
|
switch (orientation) {
|
|
|
|
case ExifInterface.ORIENTATION_ROTATE_90:
|
|
|
|
matrix.postRotate(90);
|
|
|
|
break;
|
|
|
|
case ExifInterface.ORIENTATION_ROTATE_180:
|
|
|
|
matrix.postRotate(180);
|
|
|
|
break;
|
|
|
|
case ExifInterface.ORIENTATION_ROTATE_270:
|
|
|
|
matrix.postRotate(270);
|
|
|
|
break;
|
|
|
|
}
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Bitmap b = null;
|
|
|
|
if (path != null) {
|
|
|
|
try {
|
|
|
|
b = BitmapFactory.decodeFile(path, bmOptions);
|
|
|
|
if (b != null) {
|
|
|
|
b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
|
|
|
|
}
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
ImageLoader.getInstance().clearMemory();
|
2014-10-01 21:55:24 +02:00
|
|
|
try {
|
|
|
|
if (b == null) {
|
|
|
|
b = BitmapFactory.decodeFile(path, bmOptions);
|
|
|
|
}
|
|
|
|
if (b != null) {
|
|
|
|
b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
|
|
|
|
}
|
|
|
|
} catch (Throwable e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (uri != null) {
|
|
|
|
try {
|
|
|
|
b = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, bmOptions);
|
|
|
|
if (b != null) {
|
|
|
|
b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
|
|
|
|
}
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
} finally {
|
|
|
|
try {
|
|
|
|
if (parcelFD != null) {
|
|
|
|
parcelFD.close();
|
|
|
|
}
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-08-22 16:24:33 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2014-11-17 23:04:31 +01:00
|
|
|
private static TLRPC.PhotoSize scaleAndSaveImageInternal(Bitmap bitmap, int w, int h, float photoW, float photoH, float scaleFactor, int quality, boolean cache, boolean scaleAnyway) throws Exception {
|
2014-10-01 21:55:24 +02:00
|
|
|
Bitmap scaledBitmap = null;
|
2014-11-17 23:04:31 +01:00
|
|
|
if (scaleFactor > 1 || scaleAnyway) {
|
2014-10-01 21:55:24 +02:00
|
|
|
scaledBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
|
|
|
|
} else {
|
|
|
|
scaledBitmap = bitmap;
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
|
|
|
|
TLRPC.TL_fileLocation location = new TLRPC.TL_fileLocation();
|
|
|
|
location.volume_id = Integer.MIN_VALUE;
|
|
|
|
location.dc_id = Integer.MIN_VALUE;
|
|
|
|
location.local_id = UserConfig.lastLocalId;
|
|
|
|
UserConfig.lastLocalId--;
|
|
|
|
TLRPC.PhotoSize size;
|
|
|
|
if (!cache) {
|
|
|
|
size = new TLRPC.TL_photoSize();
|
|
|
|
} else {
|
|
|
|
size = new TLRPC.TL_photoCachedSize();
|
|
|
|
}
|
|
|
|
size.location = location;
|
2014-10-01 21:55:24 +02:00
|
|
|
size.w = scaledBitmap.getWidth();
|
|
|
|
size.h = scaledBitmap.getHeight();
|
|
|
|
if (size.w <= 100 && size.h <= 100) {
|
|
|
|
size.type = "s";
|
|
|
|
} else if (size.w <= 320 && size.h <= 320) {
|
|
|
|
size.type = "m";
|
|
|
|
} else if (size.w <= 800 && size.h <= 800) {
|
|
|
|
size.type = "x";
|
|
|
|
} else if (size.w <= 1280 && size.h <= 1280) {
|
|
|
|
size.type = "y";
|
|
|
|
} else {
|
|
|
|
size.type = "w";
|
|
|
|
}
|
2014-09-30 00:48:11 +02:00
|
|
|
|
|
|
|
if (!cache) {
|
|
|
|
String fileName = location.volume_id + "_" + location.local_id + ".jpg";
|
|
|
|
final File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
|
|
|
|
FileOutputStream stream = new FileOutputStream(cacheFile);
|
|
|
|
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream);
|
|
|
|
size.size = (int)stream.getChannel().size();
|
|
|
|
} else {
|
|
|
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
|
|
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream);
|
|
|
|
size.bytes = stream.toByteArray();
|
|
|
|
size.size = size.bytes.length;
|
|
|
|
}
|
|
|
|
if (scaledBitmap != bitmap) {
|
|
|
|
scaledBitmap.recycle();
|
|
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache) {
|
2014-11-17 23:04:31 +01:00
|
|
|
return scaleAndSaveImage(bitmap, maxWidth, maxHeight, quality, cache, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache, int minWidth, int minHeight) {
|
2014-09-30 00:48:11 +02:00
|
|
|
if (bitmap == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
float photoW = bitmap.getWidth();
|
|
|
|
float photoH = bitmap.getHeight();
|
|
|
|
if (photoW == 0 || photoH == 0) {
|
|
|
|
return null;
|
|
|
|
}
|
2014-11-17 23:04:31 +01:00
|
|
|
boolean scaleAnyway = false;
|
2014-09-30 00:48:11 +02:00
|
|
|
float scaleFactor = Math.max(photoW / maxWidth, photoH / maxHeight);
|
2015-01-02 23:15:07 +01:00
|
|
|
if (minWidth != 0 && minHeight != 0 && (photoW < minWidth || photoH < minHeight)) {
|
2014-11-17 23:04:31 +01:00
|
|
|
scaleFactor = Math.max(photoW / minWidth, photoH / minHeight);
|
|
|
|
scaleAnyway = true;
|
|
|
|
}
|
2014-09-30 00:48:11 +02:00
|
|
|
int w = (int)(photoW / scaleFactor);
|
|
|
|
int h = (int)(photoH / scaleFactor);
|
|
|
|
if (h == 0 || w == 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2014-08-22 16:24:33 +02:00
|
|
|
try {
|
2014-11-17 23:04:31 +01:00
|
|
|
return scaleAndSaveImageInternal(bitmap, w, h, photoW, photoH, scaleFactor, quality, cache, scaleAnyway);
|
2014-09-14 01:40:36 +02:00
|
|
|
} catch (Throwable e) {
|
2014-09-30 00:48:11 +02:00
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
ImageLoader.getInstance().clearMemory();
|
|
|
|
System.gc();
|
|
|
|
try {
|
2014-11-17 23:04:31 +01:00
|
|
|
return scaleAndSaveImageInternal(bitmap, w, h, photoW, photoH, scaleFactor, quality, cache, scaleAnyway);
|
2014-09-30 00:48:11 +02:00
|
|
|
} catch (Throwable e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
return null;
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
}
|
2015-01-02 23:15:07 +01:00
|
|
|
|
|
|
|
public static String getHttpUrlExtension(String url) {
|
|
|
|
String ext = null;
|
|
|
|
int idx = url.lastIndexOf(".");
|
|
|
|
if (idx != -1) {
|
|
|
|
ext = url.substring(idx + 1);
|
|
|
|
}
|
|
|
|
if (ext == null || ext.length() == 0 || ext.length() > 4) {
|
|
|
|
ext = "jpg";
|
|
|
|
}
|
|
|
|
return ext;
|
|
|
|
}
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|