Added back async image loading in chat bubbles
This commit is contained in:
parent
6d9b2ab592
commit
404c92da9f
3 changed files with 229 additions and 3 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
package org.linphone.chat;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ChatMessageViewHolder.java
|
ChatMessageViewHolder.java
|
||||||
Copyright (C) 2017 Belledonne Communications, Grenoble, France
|
Copyright (C) 2017 Belledonne Communications, Grenoble, France
|
||||||
|
@ -17,8 +19,6 @@ along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.linphone.chat;
|
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
|
@ -54,6 +56,8 @@ import org.linphone.core.Content;
|
||||||
import org.linphone.mediastream.Log;
|
import org.linphone.mediastream.Log;
|
||||||
import org.linphone.utils.FileUtils;
|
import org.linphone.utils.FileUtils;
|
||||||
import org.linphone.utils.LinphoneUtils;
|
import org.linphone.utils.LinphoneUtils;
|
||||||
|
import org.linphone.views.AsyncBitmap;
|
||||||
|
import org.linphone.views.BitmapWorkerTask;
|
||||||
import org.linphone.views.ContactAvatar;
|
import org.linphone.views.ContactAvatar;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -221,7 +225,7 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
View v;
|
View v;
|
||||||
if (FileUtils.isExtensionImage(filePath)) {
|
if (FileUtils.isExtensionImage(filePath)) {
|
||||||
v = content.findViewById(R.id.image);
|
v = content.findViewById(R.id.image);
|
||||||
((ImageView)v).setImageURI(Uri.parse(c.getFilePath()));
|
loadBitmap(c.getFilePath(), ((ImageView)v));
|
||||||
} else {
|
} else {
|
||||||
v = content.findViewById(R.id.file);
|
v = content.findViewById(R.id.file);
|
||||||
((TextView)v).setText(FileUtils.getNameFromFilePath(filePath));
|
((TextView)v).setText(FileUtils.getNameFromFilePath(filePath));
|
||||||
|
@ -308,4 +312,33 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
mContext.startActivity(intent);
|
mContext.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadBitmap(String path, ImageView imageView) {
|
||||||
|
if (cancelPotentialWork(path, imageView)) {
|
||||||
|
Bitmap defaultBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.chat_file);
|
||||||
|
BitmapWorkerTask task = new BitmapWorkerTask(mContext, imageView, defaultBitmap);
|
||||||
|
final AsyncBitmap asyncBitmap = new AsyncBitmap(mContext.getResources(), defaultBitmap, task);
|
||||||
|
imageView.setImageDrawable(asyncBitmap);
|
||||||
|
task.execute(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cancelPotentialWork(String path, ImageView imageView) {
|
||||||
|
final BitmapWorkerTask bitmapWorkerTask = BitmapWorkerTask.getBitmapWorkerTask(imageView);
|
||||||
|
|
||||||
|
if (bitmapWorkerTask != null) {
|
||||||
|
final String bitmapData = bitmapWorkerTask.path;
|
||||||
|
// If bitmapData is not yet set or it differs from the new data
|
||||||
|
if (bitmapData == null || bitmapData != path) {
|
||||||
|
// Cancel previous task
|
||||||
|
bitmapWorkerTask.cancel(true);
|
||||||
|
} else {
|
||||||
|
// The same work is already in progress
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No task associated with the ImageView, or an existing task was cancelled
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
39
app/src/main/java/org/linphone/views/AsyncBitmap.java
Normal file
39
app/src/main/java/org/linphone/views/AsyncBitmap.java
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package org.linphone.views;
|
||||||
|
|
||||||
|
/*
|
||||||
|
AsyncBitmap.java
|
||||||
|
Copyright (C) 2018 Belledonne Communications, Grenoble, France
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
public class AsyncBitmap extends BitmapDrawable {
|
||||||
|
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
|
||||||
|
|
||||||
|
public AsyncBitmap(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
|
||||||
|
super(res, bitmap);
|
||||||
|
bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmapWorkerTask getBitmapWorkerTask() {
|
||||||
|
return bitmapWorkerTaskReference.get();
|
||||||
|
}
|
||||||
|
}
|
154
app/src/main/java/org/linphone/views/BitmapWorkerTask.java
Normal file
154
app/src/main/java/org/linphone/views/BitmapWorkerTask.java
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
package org.linphone.views;
|
||||||
|
|
||||||
|
/*
|
||||||
|
BitmapWorkerTask.java
|
||||||
|
Copyright (C) 2018 Belledonne Communications, Grenoble, France
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.media.ExifInterface;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.provider.MediaStore;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import org.linphone.mediastream.Log;
|
||||||
|
import org.linphone.utils.FileUtils;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
public class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
|
||||||
|
private Context mContext;
|
||||||
|
private Bitmap mDefaultBitmap;
|
||||||
|
|
||||||
|
private final WeakReference<ImageView> imageViewReference;
|
||||||
|
public String path;
|
||||||
|
|
||||||
|
public BitmapWorkerTask(Context context, ImageView imageView, Bitmap defaultBitmap) {
|
||||||
|
mContext = context;
|
||||||
|
mDefaultBitmap = defaultBitmap;
|
||||||
|
path = null;
|
||||||
|
// Use a WeakReference to ensure the ImageView can be garbage collected
|
||||||
|
imageViewReference = new WeakReference<>(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap scaleToFitHeight(Bitmap b, int height) {
|
||||||
|
float factor = height / (float) b.getHeight();
|
||||||
|
int dstWidth = (int) (b.getWidth() * factor);
|
||||||
|
if (dstWidth > 0 && height > 0) {
|
||||||
|
return Bitmap.createScaledBitmap(b, dstWidth, height, true);
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode image in background.
|
||||||
|
@Override
|
||||||
|
protected Bitmap doInBackground(String... params) {
|
||||||
|
path = params[0];
|
||||||
|
Bitmap bm = null;
|
||||||
|
Bitmap thumbnail = null;
|
||||||
|
if (FileUtils.isExtensionImage(path)) {
|
||||||
|
if (path.startsWith("content")) {
|
||||||
|
try {
|
||||||
|
bm = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), Uri.parse(path));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Log.e(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bm = BitmapFactory.decodeFile(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageView imageView = imageViewReference.get();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Rotate the bitmap if possible/needed, using EXIF data
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
ExifInterface exif = new ExifInterface(path);
|
||||||
|
int pictureOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
|
||||||
|
if (pictureOrientation == 6 || pictureOrientation == 3 || pictureOrientation == 8) {
|
||||||
|
if (pictureOrientation == 6) {
|
||||||
|
matrix.postRotate(90);
|
||||||
|
} else if (pictureOrientation == 3) {
|
||||||
|
matrix.postRotate(180);
|
||||||
|
} else {
|
||||||
|
matrix.postRotate(270);
|
||||||
|
}
|
||||||
|
if (imageView != null) {
|
||||||
|
if (pictureOrientation == 6 || pictureOrientation == 8) {
|
||||||
|
matrix.postScale(1, imageView.getMeasuredHeight() / (float) bm.getHeight());
|
||||||
|
} else {
|
||||||
|
matrix.postScale(imageView.getMeasuredHeight() / (float) bm.getHeight(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thumbnail = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
|
||||||
|
if (thumbnail != bm) {
|
||||||
|
bm.recycle();
|
||||||
|
bm = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thumbnail == null && bm != null) {
|
||||||
|
if (imageView == null) return bm;
|
||||||
|
thumbnail = scaleToFitHeight(bm, imageView.getMeasuredHeight());
|
||||||
|
if (thumbnail != bm) {
|
||||||
|
bm.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return thumbnail;
|
||||||
|
} else {
|
||||||
|
return mDefaultBitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once complete, see if ImageView is still around and set bitmap.
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Bitmap bitmap) {
|
||||||
|
if (isCancelled()) {
|
||||||
|
bitmap.recycle();
|
||||||
|
bitmap = null;
|
||||||
|
}
|
||||||
|
if (imageViewReference != null && bitmap != null) {
|
||||||
|
final ImageView imageView = imageViewReference.get();
|
||||||
|
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
|
||||||
|
if (this == bitmapWorkerTask && imageView != null) {
|
||||||
|
imageView.setImageBitmap(bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
|
||||||
|
if (imageView != null) {
|
||||||
|
final Drawable drawable = imageView.getDrawable();
|
||||||
|
if (drawable instanceof AsyncBitmap) {
|
||||||
|
final AsyncBitmap asyncDrawable = (AsyncBitmap) drawable;
|
||||||
|
return asyncDrawable.getBitmapWorkerTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue