show a preview for video files
This commit is contained in:
parent
01a4d2ea25
commit
be4aa2afc9
59
art/play_video.svg
Normal file
59
art/play_video.svg
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="48"
|
||||||
|
height="48"
|
||||||
|
viewBox="0 0 48 48"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="play_video.svg">
|
||||||
|
<metadata
|
||||||
|
id="metadata12">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs10" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1916"
|
||||||
|
inkscape:window-height="1156"
|
||||||
|
id="namedview8"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="4.9166667"
|
||||||
|
inkscape:cx="0.91525424"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="20"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="svg2" />
|
||||||
|
<path
|
||||||
|
d="M0 0h48v48H0z"
|
||||||
|
fill="none"
|
||||||
|
id="path4" />
|
||||||
|
<path
|
||||||
|
d="M20 33l12-9-12-9v18zm4-29C12.95 4 4 12.95 4 24s8.95 20 20 20 20-8.95 20-20S35.05 4 24 4zm0 36c-8.82 0-16-7.18-16-16S15.18 8 24 8s16 7.18 16 16-7.18 16-16 16z"
|
||||||
|
id="path6"
|
||||||
|
style="fill:#ffffff;fill-opacity:0.7019608;opacity:1;stroke:none;stroke-opacity:0.38039216" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -13,6 +13,7 @@ resolutions = {
|
||||||
images = {
|
images = {
|
||||||
'ic_launcher.svg' => ['ic_launcher', 48],
|
'ic_launcher.svg' => ['ic_launcher', 48],
|
||||||
'main_logo.svg' => ['main_logo', 200],
|
'main_logo.svg' => ['main_logo', 200],
|
||||||
|
'play_video.svg' => ['play_video', 96],
|
||||||
'conversations_mono.svg' => ['ic_notification', 24],
|
'conversations_mono.svg' => ['ic_notification', 24],
|
||||||
'ic_received_indicator.svg' => ['ic_received_indicator', 12],
|
'ic_received_indicator.svg' => ['ic_received_indicator', 12],
|
||||||
'ic_send_text_offline.svg' => ['ic_send_text_offline', 36],
|
'ic_send_text_offline.svg' => ['ic_send_text_offline', 36],
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
|
import android.media.MediaMetadataRetriever;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
@ -380,21 +381,43 @@ public class FileBackend {
|
||||||
if (thumbnail != null) {
|
if (thumbnail != null) {
|
||||||
return thumbnail;
|
return thumbnail;
|
||||||
}
|
}
|
||||||
File file = getFile(message);
|
DownloadableFile file = getFile(message);
|
||||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
if (file.getMimeType().startsWith("video/")) {
|
||||||
options.inSampleSize = calcSampleSize(file, size);
|
thumbnail = getVideoPreview(file, size);
|
||||||
Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
|
} else {
|
||||||
|
Bitmap fullsize = getFullsizeImagePreview(file, size);
|
||||||
if (fullsize == null) {
|
if (fullsize == null) {
|
||||||
throw new FileNotFoundException();
|
throw new FileNotFoundException();
|
||||||
}
|
}
|
||||||
thumbnail = resize(fullsize, size);
|
thumbnail = resize(fullsize, size);
|
||||||
thumbnail = rotate(thumbnail, getRotation(file));
|
thumbnail = rotate(thumbnail, getRotation(file));
|
||||||
|
}
|
||||||
this.mXmppConnectionService.getBitmapCache().put(uuid, thumbnail);
|
this.mXmppConnectionService.getBitmapCache().put(uuid, thumbnail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return thumbnail;
|
return thumbnail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Bitmap getFullsizeImagePreview(File file, int size) {
|
||||||
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
|
options.inSampleSize = calcSampleSize(file, size);
|
||||||
|
return BitmapFactory.decodeFile(file.getAbsolutePath(), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap getVideoPreview(File file, int size) {
|
||||||
|
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
|
||||||
|
metadataRetriever.setDataSource(file.getAbsolutePath());
|
||||||
|
Bitmap frame = metadataRetriever.getFrameAtTime(0);
|
||||||
|
metadataRetriever.release();
|
||||||
|
frame = resize(frame, size);
|
||||||
|
Canvas canvas = new Canvas(frame);
|
||||||
|
Bitmap play = BitmapFactory.decodeResource(mXmppConnectionService.getResources(), R.drawable.play_video);
|
||||||
|
float x = (frame.getWidth() - play.getWidth()) / 2.0f;
|
||||||
|
float y = (frame.getHeight() - play.getHeight()) / 2.0f;
|
||||||
|
canvas.drawBitmap(play,x,y,null);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
public Uri getTakePhotoUri() {
|
public Uri getTakePhotoUri() {
|
||||||
StringBuilder pathBuilder = new StringBuilder();
|
StringBuilder pathBuilder = new StringBuilder();
|
||||||
pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
|
pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
|
||||||
|
@ -656,7 +679,31 @@ public class FileBackend {
|
||||||
|
|
||||||
public void updateFileParams(Message message, URL url) {
|
public void updateFileParams(Message message, URL url) {
|
||||||
DownloadableFile file = getFile(message);
|
DownloadableFile file = getFile(message);
|
||||||
if (message.getType() == Message.TYPE_IMAGE || file.getMimeType().startsWith("image/")) {
|
boolean image = message.getType() == Message.TYPE_IMAGE || file.getMimeType().startsWith("image/");
|
||||||
|
boolean video = message.getMimeType().startsWith("video/");
|
||||||
|
if (image || video) {
|
||||||
|
try {
|
||||||
|
Dimensions dimensions = image ? getImageDimensions(file) : getVideoDimensions(file);
|
||||||
|
if (url == null) {
|
||||||
|
message.setBody(Long.toString(file.getSize()) + '|' + dimensions.width + '|' + dimensions.height);
|
||||||
|
} else {
|
||||||
|
message.setBody(url.toString() + "|" + Long.toString(file.getSize()) + '|' + dimensions.width + '|' + dimensions.height);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} catch (NotAVideoFile notAVideoFile) {
|
||||||
|
Log.d(Config.LOGTAG,"file with mime type "+file.getMimeType()+" was not a video file");
|
||||||
|
//fall threw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (url != null) {
|
||||||
|
message.setBody(url.toString()+"|"+Long.toString(file.getSize()));
|
||||||
|
} else {
|
||||||
|
message.setBody(Long.toString(file.getSize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dimensions getImageDimensions(File file) {
|
||||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
options.inJustDecodeBounds = true;
|
options.inJustDecodeBounds = true;
|
||||||
BitmapFactory.decodeFile(file.getAbsolutePath(), options);
|
BitmapFactory.decodeFile(file.getAbsolutePath(), options);
|
||||||
|
@ -664,19 +711,64 @@ public class FileBackend {
|
||||||
boolean rotated = rotation == 90 || rotation == 270;
|
boolean rotated = rotation == 90 || rotation == 270;
|
||||||
int imageHeight = rotated ? options.outWidth : options.outHeight;
|
int imageHeight = rotated ? options.outWidth : options.outHeight;
|
||||||
int imageWidth = rotated ? options.outHeight : options.outWidth;
|
int imageWidth = rotated ? options.outHeight : options.outWidth;
|
||||||
if (url == null) {
|
return new Dimensions(imageHeight, imageWidth);
|
||||||
message.setBody(Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight);
|
}
|
||||||
} else {
|
|
||||||
message.setBody(url.toString()+"|"+Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight);
|
private Dimensions getVideoDimensions(File file) throws NotAVideoFile {
|
||||||
|
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
|
||||||
|
metadataRetriever.setDataSource(file.getAbsolutePath());
|
||||||
|
String hasVideo = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO);
|
||||||
|
if (hasVideo == null) {
|
||||||
|
throw new NotAVideoFile();
|
||||||
|
}
|
||||||
|
int rotation = extractRotationFromMediaRetriever(metadataRetriever);
|
||||||
|
boolean rotated = rotation == 90 || rotation == 270;
|
||||||
|
int height;
|
||||||
|
try {
|
||||||
|
String h = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
|
||||||
|
height = Integer.parseInt(h);
|
||||||
|
} catch (Exception e) {
|
||||||
|
height = -1;
|
||||||
|
}
|
||||||
|
int width;
|
||||||
|
try {
|
||||||
|
String w = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
|
||||||
|
width = Integer.parseInt(w);
|
||||||
|
} catch (Exception e) {
|
||||||
|
width = -1;
|
||||||
|
}
|
||||||
|
metadataRetriever.release();
|
||||||
|
Log.d(Config.LOGTAG,"extracted video dims "+width+"x"+height);
|
||||||
|
return rotated ? new Dimensions(width, height) : new Dimensions(height, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int extractRotationFromMediaRetriever(MediaMetadataRetriever metadataRetriever) {
|
||||||
|
int rotation;
|
||||||
|
if (Build.VERSION.SDK_INT >= 17) {
|
||||||
|
String r = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
|
||||||
|
try {
|
||||||
|
rotation = Integer.parseInt(r);
|
||||||
|
} catch (Exception e) {
|
||||||
|
rotation = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (url != null) {
|
rotation = 0;
|
||||||
message.setBody(url.toString()+"|"+Long.toString(file.getSize()));
|
}
|
||||||
} else {
|
return rotation;
|
||||||
message.setBody(Long.toString(file.getSize()));
|
}
|
||||||
|
|
||||||
|
private class Dimensions {
|
||||||
|
public final int width;
|
||||||
|
public final int height;
|
||||||
|
|
||||||
|
public Dimensions(int height, int width) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class NotAVideoFile extends Exception {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FileCopyException extends Exception {
|
public class FileCopyException extends Exception {
|
||||||
|
|
BIN
src/main/res/drawable-hdpi/play_video.png
Normal file
BIN
src/main/res/drawable-hdpi/play_video.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
BIN
src/main/res/drawable-mdpi/play_video.png
Normal file
BIN
src/main/res/drawable-mdpi/play_video.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
src/main/res/drawable-xhdpi/play_video.png
Normal file
BIN
src/main/res/drawable-xhdpi/play_video.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5 KiB |
BIN
src/main/res/drawable-xxhdpi/play_video.png
Normal file
BIN
src/main/res/drawable-xxhdpi/play_video.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
BIN
src/main/res/drawable-xxxhdpi/play_video.png
Normal file
BIN
src/main/res/drawable-xxxhdpi/play_video.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Loading…
Reference in a new issue