FileBackend.java

  1package eu.siacs.conversations.persistance;
  2
  3import java.io.File;
  4import java.io.FileInputStream;
  5import java.io.FileNotFoundException;
  6import java.io.FileOutputStream;
  7import java.io.IOException;
  8import java.io.InputStream;
  9import java.io.OutputStream;
 10import java.lang.ref.WeakReference;
 11
 12import android.content.Context;
 13import android.graphics.Bitmap;
 14import android.graphics.BitmapFactory;
 15import android.net.Uri;
 16import android.util.Log;
 17import android.util.LruCache;
 18import android.view.View;
 19import android.widget.ImageView;
 20import android.widget.TextView;
 21import eu.siacs.conversations.entities.Account;
 22import eu.siacs.conversations.entities.Conversation;
 23import eu.siacs.conversations.entities.Message;
 24import eu.siacs.conversations.services.XmppConnectionService;
 25import eu.siacs.conversations.xmpp.jingle.JingleFile;
 26
 27public class FileBackend {
 28
 29	private static int IMAGE_SIZE = 1920;
 30
 31	private Context context;
 32	private LruCache<String, Bitmap> thumbnailCache;
 33
 34	public FileBackend(Context context) {
 35		this.context = context;
 36		int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
 37		int cacheSize = maxMemory / 8;
 38		thumbnailCache = new LruCache<String, Bitmap>(cacheSize) {
 39			@Override
 40			protected int sizeOf(String key, Bitmap bitmap) {
 41				return bitmap.getByteCount() / 1024;
 42			}
 43		};
 44
 45	}
 46	
 47	public LruCache<String, Bitmap> getThumbnailCache() {
 48		return thumbnailCache;
 49	}
 50	
 51	public JingleFile getJingleFile(Message message) {
 52		return getJingleFile(message, true);
 53	}
 54
 55	public JingleFile getJingleFile(Message message, boolean decrypted) {
 56		Conversation conversation = message.getConversation();
 57		String prefix = context.getFilesDir().getAbsolutePath();
 58		String path = prefix + "/" + conversation.getAccount().getJid() + "/"
 59				+ conversation.getContactJid();
 60		String filename;
 61		if ((decrypted)||(message.getEncryption() == Message.ENCRYPTION_NONE)) {
 62			filename = message.getUuid() + ".webp";
 63		} else {
 64			filename = message.getUuid() + ".webp.pgp";
 65		}
 66		return new JingleFile(path + "/" + filename);
 67	}
 68
 69	public Bitmap resize(Bitmap originalBitmap, int size) {
 70		int w = originalBitmap.getWidth();
 71		int h = originalBitmap.getHeight();
 72		if (Math.max(w, h) > size) {
 73			int scalledW;
 74			int scalledH;
 75			if (w <= h) {
 76				scalledW = (int) (w / ((double) h / size));
 77				scalledH = size;
 78			} else {
 79				scalledW = size;
 80				scalledH = (int) (h / ((double) w / size));
 81			}
 82			Bitmap scalledBitmap = Bitmap.createScaledBitmap(originalBitmap,
 83					scalledW, scalledH, true);
 84			return scalledBitmap;
 85		} else {
 86			return originalBitmap;
 87		}
 88	}
 89
 90	public JingleFile copyImageToPrivateStorage(Message message, Uri image) {
 91		try {
 92			InputStream is;
 93			if (image!=null) {
 94				Log.d("xmppService","copying file: "+image.toString()+ " to internal storage");
 95				is = context.getContentResolver()
 96					.openInputStream(image);
 97			} else {
 98				Log.d("xmppService","copying file from incoming to internal storage");
 99				is = new FileInputStream(getIncomingFile());
100			}
101			JingleFile file = getJingleFile(message);
102			file.getParentFile().mkdirs();
103			file.createNewFile();
104			OutputStream os = new FileOutputStream(file);
105			Bitmap originalBitmap = BitmapFactory.decodeStream(is);
106			is.close();
107			if (image==null) {
108				Log.d("xmppService","delete incoming file");
109				getIncomingFile().delete();
110			}
111			Bitmap scalledBitmap = resize(originalBitmap, IMAGE_SIZE);
112			boolean success = scalledBitmap.compress(
113					Bitmap.CompressFormat.WEBP, 75, os);
114			if (!success) {
115				return null;
116			}
117			os.flush();
118			os.close();
119			long size = file.getSize();
120			int width = scalledBitmap.getWidth();
121			int height = scalledBitmap.getHeight();
122			message.setBody(""+size+","+width+","+height);
123			return file;
124		} catch (FileNotFoundException e) {
125			return null;
126		} catch (IOException e) {
127			return null;
128		} catch (SecurityException e) {
129			return null;
130		}
131	}
132
133	public Bitmap getImageFromMessage(Message message) {
134		return BitmapFactory.decodeFile(getJingleFile(message)
135				.getAbsolutePath());
136	}
137
138	public Bitmap getThumbnail(Message message, int size, boolean cacheOnly)
139			throws FileNotFoundException {
140		Bitmap thumbnail = thumbnailCache.get(message.getUuid());
141		if ((thumbnail == null)&&(!cacheOnly)) {
142			Bitmap fullsize = BitmapFactory.decodeFile(getJingleFile(message)
143					.getAbsolutePath());
144			if (fullsize == null) {
145				throw new FileNotFoundException();
146			}
147			thumbnail = resize(fullsize, size);
148			this.thumbnailCache.put(message.getUuid(), thumbnail);
149		}
150		return thumbnail;
151	}
152
153	public void removeFiles(Conversation conversation) {
154		String prefix = context.getFilesDir().getAbsolutePath();
155		String path = prefix + "/" + conversation.getAccount().getJid() + "/"
156				+ conversation.getContactJid();
157		File file = new File(path);
158		try {
159			this.deleteFile(file);
160		} catch (IOException e) {
161			Log.d("xmppService",
162					"error deleting file: " + file.getAbsolutePath());
163		}
164	}
165
166	private void deleteFile(File f) throws IOException {
167		if (f.isDirectory()) {
168			for (File c : f.listFiles())
169				deleteFile(c);
170		}
171		f.delete();
172	}
173
174	public File getIncomingFile() {
175		return new File(context.getFilesDir().getAbsolutePath()+"/incoming");
176	}
177}