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.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.pdf.PdfRenderer;
|
||||
import android.media.MediaMetadataRetriever;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
|
@ -25,6 +26,7 @@ import android.system.Os;
|
|||
import android.system.StructStat;
|
||||
import android.util.Base64;
|
||||
import android.util.Base64OutputStream;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.LruCache;
|
||||
|
||||
|
@ -59,6 +61,7 @@ import eu.siacs.conversations.services.AttachFileToConversationRunnable;
|
|||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.ui.RecordingActivity;
|
||||
import eu.siacs.conversations.ui.util.Attachment;
|
||||
import eu.siacs.conversations.utils.Compatibility;
|
||||
import eu.siacs.conversations.utils.CryptoHelper;
|
||||
import eu.siacs.conversations.utils.ExifHelper;
|
||||
import eu.siacs.conversations.utils.FileUtils;
|
||||
|
@ -509,7 +512,6 @@ public class FileBackend {
|
|||
}
|
||||
|
||||
|
||||
|
||||
public DownloadableFile getFileForPath(String path) {
|
||||
return getFileForPath(path, MimeUtils.guessMimeTypeFromExtension(MimeUtils.extractRelevantExtension(path)));
|
||||
}
|
||||
|
@ -818,7 +820,9 @@ public class FileBackend {
|
|||
}
|
||||
DownloadableFile file = getFile(message);
|
||||
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);
|
||||
} else {
|
||||
Bitmap fullsize = getFullsizeImagePreview(file, size);
|
||||
|
@ -897,8 +901,8 @@ public class FileBackend {
|
|||
}
|
||||
}
|
||||
|
||||
private Bitmap getVideoPreview(File file, int size) {
|
||||
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
|
||||
private Bitmap getVideoPreview(final File file, final int size) {
|
||||
final MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
|
||||
Bitmap frame;
|
||||
try {
|
||||
metadataRetriever.setDataSource(file.getAbsolutePath());
|
||||
|
@ -913,6 +917,24 @@ public class FileBackend {
|
|||
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() {
|
||||
File file;
|
||||
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 video = mime != null && mime.startsWith("video/");
|
||||
final boolean audio = mime != null && mime.startsWith("audio/");
|
||||
final boolean pdf = "application/pdf".equals(mime);
|
||||
final StringBuilder body = new StringBuilder();
|
||||
if (url != null) {
|
||||
body.append(url.toString());
|
||||
}
|
||||
body.append('|').append(file.getSize());
|
||||
if (image || video) {
|
||||
if (image || video || (pdf && Compatibility.runsTwentyOne())) {
|
||||
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()) {
|
||||
body.append('|').append(dimensions.width).append('|').append(dimensions.height);
|
||||
}
|
||||
|
@ -1264,6 +1294,45 @@ public class FileBackend {
|
|||
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) {
|
||||
if (avatar == null) {
|
||||
return null;
|
||||
|
@ -1275,10 +1344,6 @@ public class FileBackend {
|
|||
return bm;
|
||||
}
|
||||
|
||||
public boolean isFileAvailable(Message message) {
|
||||
return getFile(message).exists();
|
||||
}
|
||||
|
||||
private static class Dimensions {
|
||||
public final int width;
|
||||
public final int height;
|
||||
|
|
|
@ -540,15 +540,15 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
|||
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);
|
||||
viewHolder.download_button.setVisibility(View.GONE);
|
||||
viewHolder.audioPlayer.setVisibility(View.GONE);
|
||||
viewHolder.image.setVisibility(View.VISIBLE);
|
||||
FileParams params = message.getFileParams();
|
||||
double target = metrics.density * 288;
|
||||
int scaledW;
|
||||
int scaledH;
|
||||
final FileParams params = message.getFileParams();
|
||||
final double target = metrics.density * 288;
|
||||
final int scaledW;
|
||||
final int scaledH;
|
||||
if (Math.max(params.height, params.width) * metrics.density <= target) {
|
||||
scaledW = (int) (params.width * 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) {
|
||||
if (message.getFileParams().width > 0 && message.getFileParams().height > 0) {
|
||||
displayImageMessage(viewHolder, message, darkBackground);
|
||||
displayMediaPreviewMessage(viewHolder, message, darkBackground);
|
||||
} else if (message.getFileParams().runtime > 0) {
|
||||
displayAudioMessage(viewHolder, message, darkBackground);
|
||||
} 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;
|
||||
}
|
||||
|
||||
public static boolean runsTwentySix() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
public static boolean runsTwentyOne() {
|
||||
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;
|
||||
}
|
||||
|
||||
public static boolean runsTwentySix() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
}
|
||||
|
||||
public static boolean twentyEight() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue