display PDF previews
This commit is contained in:
parent
6acb15dd15
commit
2aee26c49a
|
@ -11,6 +11,7 @@ import android.graphics.Color;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.pdf.PdfRenderer;
|
||||||
import android.media.MediaMetadataRetriever;
|
import android.media.MediaMetadataRetriever;
|
||||||
import android.media.MediaScannerConnection;
|
import android.media.MediaScannerConnection;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
@ -25,6 +26,7 @@ import android.system.Os;
|
||||||
import android.system.StructStat;
|
import android.system.StructStat;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Base64OutputStream;
|
import android.util.Base64OutputStream;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.LruCache;
|
import android.util.LruCache;
|
||||||
|
|
||||||
|
@ -59,6 +61,7 @@ import eu.siacs.conversations.services.AttachFileToConversationRunnable;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.ui.RecordingActivity;
|
import eu.siacs.conversations.ui.RecordingActivity;
|
||||||
import eu.siacs.conversations.ui.util.Attachment;
|
import eu.siacs.conversations.ui.util.Attachment;
|
||||||
|
import eu.siacs.conversations.utils.Compatibility;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.ExifHelper;
|
import eu.siacs.conversations.utils.ExifHelper;
|
||||||
import eu.siacs.conversations.utils.FileUtils;
|
import eu.siacs.conversations.utils.FileUtils;
|
||||||
|
@ -509,7 +512,6 @@ public class FileBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public DownloadableFile getFileForPath(String path) {
|
public DownloadableFile getFileForPath(String path) {
|
||||||
return getFileForPath(path, MimeUtils.guessMimeTypeFromExtension(MimeUtils.extractRelevantExtension(path)));
|
return getFileForPath(path, MimeUtils.guessMimeTypeFromExtension(MimeUtils.extractRelevantExtension(path)));
|
||||||
}
|
}
|
||||||
|
@ -818,7 +820,9 @@ public class FileBackend {
|
||||||
}
|
}
|
||||||
DownloadableFile file = getFile(message);
|
DownloadableFile file = getFile(message);
|
||||||
final String mime = file.getMimeType();
|
final String mime = file.getMimeType();
|
||||||
if (mime.startsWith("video/")) {
|
if ("application/pdf".equals(mime) && Compatibility.runsTwentyOne()) {
|
||||||
|
thumbnail = getPdfDocumentPreview(file, size);
|
||||||
|
} else if (mime.startsWith("video/")) {
|
||||||
thumbnail = getVideoPreview(file, size);
|
thumbnail = getVideoPreview(file, size);
|
||||||
} else {
|
} else {
|
||||||
Bitmap fullsize = getFullsizeImagePreview(file, size);
|
Bitmap fullsize = getFullsizeImagePreview(file, size);
|
||||||
|
@ -897,8 +901,8 @@ public class FileBackend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bitmap getVideoPreview(File file, int size) {
|
private Bitmap getVideoPreview(final File file, final int size) {
|
||||||
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
|
final MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
|
||||||
Bitmap frame;
|
Bitmap frame;
|
||||||
try {
|
try {
|
||||||
metadataRetriever.setDataSource(file.getAbsolutePath());
|
metadataRetriever.setDataSource(file.getAbsolutePath());
|
||||||
|
@ -913,6 +917,24 @@ public class FileBackend {
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
private Bitmap getPdfDocumentPreview(final File file, final int size) {
|
||||||
|
try {
|
||||||
|
final ParcelFileDescriptor fileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
|
final PdfRenderer pdfRenderer = new PdfRenderer(fileDescriptor);
|
||||||
|
final PdfRenderer.Page page = pdfRenderer.openPage(0);
|
||||||
|
Dimensions dimensions = scalePdfDimensions(new Dimensions(page.getHeight(), page.getWidth()));
|
||||||
|
final Bitmap rendered = Bitmap.createBitmap(dimensions.width, dimensions.height, Bitmap.Config.ARGB_8888);
|
||||||
|
page.render(rendered, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
|
||||||
|
return rendered;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.d(Config.LOGTAG, "unable to render PDF document preview", e);
|
||||||
|
final Bitmap placeholder = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||||
|
placeholder.eraseColor(0xff000000);
|
||||||
|
return placeholder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Uri getTakePhotoUri() {
|
public Uri getTakePhotoUri() {
|
||||||
File file;
|
File file;
|
||||||
if (Config.ONLY_INTERNAL_STORAGE) {
|
if (Config.ONLY_INTERNAL_STORAGE) {
|
||||||
|
@ -1210,14 +1232,22 @@ public class FileBackend {
|
||||||
final boolean image = message.getType() == Message.TYPE_IMAGE || (mime != null && mime.startsWith("image/"));
|
final boolean image = message.getType() == Message.TYPE_IMAGE || (mime != null && mime.startsWith("image/"));
|
||||||
final boolean video = mime != null && mime.startsWith("video/");
|
final boolean video = mime != null && mime.startsWith("video/");
|
||||||
final boolean audio = mime != null && mime.startsWith("audio/");
|
final boolean audio = mime != null && mime.startsWith("audio/");
|
||||||
|
final boolean pdf = "application/pdf".equals(mime);
|
||||||
final StringBuilder body = new StringBuilder();
|
final StringBuilder body = new StringBuilder();
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
body.append(url.toString());
|
body.append(url.toString());
|
||||||
}
|
}
|
||||||
body.append('|').append(file.getSize());
|
body.append('|').append(file.getSize());
|
||||||
if (image || video) {
|
if (image || video || (pdf && Compatibility.runsTwentyOne())) {
|
||||||
try {
|
try {
|
||||||
Dimensions dimensions = image ? getImageDimensions(file) : getVideoDimensions(file);
|
final Dimensions dimensions;
|
||||||
|
if (video) {
|
||||||
|
dimensions = getVideoDimensions(file);
|
||||||
|
} else if (pdf && Compatibility.runsTwentyOne()) {
|
||||||
|
dimensions = getPdfDocumentDimensions(file);
|
||||||
|
} else {
|
||||||
|
dimensions = getImageDimensions(file);
|
||||||
|
}
|
||||||
if (dimensions.valid()) {
|
if (dimensions.valid()) {
|
||||||
body.append('|').append(dimensions.width).append('|').append(dimensions.height);
|
body.append('|').append(dimensions.width).append('|').append(dimensions.height);
|
||||||
}
|
}
|
||||||
|
@ -1264,6 +1294,45 @@ public class FileBackend {
|
||||||
return getVideoDimensions(metadataRetriever);
|
return getVideoDimensions(metadataRetriever);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
private Dimensions getPdfDocumentDimensions(final File file) {
|
||||||
|
final ParcelFileDescriptor fileDescriptor;
|
||||||
|
try {
|
||||||
|
fileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
|
if (fileDescriptor == null) {
|
||||||
|
return new Dimensions(0, 0);
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return new Dimensions(0, 0);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final PdfRenderer pdfRenderer = new PdfRenderer(fileDescriptor);
|
||||||
|
final PdfRenderer.Page page = pdfRenderer.openPage(0);
|
||||||
|
final int height = page.getHeight();
|
||||||
|
final int width = page.getWidth();
|
||||||
|
page.close();
|
||||||
|
pdfRenderer.close();
|
||||||
|
return scalePdfDimensions(new Dimensions(height, width));
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.d(Config.LOGTAG, "unable to get dimensions for pdf document", e);
|
||||||
|
return new Dimensions(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dimensions scalePdfDimensions(Dimensions in) {
|
||||||
|
final DisplayMetrics displayMetrics = mXmppConnectionService.getResources().getDisplayMetrics();
|
||||||
|
final int target = (int) (displayMetrics.density * 288);
|
||||||
|
final int w, h;
|
||||||
|
if (in.width <= in.height) {
|
||||||
|
w = Math.max((int) (in.width / ((double) in.height / target)), 1);
|
||||||
|
h = target;
|
||||||
|
} else {
|
||||||
|
w = target;
|
||||||
|
h = Math.max((int) (in.height / ((double) in.width / target)), 1);
|
||||||
|
}
|
||||||
|
return new Dimensions(h, w);
|
||||||
|
}
|
||||||
|
|
||||||
public Bitmap getAvatar(String avatar, int size) {
|
public Bitmap getAvatar(String avatar, int size) {
|
||||||
if (avatar == null) {
|
if (avatar == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1275,10 +1344,6 @@ public class FileBackend {
|
||||||
return bm;
|
return bm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFileAvailable(Message message) {
|
|
||||||
return getFile(message).exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Dimensions {
|
private static class Dimensions {
|
||||||
public final int width;
|
public final int width;
|
||||||
public final int height;
|
public final int height;
|
||||||
|
|
|
@ -540,15 +540,15 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
this.audioPlayer.init(audioPlayer, message);
|
this.audioPlayer.init(audioPlayer, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayImageMessage(ViewHolder viewHolder, final Message message, final boolean darkBackground) {
|
private void displayMediaPreviewMessage(ViewHolder viewHolder, final Message message, final boolean darkBackground) {
|
||||||
toggleWhisperInfo(viewHolder, message, darkBackground);
|
toggleWhisperInfo(viewHolder, message, darkBackground);
|
||||||
viewHolder.download_button.setVisibility(View.GONE);
|
viewHolder.download_button.setVisibility(View.GONE);
|
||||||
viewHolder.audioPlayer.setVisibility(View.GONE);
|
viewHolder.audioPlayer.setVisibility(View.GONE);
|
||||||
viewHolder.image.setVisibility(View.VISIBLE);
|
viewHolder.image.setVisibility(View.VISIBLE);
|
||||||
FileParams params = message.getFileParams();
|
final FileParams params = message.getFileParams();
|
||||||
double target = metrics.density * 288;
|
final double target = metrics.density * 288;
|
||||||
int scaledW;
|
final int scaledW;
|
||||||
int scaledH;
|
final int scaledH;
|
||||||
if (Math.max(params.height, params.width) * metrics.density <= target) {
|
if (Math.max(params.height, params.width) * metrics.density <= target) {
|
||||||
scaledW = (int) (params.width * metrics.density);
|
scaledW = (int) (params.width * metrics.density);
|
||||||
scaledH = (int) (params.height * metrics.density);
|
scaledH = (int) (params.height * metrics.density);
|
||||||
|
@ -747,7 +747,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
}
|
}
|
||||||
} else if (message.isFileOrImage() && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) {
|
} else if (message.isFileOrImage() && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) {
|
||||||
if (message.getFileParams().width > 0 && message.getFileParams().height > 0) {
|
if (message.getFileParams().width > 0 && message.getFileParams().height > 0) {
|
||||||
displayImageMessage(viewHolder, message, darkBackground);
|
displayMediaPreviewMessage(viewHolder, message, darkBackground);
|
||||||
} else if (message.getFileParams().runtime > 0) {
|
} else if (message.getFileParams().runtime > 0) {
|
||||||
displayAudioMessage(viewHolder, message, darkBackground);
|
displayAudioMessage(viewHolder, message, darkBackground);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -38,14 +38,18 @@ public class Compatibility {
|
||||||
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
|
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean runsTwentySix() {
|
public static boolean runsTwentyOne() {
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean runsTwentyFour() {
|
private static boolean runsTwentyFour() {
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean runsTwentySix() {
|
||||||
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean twentyEight() {
|
public static boolean twentyEight() {
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue