don’t scall images to a 0 width or height
This commit is contained in:
parent
7ca719b8be
commit
78b56bb904
|
@ -77,12 +77,299 @@ public class FileBackend {
|
|||
this.mXmppConnectionService = service;
|
||||
}
|
||||
|
||||
private static boolean isInDirectoryThatShouldNotBeScanned(Context context, File file) {
|
||||
return isInDirectoryThatShouldNotBeScanned(context, file.getAbsolutePath());
|
||||
}
|
||||
|
||||
public static boolean isInDirectoryThatShouldNotBeScanned(Context context, String path) {
|
||||
for (String type : new String[]{RecordingActivity.STORAGE_DIRECTORY_TYPE_NAME, "Files"}) {
|
||||
if (path.startsWith(getConversationsDirectory(context, type))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static long getFileSize(Context context, Uri uri) {
|
||||
try {
|
||||
final Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
long size = cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE));
|
||||
cursor.close();
|
||||
return size;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean allFilesUnderSize(Context context, List<Uri> uris, long max) {
|
||||
if (max <= 0) {
|
||||
Log.d(Config.LOGTAG, "server did not report max file size for http upload");
|
||||
return true; //exception to be compatible with HTTP Upload < v0.2
|
||||
}
|
||||
for (Uri uri : uris) {
|
||||
String mime = context.getContentResolver().getType(uri);
|
||||
if (mime != null && mime.startsWith("video/")) {
|
||||
try {
|
||||
Dimensions dimensions = FileBackend.getVideoDimensions(context, uri);
|
||||
if (dimensions.getMin() > 720) {
|
||||
Log.d(Config.LOGTAG, "do not consider video file with min width larger than 720 for size check");
|
||||
continue;
|
||||
}
|
||||
} catch (NotAVideoFile notAVideoFile) {
|
||||
//ignore and fall through
|
||||
}
|
||||
}
|
||||
if (FileBackend.getFileSize(context, uri) > max) {
|
||||
Log.d(Config.LOGTAG, "not all files are under " + max + " bytes. suggesting falling back to jingle");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String getConversationsDirectory(Context context, final String type) {
|
||||
if (Config.ONLY_INTERNAL_STORAGE) {
|
||||
return context.getFilesDir().getAbsolutePath() + "/" + type + "/";
|
||||
} else {
|
||||
return getAppMediaDirectory(context) + context.getString(R.string.app_name) + " " + type + "/";
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAppMediaDirectory(Context context) {
|
||||
return Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + context.getString(R.string.app_name) + "/Media/";
|
||||
}
|
||||
|
||||
public static String getConversationsLogsDirectory() {
|
||||
return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Conversations/";
|
||||
}
|
||||
|
||||
private static Bitmap rotate(Bitmap bitmap, int degree) {
|
||||
if (degree == 0) {
|
||||
return bitmap;
|
||||
}
|
||||
int w = bitmap.getWidth();
|
||||
int h = bitmap.getHeight();
|
||||
Matrix mtx = new Matrix();
|
||||
mtx.postRotate(degree);
|
||||
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
|
||||
if (bitmap != null && !bitmap.isRecycled()) {
|
||||
bitmap.recycle();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isPathBlacklisted(String path) {
|
||||
final String androidDataPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/";
|
||||
return path.startsWith(androidDataPath);
|
||||
}
|
||||
|
||||
private static Paint createAntiAliasingPaint() {
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setFilterBitmap(true);
|
||||
paint.setDither(true);
|
||||
return paint;
|
||||
}
|
||||
|
||||
private static String getTakePhotoPath() {
|
||||
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + "/Camera/";
|
||||
}
|
||||
|
||||
public static Uri getUriForFile(Context context, File file) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N || Config.ONLY_INTERNAL_STORAGE) {
|
||||
try {
|
||||
return FileProvider.getUriForFile(context, getAuthority(context), file);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
throw new SecurityException(e);
|
||||
} else {
|
||||
return Uri.fromFile(file);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Uri.fromFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAuthority(Context context) {
|
||||
return context.getPackageName() + FILE_PROVIDER;
|
||||
}
|
||||
|
||||
public static Uri getIndexableTakePhotoUri(Uri original) {
|
||||
if (Config.ONLY_INTERNAL_STORAGE || "file".equals(original.getScheme())) {
|
||||
return original;
|
||||
} else {
|
||||
List<String> segments = original.getPathSegments();
|
||||
return Uri.parse("file://" + getTakePhotoPath() + segments.get(segments.size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasAlpha(final Bitmap bitmap) {
|
||||
for (int x = 0; x < bitmap.getWidth(); ++x) {
|
||||
for (int y = 0; y < bitmap.getWidth(); ++y) {
|
||||
if (Color.alpha(bitmap.getPixel(x, y)) < 255) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int calcSampleSize(File image, int size) {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeFile(image.getAbsolutePath(), options);
|
||||
return calcSampleSize(options, size);
|
||||
}
|
||||
|
||||
public static int calcSampleSize(BitmapFactory.Options options, int size) {
|
||||
int height = options.outHeight;
|
||||
int width = options.outWidth;
|
||||
int inSampleSize = 1;
|
||||
|
||||
if (height > size || width > size) {
|
||||
int halfHeight = height / 2;
|
||||
int halfWidth = width / 2;
|
||||
|
||||
while ((halfHeight / inSampleSize) > size
|
||||
&& (halfWidth / inSampleSize) > size) {
|
||||
inSampleSize *= 2;
|
||||
}
|
||||
}
|
||||
return inSampleSize;
|
||||
}
|
||||
|
||||
private static Dimensions getVideoDimensions(Context context, Uri uri) throws NotAVideoFile {
|
||||
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
|
||||
try {
|
||||
mediaMetadataRetriever.setDataSource(context, uri);
|
||||
} catch (RuntimeException e) {
|
||||
throw new NotAVideoFile(e);
|
||||
}
|
||||
return getVideoDimensions(mediaMetadataRetriever);
|
||||
}
|
||||
|
||||
private static Dimensions getVideoDimensionsOfFrame(MediaMetadataRetriever mediaMetadataRetriever) {
|
||||
Bitmap bitmap = null;
|
||||
try {
|
||||
bitmap = mediaMetadataRetriever.getFrameAtTime();
|
||||
return new Dimensions(bitmap.getHeight(), bitmap.getWidth());
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
} finally {
|
||||
if (bitmap != null) {
|
||||
bitmap.recycle();
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Dimensions getVideoDimensions(MediaMetadataRetriever metadataRetriever) throws NotAVideoFile {
|
||||
String hasVideo = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO);
|
||||
if (hasVideo == null) {
|
||||
throw new NotAVideoFile();
|
||||
}
|
||||
Dimensions dimensions = getVideoDimensionsOfFrame(metadataRetriever);
|
||||
if (dimensions != null) {
|
||||
return dimensions;
|
||||
}
|
||||
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 static int extractRotationFromMediaRetriever(MediaMetadataRetriever metadataRetriever) {
|
||||
String r = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
|
||||
try {
|
||||
return Integer.parseInt(r);
|
||||
} catch (Exception e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static void close(Closeable stream) {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void close(Socket socket) {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean weOwnFile(Context context, Uri uri) {
|
||||
if (uri == null || !ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
|
||||
return false;
|
||||
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return fileIsInFilesDir(context, uri);
|
||||
} else {
|
||||
return weOwnFileLollipop(uri);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is more than hacky but probably way better than doing nothing
|
||||
* Further 'optimizations' might contain to get the parents of CacheDir and NoBackupDir
|
||||
* and check against those as well
|
||||
*/
|
||||
private static boolean fileIsInFilesDir(Context context, Uri uri) {
|
||||
try {
|
||||
final String haystack = context.getFilesDir().getParentFile().getCanonicalPath();
|
||||
final String needle = new File(uri.getPath()).getCanonicalPath();
|
||||
return needle.startsWith(haystack);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private static boolean weOwnFileLollipop(Uri uri) {
|
||||
try {
|
||||
File file = new File(uri.getPath());
|
||||
FileDescriptor fd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY).getFileDescriptor();
|
||||
StructStat st = Os.fstat(fd);
|
||||
return st.st_uid == android.os.Process.myUid();
|
||||
} catch (FileNotFoundException e) {
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void createNoMedia(File diretory) {
|
||||
final File noMedia = new File(diretory,".nomedia");
|
||||
final File noMedia = new File(diretory, ".nomedia");
|
||||
if (!noMedia.exists()) {
|
||||
try {
|
||||
if (!noMedia.createNewFile()) {
|
||||
Log.d(Config.LOGTAG,"created nomedia file "+noMedia.getAbsolutePath());
|
||||
Log.d(Config.LOGTAG, "created nomedia file " + noMedia.getAbsolutePath());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d(Config.LOGTAG, "could not create nomedia file");
|
||||
|
@ -100,19 +387,6 @@ public class FileBackend {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean isInDirectoryThatShouldNotBeScanned(Context context, File file) {
|
||||
return isInDirectoryThatShouldNotBeScanned(context, file.getAbsolutePath());
|
||||
}
|
||||
|
||||
public static boolean isInDirectoryThatShouldNotBeScanned(Context context, String path) {
|
||||
for(String type : new String[]{RecordingActivity.STORAGE_DIRECTORY_TYPE_NAME, "Files"}) {
|
||||
if (path.startsWith(getConversationsDirectory(context, type))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean deleteFile(Message message) {
|
||||
File file = getFile(message);
|
||||
if (file.delete()) {
|
||||
|
@ -159,82 +433,27 @@ public class FileBackend {
|
|||
}
|
||||
}
|
||||
|
||||
public static long getFileSize(Context context, Uri uri) {
|
||||
try {
|
||||
final Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
long size = cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE));
|
||||
cursor.close();
|
||||
return size;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean allFilesUnderSize(Context context, List<Uri> uris, long max) {
|
||||
if (max <= 0) {
|
||||
Log.d(Config.LOGTAG, "server did not report max file size for http upload");
|
||||
return true; //exception to be compatible with HTTP Upload < v0.2
|
||||
}
|
||||
for (Uri uri : uris) {
|
||||
String mime = context.getContentResolver().getType(uri);
|
||||
if (mime != null && mime.startsWith("video/")) {
|
||||
try {
|
||||
Dimensions dimensions = FileBackend.getVideoDimensions(context, uri);
|
||||
if (dimensions.getMin() > 720) {
|
||||
Log.d(Config.LOGTAG, "do not consider video file with min width larger than 720 for size check");
|
||||
continue;
|
||||
}
|
||||
} catch (NotAVideoFile notAVideoFile) {
|
||||
//ignore and fall through
|
||||
}
|
||||
}
|
||||
if (FileBackend.getFileSize(context, uri) > max) {
|
||||
Log.d(Config.LOGTAG, "not all files are under " + max + " bytes. suggesting falling back to jingle");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getConversationsDirectory(final String type) {
|
||||
return getConversationsDirectory(mXmppConnectionService, type);
|
||||
}
|
||||
|
||||
public static String getConversationsDirectory(Context context, final String type) {
|
||||
if (Config.ONLY_INTERNAL_STORAGE) {
|
||||
return context.getFilesDir().getAbsolutePath() + "/" + type + "/";
|
||||
} else {
|
||||
return getAppMediaDirectory(context)+context.getString(R.string.app_name)+" " + type + "/";
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAppMediaDirectory(Context context) {
|
||||
return Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+context.getString(R.string.app_name)+"/Media/";
|
||||
}
|
||||
|
||||
public static String getConversationsLogsDirectory() {
|
||||
return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Conversations/";
|
||||
}
|
||||
|
||||
public Bitmap resize(Bitmap originalBitmap, int size) {
|
||||
private Bitmap resize(final Bitmap originalBitmap, int size) throws IOException {
|
||||
int w = originalBitmap.getWidth();
|
||||
int h = originalBitmap.getHeight();
|
||||
if (Math.max(w, h) > size) {
|
||||
if (w <= 0 || h <= 0) {
|
||||
throw new IOException("Decoded bitmap reported bounds smaller 0");
|
||||
} else if (Math.max(w, h) > size) {
|
||||
int scalledW;
|
||||
int scalledH;
|
||||
if (w <= h) {
|
||||
scalledW = (int) (w / ((double) h / size));
|
||||
scalledW = Math.max((int) (w / ((double) h / size)), 1);
|
||||
scalledH = size;
|
||||
} else {
|
||||
scalledW = size;
|
||||
scalledH = (int) (h / ((double) w / size));
|
||||
scalledH = Math.max((int) (h / ((double) w / size)), 1);
|
||||
}
|
||||
Bitmap result = Bitmap.createScaledBitmap(originalBitmap, scalledW, scalledH, true);
|
||||
if (originalBitmap != null && !originalBitmap.isRecycled()) {
|
||||
final Bitmap result = Bitmap.createScaledBitmap(originalBitmap, scalledW, scalledH, true);
|
||||
if (!originalBitmap.isRecycled()) {
|
||||
originalBitmap.recycle();
|
||||
}
|
||||
return result;
|
||||
|
@ -243,22 +462,6 @@ public class FileBackend {
|
|||
}
|
||||
}
|
||||
|
||||
private static Bitmap rotate(Bitmap bitmap, int degree) {
|
||||
if (degree == 0) {
|
||||
return bitmap;
|
||||
}
|
||||
int w = bitmap.getWidth();
|
||||
int h = bitmap.getHeight();
|
||||
Matrix mtx = new Matrix();
|
||||
mtx.postRotate(degree);
|
||||
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
|
||||
if (bitmap != null && !bitmap.isRecycled()) {
|
||||
bitmap.recycle();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public boolean useImageAsIs(Uri uri) {
|
||||
String path = getOriginalPath(uri);
|
||||
if (path == null || isPathBlacklisted(path)) {
|
||||
|
@ -282,11 +485,6 @@ public class FileBackend {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean isPathBlacklisted(String path) {
|
||||
final String androidDataPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/";
|
||||
return path.startsWith(androidDataPath);
|
||||
}
|
||||
|
||||
public String getOriginalPath(Uri uri) {
|
||||
return FileUtils.getPath(mXmppConnectionService, uri);
|
||||
}
|
||||
|
@ -332,7 +530,7 @@ public class FileBackend {
|
|||
Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage (mime=" + mime + ")");
|
||||
String extension = MimeUtils.guessExtensionFromMimeType(mime);
|
||||
if (extension == null) {
|
||||
Log.d(Config.LOGTAG,"extension from mime type was null");
|
||||
Log.d(Config.LOGTAG, "extension from mime type was null");
|
||||
extension = getExtensionFromUri(uri);
|
||||
}
|
||||
if ("ogg".equals(extension) && type != null && type.startsWith("audio/")) {
|
||||
|
@ -360,7 +558,7 @@ public class FileBackend {
|
|||
if (filename == null) {
|
||||
final List<String> segments = uri.getPathSegments();
|
||||
if (segments.size() > 0) {
|
||||
filename = segments.get(segments.size() -1);
|
||||
filename = segments.get(segments.size() - 1);
|
||||
}
|
||||
}
|
||||
int pos = filename == null ? -1 : filename.lastIndexOf('.');
|
||||
|
@ -463,7 +661,7 @@ public class FileBackend {
|
|||
}
|
||||
}
|
||||
|
||||
public Bitmap getThumbnail(Message message, int size, boolean cacheOnly) throws FileNotFoundException {
|
||||
public Bitmap getThumbnail(Message message, int size, boolean cacheOnly) throws IOException {
|
||||
final String uuid = message.getUuid();
|
||||
final LruCache<String, Bitmap> cache = mXmppConnectionService.getBitmapCache();
|
||||
Bitmap thumbnail = cache.get(uuid);
|
||||
|
@ -519,14 +717,6 @@ public class FileBackend {
|
|||
canvas.drawBitmap(overlay, null, dst, createAntiAliasingPaint());
|
||||
}
|
||||
|
||||
private static Paint createAntiAliasingPaint() {
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setFilterBitmap(true);
|
||||
paint.setDither(true);
|
||||
return paint;
|
||||
}
|
||||
|
||||
private Bitmap getVideoPreview(File file, int size) {
|
||||
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
|
||||
Bitmap frame;
|
||||
|
@ -535,7 +725,7 @@ public class FileBackend {
|
|||
frame = metadataRetriever.getFrameAtTime(0);
|
||||
metadataRetriever.release();
|
||||
frame = resize(frame, size);
|
||||
} catch (RuntimeException e) {
|
||||
} catch (IOException | RuntimeException e) {
|
||||
frame = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||
frame.eraseColor(0xff000000);
|
||||
}
|
||||
|
@ -543,10 +733,6 @@ public class FileBackend {
|
|||
return frame;
|
||||
}
|
||||
|
||||
private static String getTakePhotoPath() {
|
||||
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + "/Camera/";
|
||||
}
|
||||
|
||||
public Uri getTakePhotoUri() {
|
||||
File file;
|
||||
if (Config.ONLY_INTERNAL_STORAGE) {
|
||||
|
@ -558,35 +744,6 @@ public class FileBackend {
|
|||
return getUriForFile(mXmppConnectionService, file);
|
||||
}
|
||||
|
||||
public static Uri getUriForFile(Context context, File file) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N || Config.ONLY_INTERNAL_STORAGE) {
|
||||
try {
|
||||
return FileProvider.getUriForFile(context, getAuthority(context), file);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
throw new SecurityException(e);
|
||||
} else {
|
||||
return Uri.fromFile(file);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Uri.fromFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAuthority(Context context) {
|
||||
return context.getPackageName() + FILE_PROVIDER;
|
||||
}
|
||||
|
||||
public static Uri getIndexableTakePhotoUri(Uri original) {
|
||||
if (Config.ONLY_INTERNAL_STORAGE || "file".equals(original.getScheme())) {
|
||||
return original;
|
||||
} else {
|
||||
List<String> segments = original.getPathSegments();
|
||||
return Uri.parse("file://" + getTakePhotoPath() + segments.get(segments.size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
public Avatar getPepAvatar(Uri image, int size, Bitmap.CompressFormat format) {
|
||||
Bitmap bm = cropCenterSquare(image, size);
|
||||
if (bm == null) {
|
||||
|
@ -601,17 +758,6 @@ public class FileBackend {
|
|||
return getPepAvatar(bm, format, 100);
|
||||
}
|
||||
|
||||
private static boolean hasAlpha(final Bitmap bitmap) {
|
||||
for (int x = 0; x < bitmap.getWidth(); ++x) {
|
||||
for (int y = 0; y < bitmap.getWidth(); ++y) {
|
||||
if (Color.alpha(bitmap.getPixel(x, y)) < 255) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Avatar getPepAvatar(Bitmap bitmap, Bitmap.CompressFormat format, int quality) {
|
||||
try {
|
||||
ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream();
|
||||
|
@ -698,12 +844,12 @@ public class FileBackend {
|
|||
} else {
|
||||
file = new File(mXmppConnectionService.getCacheDir().getAbsolutePath() + "/" + UUID.randomUUID().toString());
|
||||
if (file.getParentFile().mkdirs()) {
|
||||
Log.d(Config.LOGTAG,"created cache directory");
|
||||
Log.d(Config.LOGTAG, "created cache directory");
|
||||
}
|
||||
OutputStream os = null;
|
||||
try {
|
||||
if (!file.createNewFile()) {
|
||||
Log.d(Config.LOGTAG,"unable to create temporary file "+file.getAbsolutePath());
|
||||
Log.d(Config.LOGTAG, "unable to create temporary file " + file.getAbsolutePath());
|
||||
}
|
||||
os = new FileOutputStream(file);
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||
|
@ -717,17 +863,17 @@ public class FileBackend {
|
|||
if (sha1sum.equals(avatar.sha1sum)) {
|
||||
File outputFile = new File(getAvatarPath(avatar.getFilename()));
|
||||
if (outputFile.getParentFile().mkdirs()) {
|
||||
Log.d(Config.LOGTAG,"created avatar directory");
|
||||
Log.d(Config.LOGTAG, "created avatar directory");
|
||||
}
|
||||
String filename = getAvatarPath(avatar.getFilename());
|
||||
if (!file.renameTo(new File(filename))) {
|
||||
Log.d(Config.LOGTAG,"unable to rename "+file.getAbsolutePath()+" to "+outputFile);
|
||||
Log.d(Config.LOGTAG, "unable to rename " + file.getAbsolutePath() + " to " + outputFile);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, "sha1sum mismatch for " + avatar.owner);
|
||||
if (!file.delete()) {
|
||||
Log.d(Config.LOGTAG,"unable to delete temporary file");
|
||||
Log.d(Config.LOGTAG, "unable to delete temporary file");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -846,30 +992,6 @@ public class FileBackend {
|
|||
return calcSampleSize(options, size);
|
||||
}
|
||||
|
||||
private static int calcSampleSize(File image, int size) {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeFile(image.getAbsolutePath(), options);
|
||||
return calcSampleSize(options, size);
|
||||
}
|
||||
|
||||
public static int calcSampleSize(BitmapFactory.Options options, int size) {
|
||||
int height = options.outHeight;
|
||||
int width = options.outWidth;
|
||||
int inSampleSize = 1;
|
||||
|
||||
if (height > size || width > size) {
|
||||
int halfHeight = height / 2;
|
||||
int halfWidth = width / 2;
|
||||
|
||||
while ((halfHeight / inSampleSize) > size
|
||||
&& (halfWidth / inSampleSize) > size) {
|
||||
inSampleSize *= 2;
|
||||
}
|
||||
}
|
||||
return inSampleSize;
|
||||
}
|
||||
|
||||
public void updateFileParams(Message message) {
|
||||
updateFileParams(message, null);
|
||||
}
|
||||
|
@ -942,67 +1064,19 @@ public class FileBackend {
|
|||
return getVideoDimensions(metadataRetriever);
|
||||
}
|
||||
|
||||
private static Dimensions getVideoDimensions(Context context, Uri uri) throws NotAVideoFile {
|
||||
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
|
||||
try {
|
||||
mediaMetadataRetriever.setDataSource(context, uri);
|
||||
} catch (RuntimeException e) {
|
||||
throw new NotAVideoFile(e);
|
||||
}
|
||||
return getVideoDimensions(mediaMetadataRetriever);
|
||||
}
|
||||
|
||||
private static Dimensions getVideoDimensionsOfFrame(MediaMetadataRetriever mediaMetadataRetriever) {
|
||||
Bitmap bitmap = null;
|
||||
try {
|
||||
bitmap = mediaMetadataRetriever.getFrameAtTime();
|
||||
return new Dimensions(bitmap.getHeight(), bitmap.getWidth());
|
||||
} catch (Exception e) {
|
||||
public Bitmap getAvatar(String avatar, int size) {
|
||||
if (avatar == null) {
|
||||
return null;
|
||||
} finally {
|
||||
if (bitmap != null) {
|
||||
bitmap.recycle();;
|
||||
}
|
||||
}
|
||||
Bitmap bm = cropCenter(getAvatarUri(avatar), size, size);
|
||||
if (bm == null) {
|
||||
return null;
|
||||
}
|
||||
return bm;
|
||||
}
|
||||
|
||||
private static Dimensions getVideoDimensions(MediaMetadataRetriever metadataRetriever) throws NotAVideoFile {
|
||||
String hasVideo = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO);
|
||||
if (hasVideo == null) {
|
||||
throw new NotAVideoFile();
|
||||
}
|
||||
Dimensions dimensions = getVideoDimensionsOfFrame(metadataRetriever);
|
||||
if (dimensions != null) {
|
||||
return dimensions;
|
||||
}
|
||||
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 static int extractRotationFromMediaRetriever(MediaMetadataRetriever metadataRetriever) {
|
||||
String r = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
|
||||
try {
|
||||
return Integer.parseInt(r);
|
||||
} catch (Exception e) {
|
||||
return 0;
|
||||
}
|
||||
public boolean isFileAvailable(Message message) {
|
||||
return getFile(message).exists();
|
||||
}
|
||||
|
||||
private static class Dimensions {
|
||||
|
@ -1045,78 +1119,4 @@ public class FileBackend {
|
|||
return resId;
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap getAvatar(String avatar, int size) {
|
||||
if (avatar == null) {
|
||||
return null;
|
||||
}
|
||||
Bitmap bm = cropCenter(getAvatarUri(avatar), size, size);
|
||||
if (bm == null) {
|
||||
return null;
|
||||
}
|
||||
return bm;
|
||||
}
|
||||
|
||||
public boolean isFileAvailable(Message message) {
|
||||
return getFile(message).exists();
|
||||
}
|
||||
|
||||
public static void close(Closeable stream) {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void close(Socket socket) {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean weOwnFile(Context context, Uri uri) {
|
||||
if (uri == null || !ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
|
||||
return false;
|
||||
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return fileIsInFilesDir(context, uri);
|
||||
} else {
|
||||
return weOwnFileLollipop(uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is more than hacky but probably way better than doing nothing
|
||||
* Further 'optimizations' might contain to get the parents of CacheDir and NoBackupDir
|
||||
* and check against those as well
|
||||
*/
|
||||
private static boolean fileIsInFilesDir(Context context, Uri uri) {
|
||||
try {
|
||||
final String haystack = context.getFilesDir().getParentFile().getCanonicalPath();
|
||||
final String needle = new File(uri.getPath()).getCanonicalPath();
|
||||
return needle.startsWith(haystack);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private static boolean weOwnFileLollipop(Uri uri) {
|
||||
try {
|
||||
File file = new File(uri.getPath());
|
||||
FileDescriptor fd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY).getFileDescriptor();
|
||||
StructStat st = Os.fstat(fd);
|
||||
return st.st_uid == android.os.Process.myUid();
|
||||
} catch (FileNotFoundException e) {
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import android.util.Pair;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
|
@ -504,7 +505,7 @@ public class NotificationService {
|
|||
builder.setContentText(UIHelper.getFileDescriptionString(mXmppConnectionService, message));
|
||||
}
|
||||
builder.setStyle(bigPictureStyle);
|
||||
} catch (final FileNotFoundException e) {
|
||||
} catch (final IOException e) {
|
||||
modifyForTextOnly(builder, uBuilder, messages);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import android.widget.ImageView;
|
|||
import android.widget.Toast;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -876,7 +877,7 @@ public abstract class XmppActivity extends ActionBarActivity {
|
|||
Bitmap bm;
|
||||
try {
|
||||
bm = xmppConnectionService.getFileBackend().getThumbnail(message, (int) (metrics.density * 288), true);
|
||||
} catch (FileNotFoundException e) {
|
||||
} catch (IOException e) {
|
||||
bm = null;
|
||||
}
|
||||
if (bm != null) {
|
||||
|
@ -970,7 +971,7 @@ public abstract class XmppActivity extends ActionBarActivity {
|
|||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue