Java tutorial
/* * Copyright 2017 Vector Creations Ltd * Copyright 2018 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package im.vector.adapters; import android.content.Context; import android.graphics.Color; import android.media.ExifInterface; import android.text.TextUtils; import android.text.format.DateUtils; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.request.RequestOptions; import com.google.gson.JsonElement; import org.matrix.androidsdk.MXSession; import org.matrix.androidsdk.db.MXMediasCache; import org.matrix.androidsdk.listeners.IMXMediaDownloadListener; import org.matrix.androidsdk.listeners.IMXMediaUploadListener; import org.matrix.androidsdk.listeners.MXMediaDownloadListener; import org.matrix.androidsdk.listeners.MXMediaUploadListener; import org.matrix.androidsdk.rest.model.crypto.EncryptedFileInfo; import org.matrix.androidsdk.rest.model.Event; import org.matrix.androidsdk.rest.model.message.FileMessage; import org.matrix.androidsdk.rest.model.message.ImageInfo; import org.matrix.androidsdk.rest.model.message.ImageMessage; import org.matrix.androidsdk.rest.model.MatrixError; import org.matrix.androidsdk.rest.model.message.Message; import org.matrix.androidsdk.rest.model.message.StickerMessage; import org.matrix.androidsdk.rest.model.message.VideoInfo; import org.matrix.androidsdk.rest.model.message.VideoMessage; import org.matrix.androidsdk.util.JsonUtils; import org.matrix.androidsdk.util.Log; import java.util.HashMap; import java.util.Map; import im.vector.R; import im.vector.listeners.IMessagesAdapterActionsListener; /** * An helper to display medias information */ class VectorMessagesAdapterMediasHelper { private static final String LOG_TAG = VectorMessagesAdapterMediasHelper.class.getSimpleName(); private final MXSession mSession; private final Context mContext; private final int mMaxImageWidth; private final int mMaxImageHeight; private final MXMediasCache mMediasCache; private IMessagesAdapterActionsListener mVectorMessagesAdapterEventsListener; private final int mNotSentMessageTextColor; private final int mDefaultMessageTextColor; VectorMessagesAdapterMediasHelper(Context context, MXSession session, int maxImageWidth, int maxImageHeight, int notSentMessageTextColor, int defaultMessageTextColor) { mContext = context; mSession = session; mMaxImageWidth = maxImageWidth; mMaxImageHeight = maxImageHeight; mMediasCache = mSession.getMediasCache(); mNotSentMessageTextColor = notSentMessageTextColor; mDefaultMessageTextColor = defaultMessageTextColor; } /** * Define the events listener * * @param listener teh events listener */ void setVectorMessagesAdapterActionsListener(IMessagesAdapterActionsListener listener) { mVectorMessagesAdapterEventsListener = listener; } /** * Check if there is a linked upload. * * @param convertView the media view * @param event teh related event * @param type the media type * @param mediaUrl the media url */ void managePendingUpload(final View convertView, final Event event, final int type, final String mediaUrl) { final View uploadProgressLayout = convertView.findViewById(R.id.content_upload_progress_layout); final ProgressBar uploadSpinner = convertView.findViewById(R.id.upload_event_spinner); // the dedicated UI items are not found if ((null == uploadProgressLayout) || (null == uploadSpinner)) { return; } // Mark the upload layout as uploadProgressLayout.setTag(mediaUrl); // no upload in progress if (!mSession.getMyUserId().equals(event.getSender()) || !event.isSending()) { uploadProgressLayout.setVisibility(View.GONE); uploadSpinner.setVisibility(View.GONE); showUploadFailure(convertView, type, event.isUndeliverable()); return; } IMXMediaUploadListener.UploadStats uploadStats = mSession.getMediasCache().getStatsForUploadId(mediaUrl); if (null != uploadStats) { mSession.getMediasCache().addUploadListener(mediaUrl, new MXMediaUploadListener() { @Override public void onUploadProgress(String uploadId, UploadStats uploadStats) { if (TextUtils.equals((String) uploadProgressLayout.getTag(), uploadId)) { refreshUploadViews(event, uploadStats, uploadProgressLayout); } } private void onUploadStop(String message) { if (!TextUtils.isEmpty(message)) { Toast.makeText(mContext, message, Toast.LENGTH_LONG).show(); } showUploadFailure(convertView, type, true); uploadProgressLayout.setVisibility(View.GONE); uploadSpinner.setVisibility(View.GONE); } @Override public void onUploadCancel(String uploadId) { if (TextUtils.equals((String) uploadProgressLayout.getTag(), uploadId)) { onUploadStop(null); } } @Override public void onUploadError(String uploadId, int serverResponseCode, String serverErrorMessage) { if (TextUtils.equals((String) uploadProgressLayout.getTag(), uploadId)) { onUploadStop(serverErrorMessage); } } @Override public void onUploadComplete(final String uploadId, final String contentUri) { if (TextUtils.equals((String) uploadProgressLayout.getTag(), uploadId)) { uploadSpinner.setVisibility(View.GONE); } } }); } showUploadFailure(convertView, type, false); uploadSpinner.setVisibility((null == uploadStats) ? View.VISIBLE : View.GONE); refreshUploadViews(event, uploadStats, uploadProgressLayout); } // the image / video bitmaps are set to null if the matching URL is not the same // to avoid flickering private Map<String, String> mUrlByBitmapIndex = new HashMap<>(); /** * Manage the image/video download. * * @param convertView the parent view. * @param event the event * @param message the image / video message * @param position the message position */ void managePendingImageVideoDownload(final View convertView, final Event event, final Message message, final int position) { int maxImageWidth = mMaxImageWidth; int maxImageHeight = mMaxImageHeight; int rotationAngle = 0; int orientation = ExifInterface.ORIENTATION_NORMAL; String thumbUrl = null; int thumbWidth = -1; int thumbHeight = -1; EncryptedFileInfo encryptedFileInfo = null; // retrieve the common items if (message instanceof ImageMessage) { ImageMessage imageMessage = (ImageMessage) message; imageMessage.checkMediaUrls(); // Backwards compatibility with events from before Synapse 0.6.0 if (imageMessage.getThumbnailUrl() != null) { thumbUrl = imageMessage.getThumbnailUrl(); if (null != imageMessage.info) { encryptedFileInfo = imageMessage.info.thumbnail_file; } } else if (imageMessage.getUrl() != null) { thumbUrl = imageMessage.getUrl(); encryptedFileInfo = imageMessage.file; } rotationAngle = imageMessage.getRotation(); ImageInfo imageInfo = imageMessage.info; if (null != imageInfo) { if ((null != imageInfo.w) && (null != imageInfo.h)) { thumbWidth = imageInfo.w; thumbHeight = imageInfo.h; } if (null != imageInfo.orientation) { orientation = imageInfo.orientation; } } } else if (message instanceof VideoMessage) { // video VideoMessage videoMessage = (VideoMessage) message; videoMessage.checkMediaUrls(); thumbUrl = videoMessage.getThumbnailUrl(); if (null != videoMessage.info) { encryptedFileInfo = videoMessage.info.thumbnail_file; } VideoInfo videoinfo = videoMessage.info; if (null != videoinfo) { if ((null != videoMessage.info.thumbnail_info) && (null != videoMessage.info.thumbnail_info.w) && (null != videoMessage.info.thumbnail_info.h)) { thumbWidth = videoMessage.info.thumbnail_info.w; thumbHeight = videoMessage.info.thumbnail_info.h; } } } ImageView imageView = convertView.findViewById(R.id.messagesAdapter_image); // reset the bitmap if the url is not the same than before if ((null == thumbUrl) || !TextUtils.equals(imageView.hashCode() + "", mUrlByBitmapIndex.get(thumbUrl))) { imageView.setImageBitmap(null); if (null != thumbUrl) { mUrlByBitmapIndex.put(thumbUrl, imageView.hashCode() + ""); } } RelativeLayout informationLayout = convertView.findViewById(R.id.messagesAdapter_image_layout); final FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) informationLayout .getLayoutParams(); // the thumbnails are always pre - rotated String downloadId = null; if (!event.getType().equals(Event.EVENT_TYPE_STICKER)) { downloadId = mMediasCache.loadBitmap(mSession.getHomeServerConfig(), imageView, thumbUrl, maxImageWidth, maxImageHeight, rotationAngle, ExifInterface.ORIENTATION_UNDEFINED, "image/jpeg", encryptedFileInfo); } // test if the media is downloading when the thumbnail is not downloading if (null == downloadId) { if (message instanceof VideoMessage) { downloadId = mMediasCache.downloadIdFromUrl(((VideoMessage) message).getUrl()); } else if (message instanceof ImageMessage) { downloadId = mMediasCache.downloadIdFromUrl(((ImageMessage) message).getUrl()); } } // Use Glide library to display stickers into ImageView // Glide support animated gif if (event.getType().equals(Event.EVENT_TYPE_STICKER)) { // Check whether the sticker url is a valid Matrix media content URI, and convert it in an actual url. String downloadableUrl = mSession.getContentManager() .getDownloadableUrl(((StickerMessage) message).getUrl()); if (null != downloadableUrl) { Glide.with(mContext).load(downloadableUrl) .apply(new RequestOptions().override(maxImageWidth, maxImageHeight).fitCenter() .placeholder(R.drawable.sticker_placeholder)) .into(imageView); } else { // Display the placeholder imageView.setImageResource(R.drawable.sticker_placeholder); } } final View downloadProgressLayout = convertView.findViewById(R.id.content_download_progress_layout); if (null == downloadProgressLayout) { return; } // the tag is used to detect if the progress value is linked to this layout downloadProgressLayout.setTag(downloadId); int frameHeight = -1; int frameWidth = -1; // if the image size is known // compute the expected thumbnail height if ((thumbWidth > 0) && (thumbHeight > 0)) { // swap width and height if the image is side oriented if ((rotationAngle == 90) || (rotationAngle == 270)) { int tmp = thumbWidth; thumbWidth = thumbHeight; thumbHeight = tmp; } else if ((orientation == ExifInterface.ORIENTATION_ROTATE_90) || (orientation == ExifInterface.ORIENTATION_ROTATE_270)) { int tmp = thumbWidth; thumbWidth = thumbHeight; thumbHeight = tmp; } frameHeight = Math.min(maxImageWidth * thumbHeight / thumbWidth, maxImageHeight); frameWidth = frameHeight * thumbWidth / thumbHeight; } // ensure that some values are properly initialized if (frameHeight < 0) { frameHeight = mMaxImageHeight; } if (frameWidth < 0) { frameWidth = mMaxImageWidth; } // apply it the layout // it avoid row jumping when the image is downloaded layoutParams.height = frameHeight; layoutParams.width = frameWidth; // no download in progress if (null != downloadId) { downloadProgressLayout.setVisibility(View.VISIBLE); mMediasCache.addDownloadListener(downloadId, new MXMediaDownloadListener() { @Override public void onDownloadCancel(String downloadId) { if (TextUtils.equals(downloadId, (String) downloadProgressLayout.getTag())) { downloadProgressLayout.setVisibility(View.GONE); } } @Override public void onDownloadError(String downloadId, JsonElement jsonElement) { if (TextUtils.equals(downloadId, (String) downloadProgressLayout.getTag())) { MatrixError error = null; try { error = JsonUtils.toMatrixError(jsonElement); } catch (Exception e) { Log.e(LOG_TAG, "Cannot cast to Matrix error " + e.getLocalizedMessage()); } downloadProgressLayout.setVisibility(View.GONE); if ((null != error) && error.isSupportedErrorCode()) { Toast.makeText(mContext, error.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } else if (null != jsonElement) { Toast.makeText(mContext, jsonElement.toString(), Toast.LENGTH_LONG).show(); } } } @Override public void onDownloadProgress(String aDownloadId, DownloadStats stats) { if (TextUtils.equals(aDownloadId, (String) downloadProgressLayout.getTag())) { refreshDownloadViews(event, stats, downloadProgressLayout); } } @Override public void onDownloadComplete(String aDownloadId) { if (TextUtils.equals(aDownloadId, (String) downloadProgressLayout.getTag())) { downloadProgressLayout.setVisibility(View.GONE); if (null != mVectorMessagesAdapterEventsListener) { mVectorMessagesAdapterEventsListener.onMediaDownloaded(position); } } } }); refreshDownloadViews(event, mMediasCache.getStatsForDownloadId(downloadId), downloadProgressLayout); } else { downloadProgressLayout.setVisibility(View.GONE); } imageView.setBackgroundColor(Color.TRANSPARENT); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); } /** * Manage the video upload * * @param convertView the base view * @param event the image or video event * @param message the image or video message */ void managePendingImageVideoUpload(final View convertView, final Event event, Message message) { final View uploadProgressLayout = convertView.findViewById(R.id.content_upload_progress_layout); final ProgressBar uploadSpinner = convertView.findViewById(R.id.upload_event_spinner); final boolean isVideoMessage = message instanceof VideoMessage; // the dedicated UI items are not found if ((null == uploadProgressLayout) || (null == uploadSpinner)) { return; } // refresh the progress only if it is the expected URL uploadProgressLayout.setTag(null); boolean hasContentInfo = (null != (isVideoMessage ? ((VideoMessage) message).info : ((ImageMessage) message).info)); // not the sender ? if (!mSession.getMyUserId().equals(event.getSender()) || event.isUndeliverable() || !hasContentInfo) { uploadProgressLayout.setVisibility(View.GONE); uploadSpinner.setVisibility(View.GONE); showUploadFailure(convertView, isVideoMessage ? VectorMessagesAdapter.ROW_TYPE_VIDEO : VectorMessagesAdapter.ROW_TYPE_IMAGE, event.isUndeliverable()); return; } String uploadingUrl; final boolean isUploadingThumbnail; boolean isUploadingContent = false; if (isVideoMessage) { uploadingUrl = ((VideoMessage) message).getThumbnailUrl(); isUploadingThumbnail = ((VideoMessage) message).isThumbnailLocalContent(); } else { uploadingUrl = ((ImageMessage) message).getThumbnailUrl(); isUploadingThumbnail = ((ImageMessage) message).isThumbnailLocalContent(); } int progress; if (isUploadingThumbnail) { progress = mSession.getMediasCache().getProgressValueForUploadId(uploadingUrl); } else { if (message instanceof VideoMessage) { uploadingUrl = ((VideoMessage) message).getUrl(); isUploadingContent = ((VideoMessage) message).isLocalContent(); } else if (message instanceof ImageMessage) { uploadingUrl = ((ImageMessage) message).getUrl(); isUploadingContent = ((ImageMessage) message).isLocalContent(); } progress = mSession.getMediasCache().getProgressValueForUploadId(uploadingUrl); } if (progress >= 0) { uploadProgressLayout.setTag(uploadingUrl); mSession.getMediasCache().addUploadListener(uploadingUrl, new MXMediaUploadListener() { @Override public void onUploadProgress(String uploadId, UploadStats uploadStats) { if (TextUtils.equals((String) uploadProgressLayout.getTag(), uploadId)) { refreshUploadViews(event, uploadStats, uploadProgressLayout); int progress; if (!isUploadingThumbnail) { progress = 10 + (uploadStats.mProgress * 90 / 100); } else { progress = (uploadStats.mProgress * 10 / 100); } updateUploadProgress(uploadProgressLayout, progress); } } private void onUploadStop(String message) { if (!TextUtils.isEmpty(message)) { Toast.makeText(mContext, message, Toast.LENGTH_LONG).show(); } showUploadFailure(convertView, isVideoMessage ? VectorMessagesAdapter.ROW_TYPE_VIDEO : VectorMessagesAdapter.ROW_TYPE_IMAGE, true); uploadProgressLayout.setVisibility(View.GONE); uploadSpinner.setVisibility(View.GONE); } @Override public void onUploadCancel(String uploadId) { if (TextUtils.equals((String) uploadProgressLayout.getTag(), uploadId)) { onUploadStop(null); } } @Override public void onUploadError(String uploadId, int serverResponseCode, String serverErrorMessage) { if (TextUtils.equals((String) uploadProgressLayout.getTag(), uploadId)) { onUploadStop(serverErrorMessage); } } @Override public void onUploadComplete(final String uploadId, final String contentUri) { if (TextUtils.equals((String) uploadProgressLayout.getTag(), uploadId)) { uploadSpinner.setVisibility(View.GONE); } } }); } showUploadFailure(convertView, isVideoMessage ? VectorMessagesAdapter.ROW_TYPE_VIDEO : VectorMessagesAdapter.ROW_TYPE_IMAGE, false); uploadSpinner.setVisibility(((progress < 0) && event.isSending()) ? View.VISIBLE : View.GONE); refreshUploadViews(event, mSession.getMediasCache().getStatsForUploadId(uploadingUrl), uploadProgressLayout); if (isUploadingContent) { progress = 10 + (progress * 90 / 100); } else if (isUploadingThumbnail) { progress = (progress * 10 / 100); } updateUploadProgress(uploadProgressLayout, progress); uploadProgressLayout.setVisibility(((progress >= 0) && event.isSending()) ? View.VISIBLE : View.GONE); } /** * Update the progress bar * * @param uploadProgressLayout the progress layout * @param progress the progress value */ private static void updateUploadProgress(View uploadProgressLayout, int progress) { ProgressBar progressBar = uploadProgressLayout.findViewById(R.id.media_progress_view); if (null != progressBar) { progressBar.setProgress(progress); } } /** * Refresh the upload views. * * @param event the event * @param uploadStats the upload stats * @param uploadProgressLayout the progress layout */ private void refreshUploadViews(final Event event, final IMXMediaUploadListener.UploadStats uploadStats, final View uploadProgressLayout) { if (null != uploadStats) { uploadProgressLayout.setVisibility(View.VISIBLE); TextView uploadProgressStatsTextView = uploadProgressLayout.findViewById(R.id.media_progress_text_view); ProgressBar progressBar = uploadProgressLayout.findViewById(R.id.media_progress_view); if (null != uploadProgressStatsTextView) { uploadProgressStatsTextView.setText(formatUploadStats(mContext, uploadStats)); } if (null != progressBar) { progressBar.setProgress(uploadStats.mProgress); } final View cancelLayout = uploadProgressLayout.findViewById(R.id.media_progress_cancel); if (null != cancelLayout) { cancelLayout.setTag(event); cancelLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (event == cancelLayout.getTag()) { if (null != mVectorMessagesAdapterEventsListener) { mVectorMessagesAdapterEventsListener.onEventAction(event, "", R.id.ic_action_vector_cancel_upload); } } } }); } } else { uploadProgressLayout.setVisibility(View.GONE); } } /** * Manage the file download items. * * @param convertView the message cell view. * @param event the event * @param fileMessage the file message. * @param position the position in the listview. */ void managePendingFileDownload(View convertView, final Event event, FileMessage fileMessage, final int position) { String downloadId = mMediasCache.downloadIdFromUrl(fileMessage.getUrl()); final View downloadProgressLayout = convertView.findViewById(R.id.content_download_progress_layout); if (null == downloadProgressLayout) { return; } downloadProgressLayout.setTag(downloadId); // no download in progress if (null != downloadId) { downloadProgressLayout.setVisibility(View.VISIBLE); mMediasCache.addDownloadListener(downloadId, new MXMediaDownloadListener() { @Override public void onDownloadCancel(String downloadId) { if (TextUtils.equals(downloadId, (String) downloadProgressLayout.getTag())) { downloadProgressLayout.setVisibility(View.GONE); } } @Override public void onDownloadError(String downloadId, JsonElement jsonElement) { if (TextUtils.equals(downloadId, (String) downloadProgressLayout.getTag())) { MatrixError error = null; try { error = JsonUtils.toMatrixError(jsonElement); } catch (Exception e) { Log.e(LOG_TAG, "Cannot cast to Matrix error " + e.getLocalizedMessage()); } downloadProgressLayout.setVisibility(View.GONE); if ((null != error) && error.isSupportedErrorCode()) { Toast.makeText(mContext, error.getLocalizedMessage(), Toast.LENGTH_LONG).show(); } else if (null != jsonElement) { Toast.makeText(mContext, jsonElement.toString(), Toast.LENGTH_LONG).show(); } } } @Override public void onDownloadProgress(String aDownloadId, DownloadStats stats) { if (TextUtils.equals(aDownloadId, (String) downloadProgressLayout.getTag())) { refreshDownloadViews(event, stats, downloadProgressLayout); } } @Override public void onDownloadComplete(String aDownloadId) { if (TextUtils.equals(aDownloadId, (String) downloadProgressLayout.getTag())) { downloadProgressLayout.setVisibility(View.GONE); if (null != mVectorMessagesAdapterEventsListener) { mVectorMessagesAdapterEventsListener.onMediaDownloaded(position); } } } }); refreshDownloadViews(event, mMediasCache.getStatsForDownloadId(downloadId), downloadProgressLayout); } else { downloadProgressLayout.setVisibility(View.GONE); } } /** * Show the upload failure items * * @param convertView the cell view * @param type the media type * @param show true to show the failure items */ private void showUploadFailure(View convertView, int type, boolean show) { if (VectorMessagesAdapter.ROW_TYPE_FILE == type) { TextView fileTextView = convertView.findViewById(R.id.messagesAdapter_filename); if (null != fileTextView) { fileTextView.setTextColor(show ? mNotSentMessageTextColor : mDefaultMessageTextColor); } } else if ((VectorMessagesAdapter.ROW_TYPE_IMAGE == type) || (VectorMessagesAdapter.ROW_TYPE_VIDEO == type)) { View failedLayout = convertView.findViewById(R.id.media_upload_failed); if (null != failedLayout) { failedLayout.setVisibility(show ? View.VISIBLE : View.GONE); } } } /** * Refresh the download views * * @param event the event * @param downloadStats the download stats * @param downloadProgressLayout the download progress layout */ private void refreshDownloadViews(final Event event, final IMXMediaDownloadListener.DownloadStats downloadStats, final View downloadProgressLayout) { if ((null != downloadStats) && isMediaDownloading(event)) { downloadProgressLayout.setVisibility(View.VISIBLE); TextView downloadProgressStatsTextView = downloadProgressLayout .findViewById(R.id.media_progress_text_view); ProgressBar progressBar = downloadProgressLayout.findViewById(R.id.media_progress_view); if (null != downloadProgressStatsTextView) { downloadProgressStatsTextView.setText(formatDownloadStats(mContext, downloadStats)); } if (null != progressBar) { progressBar.setProgress(downloadStats.mProgress); } final View cancelLayout = downloadProgressLayout.findViewById(R.id.media_progress_cancel); if (null != cancelLayout) { cancelLayout.setTag(event); cancelLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (event == cancelLayout.getTag()) { if (null != mVectorMessagesAdapterEventsListener) { mVectorMessagesAdapterEventsListener.onEventAction(event, "", R.id.ic_action_vector_cancel_download); } } } }); } } else { downloadProgressLayout.setVisibility(View.GONE); } } /** * Tells if the downloadId is the media download id. * * @param event the event * @return true if the media is downloading (not the thumbnail) */ private boolean isMediaDownloading(Event event) { if (TextUtils.equals(event.getType(), Event.EVENT_TYPE_MESSAGE)) { Message message = JsonUtils.toMessage(event.getContent()); String url = null; if (TextUtils.equals(message.msgtype, Message.MSGTYPE_IMAGE)) { url = JsonUtils.toImageMessage(event.getContent()).getUrl(); } else if (TextUtils.equals(message.msgtype, Message.MSGTYPE_VIDEO)) { url = JsonUtils.toVideoMessage(event.getContent()).getUrl(); } else if (TextUtils.equals(message.msgtype, Message.MSGTYPE_FILE)) { url = JsonUtils.toFileMessage(event.getContent()).getUrl(); } if (!TextUtils.isEmpty(url)) { return null != mSession.getMediasCache().downloadIdFromUrl(url); } } return false; } //============================================================================================================== // Download / upload progress management //============================================================================================================== /** * Format a second time range. * * @param seconds the seconds time * @return the formatted string */ private static String vectorRemainingTimeToString(Context context, int seconds) { if (seconds < 0) { return ""; } else if (seconds <= 1) { return "< 1s"; } else if (seconds < 60) { return context.getString(R.string.attachment_remaining_time_seconds, seconds); } else if (seconds < 3600) { return context.getString(R.string.attachment_remaining_time_minutes, (seconds / 60), (seconds % 60)); } else { return DateUtils.formatElapsedTime(seconds); } } /** * Format the download / upload stats. * * @param context the context. * @param progressFileSize the upload / download media size. * @param fileSize the expected media size. * @param remainingTime the remaining time (seconds) * @return the formatted string. */ private static String formatStats(Context context, int progressFileSize, int fileSize, int remainingTime) { String formattedString = ""; if (fileSize > 0) { formattedString += android.text.format.Formatter.formatShortFileSize(context, progressFileSize); formattedString += " / " + android.text.format.Formatter.formatShortFileSize(context, fileSize); } if (remainingTime > 0) { if (!TextUtils.isEmpty(formattedString)) { formattedString += " (" + vectorRemainingTimeToString(context, remainingTime) + ")"; } else { formattedString += vectorRemainingTimeToString(context, remainingTime); } } return formattedString; } /** * Format the download stats. * * @param context the context. * @param stats the download stats * @return the formatted string */ private static String formatDownloadStats(Context context, IMXMediaDownloadListener.DownloadStats stats) { return formatStats(context, stats.mDownloadedSize, stats.mFileSize, stats.mEstimatedRemainingTime); } /** * Format the upload stats. * * @param context the context. * @param stats the upload stats * @return the formatted string */ private static String formatUploadStats(Context context, IMXMediaUploadListener.UploadStats stats) { return formatStats(context, stats.mUploadedSize, stats.mFileSize, stats.mEstimatedRemainingTime); } }