1package eu.siacs.conversations.persistance;
2
3import java.io.File;
4import java.io.FileNotFoundException;
5import java.io.FileOutputStream;
6import java.io.IOException;
7import java.io.InputStream;
8import java.io.OutputStream;
9import java.lang.ref.WeakReference;
10
11import android.content.Context;
12import android.graphics.Bitmap;
13import android.graphics.BitmapFactory;
14import android.net.Uri;
15import android.util.Log;
16import android.util.LruCache;
17import android.view.View;
18import android.widget.ImageView;
19import android.widget.TextView;
20
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 Conversation conversation = message.getConversation();
53 String prefix = context.getFilesDir().getAbsolutePath();
54 String path = prefix + "/" + conversation.getAccount().getJid() + "/"
55 + conversation.getContactJid();
56 String filename = message.getUuid() + ".webp";
57 return new JingleFile(path + "/" + filename);
58 }
59
60 public Bitmap resize(Bitmap originalBitmap, int size) {
61 int w = originalBitmap.getWidth();
62 int h = originalBitmap.getHeight();
63 if (Math.max(w, h) > size) {
64 int scalledW;
65 int scalledH;
66 if (w <= h) {
67 scalledW = (int) (w / ((double) h / size));
68 scalledH = size;
69 } else {
70 scalledW = size;
71 scalledH = (int) (h / ((double) w / size));
72 }
73 Bitmap scalledBitmap = Bitmap.createScaledBitmap(originalBitmap,
74 scalledW, scalledH, true);
75 return scalledBitmap;
76 } else {
77 return originalBitmap;
78 }
79 }
80
81 public JingleFile copyImageToPrivateStorage(Message message, Uri image) {
82 try {
83 Log.d("xmppService","copying file: "+image.toString()+ " to internal storage");
84 InputStream is = context.getContentResolver()
85 .openInputStream(image);
86 JingleFile file = getJingleFile(message);
87 file.getParentFile().mkdirs();
88 file.createNewFile();
89 OutputStream os = new FileOutputStream(file);
90 Bitmap originalBitmap = BitmapFactory.decodeStream(is);
91 is.close();
92 Bitmap scalledBitmap = resize(originalBitmap, IMAGE_SIZE);
93 boolean success = scalledBitmap.compress(
94 Bitmap.CompressFormat.WEBP, 75, os);
95 if (!success) {
96 // Log.d("xmppService", "couldnt compress");
97 }
98 os.flush();
99 os.close();
100 long size = file.getSize();
101 int width = scalledBitmap.getWidth();
102 int height = scalledBitmap.getHeight();
103 message.setBody(""+size+","+width+","+height);
104 return file;
105 } catch (FileNotFoundException e) {
106 // TODO Auto-generated catch block
107 e.printStackTrace();
108 } catch (IOException e) {
109 // TODO Auto-generated catch block
110 e.printStackTrace();
111 }
112
113 return null;
114 }
115
116 public Bitmap getImageFromMessage(Message message) {
117 return BitmapFactory.decodeFile(getJingleFile(message)
118 .getAbsolutePath());
119 }
120
121 public Bitmap getThumbnail(Message message, int size)
122 throws FileNotFoundException {
123 Bitmap thumbnail = thumbnailCache.get(message.getUuid());
124 if (thumbnail == null) {
125 Bitmap fullsize = BitmapFactory.decodeFile(getJingleFile(message)
126 .getAbsolutePath());
127 if (fullsize == null) {
128 throw new FileNotFoundException();
129 }
130 thumbnail = resize(fullsize, size);
131 this.thumbnailCache.put(message.getUuid(), thumbnail);
132 }
133 return thumbnail;
134 }
135
136 public void getThumbnailAsync(final Message message, final int size, ImageView imageView, TextView textView) {
137
138 Bitmap thumbnail = thumbnailCache.get(message.getUuid());
139 if (thumbnail == null) {
140 final WeakReference<ImageView> image = new WeakReference<ImageView>(imageView);
141 final WeakReference<TextView> text = new WeakReference<TextView>(textView);
142 new Thread(new Runnable() {
143
144 @Override
145 public void run() {
146 if (image.get()!=null) {
147 image.get().setVisibility(View.GONE);
148 }
149 if (text.get()!=null) {
150 text.get().setVisibility(View.VISIBLE);
151 text.get().setText("loading image");
152 }
153 Bitmap fullsize = BitmapFactory.decodeFile(getJingleFile(message)
154 .getAbsolutePath());
155 if (fullsize!=null) {
156 Bitmap thumbnail = resize(fullsize, size);
157 thumbnailCache.put(message.getUuid(), thumbnail);
158 if (image.get()!=null) {
159 image.get().setVisibility(View.VISIBLE);
160 image.get().setImageBitmap(thumbnail);
161 }
162 if (text.get()!=null) {
163 text.get().setVisibility(View.GONE);
164 }
165 }
166 }
167 }).start();
168 } else {
169 textView.setVisibility(View.GONE);
170 imageView.setVisibility(View.VISIBLE);
171 imageView.setImageBitmap(thumbnail);
172 }
173 }
174
175 public void removeFiles(Conversation conversation) {
176 String prefix = context.getFilesDir().getAbsolutePath();
177 String path = prefix + "/" + conversation.getAccount().getJid() + "/"
178 + conversation.getContactJid();
179 File file = new File(path);
180 try {
181 this.deleteFile(file);
182 } catch (IOException e) {
183 Log.d("xmppService",
184 "error deleting file: " + file.getAbsolutePath());
185 }
186 }
187
188 private void deleteFile(File f) throws IOException {
189 if (f.isDirectory()) {
190 for (File c : f.listFiles())
191 deleteFile(c);
192 }
193 f.delete();
194 }
195}