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}