diff options
29 files changed, 383 insertions, 175 deletions
diff --git a/res/layout/compose_message_view.xml b/res/layout/compose_message_view.xml index fd60e2a..8bb8249 100644 --- a/res/layout/compose_message_view.xml +++ b/res/layout/compose_message_view.xml @@ -88,8 +88,8 @@ android:layout_height="wrap_content" android:orientation="horizontal"> - <!-- Contains compose message bubble and character counter for SMS which should be left - aligned --> + <!-- Contains compose message bubble and character counter for SMS or attachments size + for MMS which should be left aligned --> <LinearLayout android:layout_width="0dp" android:layout_weight="1" @@ -128,8 +128,8 @@ </LinearLayout> <TextView - android:id="@+id/char_counter" - style="@style/ComposeMessageViewTextCounterStyle" + android:id="@+id/message_body_size" + style="@style/ComposeMessageViewMessageBodySizeStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" diff --git a/res/layout/gallery_grid_item_view.xml b/res/layout/gallery_grid_item_view.xml index 8b7ee58..fc857ca 100644 --- a/res/layout/gallery_grid_item_view.xml +++ b/res/layout/gallery_grid_item_view.xml @@ -21,12 +21,67 @@ android:background="@color/gallery_image_default_background" android:clickable="true"> + <!-- Thumbnail for image and video contents. --> <com.android.messaging.ui.AsyncImageView - android:id="@+id/image" + android:id="@+id/thumbnail" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" /> + <!-- Additional info such as icon, name and etc. --> + <RelativeLayout + android:id="@+id/additional_info" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center" + android:orientation="vertical" + android:visibility="gone" > + + <FrameLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_above="@id/file_info" > + <ImageView + android:id="@+id/icon" + android:layout_width="@dimen/gallery_icon_size" + android:layout_height="@dimen/gallery_icon_size" + android:layout_gravity="center" + android:scaleType="fitCenter" + android:background="@color/background_item_transparent" + android:visibility="gone" /> + </FrameLayout> + + <!-- File info for audio contents only --> + <LinearLayout + android:id="@+id/file_info" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_marginBottom="4dp" + android:paddingLeft="4dp" + android:paddingRight="4dp" + android:orientation="vertical" + android:visibility="gone" > + + <TextView + android:id="@+id/file_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="end" + android:textAppearance="@android:style/TextAppearance.Material.Subhead" /> + + <TextView + android:id="@+id/file_type" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="end" + android:gravity="right" + android:textAppearance="@android:style/TextAppearance.Material.Caption" /> + </LinearLayout> + </RelativeLayout> + <View android:layout_width="match_parent" android:layout_height="match_parent" @@ -43,4 +98,5 @@ android:paddingTop="4dp" android:visibility="gone" android:contentDescription="@string/gallery_checkbox_content_description" /> + </com.android.messaging.ui.mediapicker.GalleryGridItemView> diff --git a/res/layout/mediapicker_image_chooser.xml b/res/layout/mediapicker_gallery_chooser.xml index b4f3c01..b4f3c01 100644 --- a/res/layout/mediapicker_image_chooser.xml +++ b/res/layout/mediapicker_gallery_chooser.xml diff --git a/res/values-ldrtl/styles.xml b/res/values-ldrtl/styles.xml index bd270c7..de4d9e8 100644 --- a/res/values-ldrtl/styles.xml +++ b/res/values-ldrtl/styles.xml @@ -171,9 +171,9 @@ <item name="android:layout_marginStart">4dp</item> </style> - <style name="ComposeMessageViewTextCounterStyle"> - <item name="android:textColor">@color/message_text_counter_color</item> - <item name="android:textSize">@dimen/message_text_counter_size</item> + <style name="ComposeMessageViewMessageBodySizeStyle"> + <item name="android:textColor">@color/message_body_size_text_color</item> + <item name="android:textSize">@dimen/message_body_size_text_size</item> <item name="android:fontFamily">sans-serif</item> <item name="android:layout_gravity">end|center_vertical</item> <item name="android:paddingEnd">@dimen/compose_message_text_box_padding_side</item> diff --git a/res/values/colors.xml b/res/values/colors.xml index f33e105..035ed81 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -128,7 +128,7 @@ <color name="fab_pressed_color">#3ea4dc</color> <color name="fab_ripple">#40ffffff</color> - <color name="message_text_counter_color">#555555</color> + <color name="message_body_size_text_color">#555555</color> <color name="mms_indicator_color">#8BC34A</color> <color name="list_empty_text">#6d6d6d</color> <color name="low_storage_action_item_color">#ff000000</color> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 5ff0eb7..d775c7e 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -85,6 +85,7 @@ <!-- Flings faster than this length / sec will go from fullscreen straight to closed --> <dimen name="mediapicker_big_fling_threshold">1000dp</dimen> <dimen name="gallery_image_cell_size">110dp</dimen> + <dimen name="gallery_icon_size">40dp</dimen> <dimen name="single_attachment_min_dimen">50dp</dimen> <dimen name="single_attachment_max_height">150dp</dimen> <dimen name="multiple_attachment_preview_height">130dp</dimen> @@ -116,7 +117,7 @@ <dimen name="fab_elevation_pressed">6dp</dimen> <dimen name="fab_bottom_margin">12dp</dimen> <dimen name="fab_left_right_margin">14dp</dimen> - <dimen name="message_text_counter_size">12sp</dimen> + <dimen name="message_body_size_text_size">12sp</dimen> <dimen name="vcard_detail_group_indicator_width">40dp</dimen> <dimen name="mms_indicator_size">12sp</dimen> diff --git a/res/values/strings.xml b/res/values/strings.xml index 0e91156..521b1fa 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -53,7 +53,7 @@ <string name="mediapicker_cameraChooserDescription">Capture pictures or video</string> <string name="mediapicker_galleryChooserDescription">Choose images from this device</string> <string name="mediapicker_audioChooserDescription">Record audio</string> - <string name="mediapicker_gallery_title">Choose photo</string> + <string name="mediapicker_gallery_title">Choose media</string> <string name="mediapicker_gallery_item_selected_content_description">The media is selected.</string> <string name="mediapicker_gallery_item_unselected_content_description">The media is unselected.</string> <string name="mediapicker_gallery_title_selection"><xliff:g id="count">%d</xliff:g> selected</string> diff --git a/res/values/styles.xml b/res/values/styles.xml index 442818d..46533af 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -365,9 +365,9 @@ <item name="android:dividerHeight">0dp</item> </style> - <style name="ComposeMessageViewTextCounterStyle"> - <item name="android:textColor">@color/message_text_counter_color</item> - <item name="android:textSize">@dimen/message_text_counter_size</item> + <style name="ComposeMessageViewMessageBodySizeStyle"> + <item name="android:textColor">@color/message_body_size_text_color</item> + <item name="android:textSize">@dimen/message_body_size_text_size</item> <item name="android:fontFamily">sans-serif</item> <item name="android:layout_gravity">right|center_vertical</item> <item name="android:paddingRight">@dimen/compose_message_text_box_padding_side</item> diff --git a/src/com/android/messaging/datamodel/GalleryBoundCursorLoader.java b/src/com/android/messaging/datamodel/GalleryBoundCursorLoader.java index 28ec303..1974a5e 100644 --- a/src/com/android/messaging/datamodel/GalleryBoundCursorLoader.java +++ b/src/com/android/messaging/datamodel/GalleryBoundCursorLoader.java @@ -20,7 +20,7 @@ import android.content.Context; import android.net.Uri; import android.provider.MediaStore.Files; import android.provider.MediaStore.Files.FileColumns; -import android.provider.MediaStore.Images.Media; +import android.provider.MediaStore.MediaColumns; import com.android.messaging.datamodel.data.GalleryGridItemData; import com.android.messaging.datamodel.data.MessagePartData; @@ -32,18 +32,22 @@ import com.google.common.base.Joiner; public class GalleryBoundCursorLoader extends BoundCursorLoader { public static final String MEDIA_SCANNER_VOLUME_EXTERNAL = "external"; private static final Uri STORAGE_URI = Files.getContentUri(MEDIA_SCANNER_VOLUME_EXTERNAL); - private static final String SORT_ORDER = Media.DATE_MODIFIED + " DESC"; - private static final String IMAGE_SELECTION = createSelection( - MessagePartData.ACCEPTABLE_IMAGE_TYPES, - new Integer[] { FileColumns.MEDIA_TYPE_IMAGE }); + private static final String SORT_ORDER = MediaColumns.DATE_MODIFIED + " DESC"; + private static final String SELECTION = createSelection( + MessagePartData.ACCEPTABLE_GALLERY_MEDIA_TYPES, + new Integer[] { + FileColumns.MEDIA_TYPE_IMAGE, + FileColumns.MEDIA_TYPE_VIDEO, + FileColumns.MEDIA_TYPE_AUDIO + }); public GalleryBoundCursorLoader(final String bindingId, final Context context) { - super(bindingId, context, STORAGE_URI, GalleryGridItemData.IMAGE_PROJECTION, - IMAGE_SELECTION, null, SORT_ORDER); + super(bindingId, context, STORAGE_URI, GalleryGridItemData.MEDIA_PROJECTION, SELECTION, + null, SORT_ORDER); } private static String createSelection(final String[] mimeTypes, Integer[] mediaTypes) { - return Media.MIME_TYPE + " IN ('" + Joiner.on("','").join(mimeTypes) + "') AND " + return MediaColumns.MIME_TYPE + " IN ('" + Joiner.on("','").join(mimeTypes) + "') AND " + FileColumns.MEDIA_TYPE + " IN (" + Joiner.on(',').join(mediaTypes) + ")"; } } diff --git a/src/com/android/messaging/datamodel/data/GalleryGridItemData.java b/src/com/android/messaging/datamodel/data/GalleryGridItemData.java index 6649757..941d38d 100644 --- a/src/com/android/messaging/datamodel/data/GalleryGridItemData.java +++ b/src/com/android/messaging/datamodel/data/GalleryGridItemData.java @@ -20,25 +20,29 @@ import android.database.Cursor; import android.graphics.Rect; import android.net.Uri; import android.provider.BaseColumns; -import android.provider.MediaStore.Images.Media; +import android.provider.MediaStore.MediaColumns; import android.text.TextUtils; import com.android.messaging.datamodel.media.FileImageRequestDescriptor; import com.android.messaging.datamodel.media.ImageRequest; import com.android.messaging.datamodel.media.UriImageRequestDescriptor; +import com.android.messaging.datamodel.media.VideoThumbnailRequestDescriptor; import com.android.messaging.util.Assert; +import com.android.messaging.util.ContentType; +import com.android.messaging.util.UriUtil; /** * Provides data for GalleryGridItemView */ public class GalleryGridItemData { - public static final String[] IMAGE_PROJECTION = new String[] { - Media._ID, - Media.DATA, - Media.WIDTH, - Media.HEIGHT, - Media.MIME_TYPE, - Media.DATE_MODIFIED}; + public static final String[] MEDIA_PROJECTION = new String[] { + MediaColumns._ID, + MediaColumns.DATA, + MediaColumns.WIDTH, + MediaColumns.HEIGHT, + MediaColumns.MIME_TYPE, + MediaColumns.DATE_MODIFIED, + MediaColumns.DISPLAY_NAME}; public static final String[] SPECIAL_ITEM_COLUMNS = new String[] { BaseColumns._ID @@ -46,20 +50,23 @@ public class GalleryGridItemData { private static final int INDEX_ID = 0; - // For local image gallery. + // For local media gallery. private static final int INDEX_DATA_PATH = 1; private static final int INDEX_WIDTH = 2; private static final int INDEX_HEIGHT = 3; private static final int INDEX_MIME_TYPE = 4; private static final int INDEX_DATE_MODIFIED = 5; + private static final int INDEX_DISPLAY_NAME = 6; - /** A special item's id for picking images from document picker */ + /** A special item's id for picking a media from document picker */ public static final String ID_DOCUMENT_PICKER_ITEM = "-1"; private UriImageRequestDescriptor mImageData; private String mContentType; private boolean mIsDocumentPickerItem; private long mDateSeconds; + private String mFileName; + private Uri mAudioUri; public GalleryGridItemData() { } @@ -71,29 +78,45 @@ public class GalleryGridItemData { mImageData = null; mContentType = null; } else { - int sourceWidth = cursor.getInt(INDEX_WIDTH); - int sourceHeight = cursor.getInt(INDEX_HEIGHT); - - // Guard against bad data - if (sourceWidth <= 0) { - sourceWidth = ImageRequest.UNSPECIFIED_SIZE; - } - if (sourceHeight <= 0) { - sourceHeight = ImageRequest.UNSPECIFIED_SIZE; - } - mContentType = cursor.getString(INDEX_MIME_TYPE); + final String filePath = cursor.getString(INDEX_DATA_PATH); final String dateModified = cursor.getString(INDEX_DATE_MODIFIED); mDateSeconds = !TextUtils.isEmpty(dateModified) ? Long.parseLong(dateModified) : -1; - mImageData = new FileImageRequestDescriptor( - cursor.getString(INDEX_DATA_PATH), - desiredWidth, - desiredHeight, - sourceWidth, - sourceHeight, - true /* canUseThumbnail */, - true /* allowCompression */, - true /* isStatic */); + if (ContentType.isAudioType(mContentType)) { + mImageData = null; + mAudioUri = UriUtil.getUriForResourceFile(filePath); + mFileName = cursor.getString(INDEX_DISPLAY_NAME); + } else { // For image and video types + int sourceWidth = cursor.getInt(INDEX_WIDTH); + int sourceHeight = cursor.getInt(INDEX_HEIGHT); + + // Guard against bad data + if (sourceWidth <= 0) { + sourceWidth = ImageRequest.UNSPECIFIED_SIZE; + } + if (sourceHeight <= 0) { + sourceHeight = ImageRequest.UNSPECIFIED_SIZE; + } + + if (ContentType.isVideoType(mContentType)) { + mImageData = new VideoThumbnailRequestDescriptor( + cursor.getLong(INDEX_ID), + desiredWidth, + desiredHeight, + sourceWidth, + sourceHeight); + } else { + mImageData = new FileImageRequestDescriptor( + filePath, + desiredWidth, + desiredHeight, + sourceWidth, + sourceHeight, + true /* canUseThumbnail */, + true /* allowCompression */, + true /* isStatic */); + } + } } } @@ -102,7 +125,7 @@ public class GalleryGridItemData { } public Uri getImageUri() { - return mImageData.uri; + return ContentType.isAudioType(mContentType) ? mAudioUri : mImageData.uri; } public UriImageRequestDescriptor getImageRequestDescriptor() { @@ -111,8 +134,10 @@ public class GalleryGridItemData { public MessagePartData constructMessagePartData(final Rect startRect) { Assert.isTrue(!mIsDocumentPickerItem); - return new MediaPickerMessagePartData(startRect, mContentType, - mImageData.uri, mImageData.sourceWidth, mImageData.sourceHeight); + return ContentType.isAudioType(mContentType) + ? new MediaPickerMessagePartData(startRect, mContentType, mAudioUri, 0, 0) + : new MediaPickerMessagePartData(startRect, mContentType, mImageData.uri, + mImageData.sourceWidth, mImageData.sourceHeight); } /** @@ -125,4 +150,8 @@ public class GalleryGridItemData { public String getContentType() { return mContentType; } + + public String getFileName() { + return mFileName; + } } diff --git a/src/com/android/messaging/datamodel/data/MediaPickerData.java b/src/com/android/messaging/datamodel/data/MediaPickerData.java index 7fef67f..5a2ef33 100644 --- a/src/com/android/messaging/datamodel/data/MediaPickerData.java +++ b/src/com/android/messaging/datamodel/data/MediaPickerData.java @@ -51,7 +51,7 @@ public class MediaPickerData extends BindableData { mGalleryLoaderCallbacks = new GalleryLoaderCallbacks(); } - public static final int GALLERY_IMAGE_LOADER = 1; + public static final int GALLERY_MEDIA_LOADER = 1; /** * A trampoline class so that we can inherit from LoaderManager.LoaderCallbacks multiple times. @@ -63,7 +63,7 @@ public class MediaPickerData extends BindableData { // Check if data still bound to the requesting ui element if (isBound(bindingId)) { switch (id) { - case GALLERY_IMAGE_LOADER: + case GALLERY_MEDIA_LOADER: return new GalleryBoundCursorLoader(bindingId, mContext); default: @@ -84,9 +84,9 @@ public class MediaPickerData extends BindableData { final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader; if (isBound(cursorLoader.getBindingId())) { switch (loader.getId()) { - case GALLERY_IMAGE_LOADER: + case GALLERY_MEDIA_LOADER: mListener.onMediaPickerDataUpdated(MediaPickerData.this, data, - GALLERY_IMAGE_LOADER); + GALLERY_MEDIA_LOADER); break; default: @@ -106,9 +106,9 @@ public class MediaPickerData extends BindableData { final BoundCursorLoader cursorLoader = (BoundCursorLoader) loader; if (isBound(cursorLoader.getBindingId())) { switch (loader.getId()) { - case GALLERY_IMAGE_LOADER: + case GALLERY_MEDIA_LOADER: mListener.onMediaPickerDataUpdated(MediaPickerData.this, null, - GALLERY_IMAGE_LOADER); + GALLERY_MEDIA_LOADER); break; default: @@ -129,7 +129,7 @@ public class MediaPickerData extends BindableData { args = new Bundle(); } args.putString(BINDING_ID, binding.getBindingId()); - if (loaderId == GALLERY_IMAGE_LOADER) { + if (loaderId == GALLERY_MEDIA_LOADER) { mLoaderManager.initLoader(loaderId, args, mGalleryLoaderCallbacks).forceLoad(); } else { Assert.fail("Unsupported loader id for media picker!"); @@ -149,7 +149,7 @@ public class MediaPickerData extends BindableData { protected void unregisterListeners() { // This could be null if we bind but the caller doesn't init the BindableData if (mLoaderManager != null) { - mLoaderManager.destroyLoader(GALLERY_IMAGE_LOADER); + mLoaderManager.destroyLoader(GALLERY_MEDIA_LOADER); mLoaderManager = null; } } @@ -172,4 +172,4 @@ public class MediaPickerData extends BindableData { selectedIndex); } -}
\ No newline at end of file +} diff --git a/src/com/android/messaging/datamodel/data/MessagePartData.java b/src/com/android/messaging/datamodel/data/MessagePartData.java index 1bb024d..ea24876 100644 --- a/src/com/android/messaging/datamodel/data/MessagePartData.java +++ b/src/com/android/messaging/datamodel/data/MessagePartData.java @@ -52,9 +52,22 @@ import java.util.concurrent.TimeUnit; */ public class MessagePartData implements Parcelable { public static final int UNSPECIFIED_SIZE = MessagingContentProvider.UNSPECIFIED_SIZE; - public static final String[] ACCEPTABLE_IMAGE_TYPES = - new String[] { ContentType.IMAGE_JPEG, ContentType.IMAGE_JPG, ContentType.IMAGE_PNG, - ContentType.IMAGE_GIF }; + + public static final String[] ACCEPTABLE_GALLERY_MEDIA_TYPES = + new String[] { + // Acceptable image types + ContentType.IMAGE_JPEG, ContentType.IMAGE_JPG, ContentType.IMAGE_PNG, + ContentType.IMAGE_GIF, ContentType.IMAGE_WBMP, ContentType.IMAGE_X_MS_BMP, + // Acceptable video types + ContentType.VIDEO_3GP, ContentType.VIDEO_3GPP, ContentType.VIDEO_3G2, + ContentType.VIDEO_H263, ContentType.VIDEO_M4V, ContentType.VIDEO_MP4, + ContentType.VIDEO_MPEG, ContentType.VIDEO_MPEG4, ContentType.VIDEO_WEBM, + // Acceptable audio types + ContentType.AUDIO_MP3, ContentType.AUDIO_MP4, ContentType.AUDIO_MIDI, + ContentType.AUDIO_MID, ContentType.AUDIO_AMR, ContentType.AUDIO_X_WAV, + ContentType.AUDIO_AAC, ContentType.AUDIO_X_MIDI, ContentType.AUDIO_X_MID, + ContentType.AUDIO_X_MP3 + }; private static final String[] sProjection = { PartColumns._ID, @@ -328,6 +341,11 @@ public class MessagePartData implements Parcelable { return mHeight; } + public static boolean isSupportedMediaType(final String contentType) { + return ContentType.isVCardType(contentType) + || Arrays.asList(ACCEPTABLE_GALLERY_MEDIA_TYPES).contains(contentType); + } + /** * * @return true if this part can only exist by itself, with no other attachments diff --git a/src/com/android/messaging/datamodel/media/UriImageRequestDescriptor.java b/src/com/android/messaging/datamodel/media/UriImageRequestDescriptor.java index c5685d1..dae293a 100644 --- a/src/com/android/messaging/datamodel/media/UriImageRequestDescriptor.java +++ b/src/com/android/messaging/datamodel/media/UriImageRequestDescriptor.java @@ -87,9 +87,4 @@ public class UriImageRequestDescriptor extends ImageRequestDescriptor { return new NetworkUriImageRequest<UriImageRequestDescriptor>(context, this); } } - - /** ID of the resource in MediaStore or null if this resource didn't come from MediaStore */ - public Long getMediaStoreId() { - return null; - } -}
\ No newline at end of file +} diff --git a/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java b/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java index 219e0a6..73ce5e0 100644 --- a/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java +++ b/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java @@ -16,15 +16,11 @@ package com.android.messaging.datamodel.media; -import android.content.ContentResolver; import android.content.Context; import android.graphics.Bitmap; -import android.provider.MediaStore.Video.Thumbnails; -import com.android.messaging.Factory; import com.android.messaging.util.MediaMetadataRetrieverWrapper; import com.android.messaging.util.MediaUtil; -import com.android.messaging.util.OsUtil; import java.io.FileNotFoundException; import java.io.IOException; @@ -57,19 +53,15 @@ public class VideoThumbnailRequest extends ImageRequest<UriImageRequestDescripto @Override protected Bitmap getBitmapForResource() throws IOException { - final Long mediaId = mDescriptor.getMediaStoreId(); Bitmap bitmap = null; - if (mediaId != null) { - final ContentResolver cr = Factory.get().getApplicationContext().getContentResolver(); - bitmap = Thumbnails.getThumbnail(cr, mediaId, Thumbnails.MICRO_KIND, null); - } else { - final MediaMetadataRetrieverWrapper retriever = new MediaMetadataRetrieverWrapper(); - try { - retriever.setDataSource(mDescriptor.uri); - bitmap = retriever.getFrameAtTime(); - } finally { - retriever.release(); - } + // Get a thumbnail through MediaMetadataRetriever to get a representative frame at any time + // position instead. + final MediaMetadataRetrieverWrapper retriever = new MediaMetadataRetrieverWrapper(); + try { + retriever.setDataSource(mDescriptor.uri); + bitmap = retriever.getFrameAtTime(); + } finally { + retriever.release(); } if (bitmap != null) { mDescriptor.updateSourceDimensions(bitmap.getWidth(), bitmap.getHeight()); diff --git a/src/com/android/messaging/datamodel/media/VideoThumbnailRequestDescriptor.java b/src/com/android/messaging/datamodel/media/VideoThumbnailRequestDescriptor.java index 907bb8f..22f1871 100644 --- a/src/com/android/messaging/datamodel/media/VideoThumbnailRequestDescriptor.java +++ b/src/com/android/messaging/datamodel/media/VideoThumbnailRequestDescriptor.java @@ -21,24 +21,17 @@ import com.android.messaging.util.ImageUtils; import com.android.messaging.util.UriUtil; public class VideoThumbnailRequestDescriptor extends UriImageRequestDescriptor { - protected final long mMediaId; - public VideoThumbnailRequestDescriptor(final long id, String path, int desiredWidth, - int desiredHeight, int sourceWidth, int sourceHeight) { - super(UriUtil.getUriForResourceFile(path), desiredWidth, desiredHeight, sourceWidth, + public VideoThumbnailRequestDescriptor(final long id, int desiredWidth, int desiredHeight, + int sourceWidth, int sourceHeight) { + super(UriUtil.getContentUriForMediaStoreId(id), desiredWidth, desiredHeight, sourceWidth, sourceHeight, false /* canCompress */, false /* isStatic */, false /* cropToCircle */, ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */, ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */); - mMediaId = id; } @Override public MediaRequest<ImageResource> buildSyncMediaRequest(Context context) { return new VideoThumbnailRequest(context, this); } - - @Override - public Long getMediaStoreId() { - return mMediaId; - } } diff --git a/src/com/android/messaging/ui/UIIntents.java b/src/com/android/messaging/ui/UIIntents.java index e5f8a52..b09c457 100644 --- a/src/com/android/messaging/ui/UIIntents.java +++ b/src/com/android/messaging/ui/UIIntents.java @@ -44,8 +44,8 @@ public abstract class UIIntents { // Sending draft data (from share intent / message forwarding) to the ConversationActivity. public static final String UI_INTENT_EXTRA_DRAFT_DATA = "draft_data"; - // The request code for picking image from the Document picker. - public static final int REQUEST_PICK_IMAGE_FROM_DOCUMENT_PICKER = 1400; + // The request code for picking a media from the Document picker. + public static final int REQUEST_PICK_MEDIA_FROM_DOCUMENT_PICKER = 1400; // Indicates what type of notification this applies to (See BugleNotifications: // UPDATE_NONE, UPDATE_MESSAGES, UPDATE_ERRORS, UPDATE_ALL) @@ -166,7 +166,8 @@ public abstract class UIIntents { public abstract void launchAddContactActivity(final Context context, final String destination); /** - * Launch an activity to show the document picker to pick an image. + * Launch an activity to show the document picker to pick an image/video. + * * @param fragment the requesting fragment */ public abstract void launchDocumentImagePicker(final Fragment fragment); diff --git a/src/com/android/messaging/ui/UIIntentsImpl.java b/src/com/android/messaging/ui/UIIntentsImpl.java index fb624ad..ac430cd 100644 --- a/src/com/android/messaging/ui/UIIntentsImpl.java +++ b/src/com/android/messaging/ui/UIIntentsImpl.java @@ -236,11 +236,11 @@ public class UIIntentsImpl extends UIIntents { @Override public void launchDocumentImagePicker(final Fragment fragment) { final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.putExtra(Intent.EXTRA_MIME_TYPES, MessagePartData.ACCEPTABLE_IMAGE_TYPES); + intent.putExtra(Intent.EXTRA_MIME_TYPES, MessagePartData.ACCEPTABLE_GALLERY_MEDIA_TYPES); intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.setType(ContentType.IMAGE_UNSPECIFIED); + intent.setType(ContentType.ANY_TYPE); - fragment.startActivityForResult(intent, REQUEST_PICK_IMAGE_FROM_DOCUMENT_PICKER); + fragment.startActivityForResult(intent, REQUEST_PICK_MEDIA_FROM_DOCUMENT_PICKER); } @Override diff --git a/src/com/android/messaging/ui/conversation/ComposeMessageView.java b/src/com/android/messaging/ui/conversation/ComposeMessageView.java index 5db1292..0f36e9a 100644 --- a/src/com/android/messaging/ui/conversation/ComposeMessageView.java +++ b/src/com/android/messaging/ui/conversation/ComposeMessageView.java @@ -27,6 +27,7 @@ import android.text.InputFilter; import android.text.InputFilter.LengthFilter; import android.text.TextUtils; import android.text.TextWatcher; +import android.text.format.Formatter; import android.util.AttributeSet; import android.view.ContextThemeWrapper; import android.view.KeyEvent; @@ -67,7 +68,9 @@ import com.android.messaging.util.ContentType; import com.android.messaging.util.LogUtil; import com.android.messaging.util.MediaUtil; import com.android.messaging.util.OsUtil; +import com.android.messaging.util.SafeAsyncTask; import com.android.messaging.util.UiUtils; +import com.android.messaging.util.UriUtil; import java.util.Collection; import java.util.List; @@ -112,7 +115,7 @@ public class ComposeMessageView extends LinearLayout private PlainTextEditText mComposeEditText; private PlainTextEditText mComposeSubjectText; - private TextView mCharCounter; + private TextView mMessageBodySize; private TextView mMmsIndicator; private SimIconView mSelfSendIcon; private ImageButton mSendButton; @@ -171,7 +174,7 @@ public class ComposeMessageView extends LinearLayout final int counterColor = mHost.overrideCounterColor(); if (counterColor != -1) { - mCharCounter.setTextColor(counterColor); + mMessageBodySize.setTextColor(counterColor); } } @@ -309,7 +312,7 @@ public class ComposeMessageView extends LinearLayout mAttachmentPreview = (AttachmentPreview) findViewById(R.id.attachment_draft_view); mAttachmentPreview.setComposeMessageView(this); - mCharCounter = (TextView) findViewById(R.id.char_counter); + mMessageBodySize = (TextView) findViewById(R.id.message_body_size); mMmsIndicator = (TextView) findViewById(R.id.mms_indicator); } @@ -480,6 +483,8 @@ public class ComposeMessageView extends LinearLayout final String subject = data.getMessageSubject(); final String message = data.getMessageText(); + boolean hasAttachmentsChanged = false; + if ((changeFlags & DraftMessageData.MESSAGE_SUBJECT_CHANGED) == DraftMessageData.MESSAGE_SUBJECT_CHANGED) { mComposeSubjectText.setText(subject); @@ -500,12 +505,13 @@ public class ComposeMessageView extends LinearLayout DraftMessageData.ATTACHMENTS_CHANGED) { final boolean haveAttachments = mAttachmentPreview.onAttachmentsChanged(data); mHost.onAttachmentsChanged(haveAttachments); + hasAttachmentsChanged = true; } if ((changeFlags & DraftMessageData.SELF_CHANGED) == DraftMessageData.SELF_CHANGED) { updateOnSelfSubscriptionChange(); } - updateVisualsOnDraftChanged(); + updateVisualsOnDraftChanged(hasAttachmentsChanged); } @Override // From DraftMessageDataListener @@ -624,7 +630,44 @@ public class ComposeMessageView extends LinearLayout mConversationDataModel.getData().getParticipantsLoaded(); } + private static class AsyncUpdateMessageBodySizeTask + extends SafeAsyncTask<List<MessagePartData>, Void, Long> { + + private final Context mContext; + private final TextView mSizeTextView; + + public AsyncUpdateMessageBodySizeTask(final Context context, final TextView tv) { + mContext = context; + mSizeTextView = tv; + } + + @Override + protected Long doInBackgroundTimed(final List<MessagePartData>... params) { + final List<MessagePartData> attachments = params[0]; + long totalSize = 0; + for (final MessagePartData attachment : attachments) { + final Uri contentUri = attachment.getContentUri(); + if (contentUri != null) { + totalSize += UriUtil.getContentSize(attachment.getContentUri()); + } + } + return totalSize; + } + + @Override + protected void onPostExecute(Long size) { + if (mSizeTextView != null) { + mSizeTextView.setText(Formatter.formatFileSize(mContext, size)); + mSizeTextView.setVisibility(View.VISIBLE); + } + } + } + private void updateVisualsOnDraftChanged() { + updateVisualsOnDraftChanged(false); + } + + private void updateVisualsOnDraftChanged(boolean hasAttachmentsChanged) { final String messageText = mComposeEditText.getText().toString(); final DraftMessageData draftMessageData = mBinding.getData(); draftMessageData.setMessageText(messageText); @@ -640,26 +683,39 @@ public class ComposeMessageView extends LinearLayout final boolean hasWorkingDraft = hasMessageText || hasSubject || mBinding.getData().hasAttachments(); - // Update the SMS text counter. - final int messageCount = draftMessageData.getNumMessagesToBeSent(); - final int codePointsRemaining = draftMessageData.getCodePointsRemainingInCurrentMessage(); - // Show the counter only if: - // - We are not in MMS mode - // - We are going to send more than one message OR we are getting close - boolean showCounter = false; - if (!draftMessageData.getIsMms() && (messageCount > 1 || - codePointsRemaining <= CODEPOINTS_REMAINING_BEFORE_COUNTER_SHOWN)) { - showCounter = true; - } - - if (showCounter) { - // Update the remaining characters and number of messages required. - final String counterText = messageCount > 1 ? codePointsRemaining + " / " + - messageCount : String.valueOf(codePointsRemaining); - mCharCounter.setText(counterText); - mCharCounter.setVisibility(View.VISIBLE); - } else { - mCharCounter.setVisibility(View.INVISIBLE); + final List<MessagePartData> attachments = draftMessageData.getReadOnlyAttachments(); + if (draftMessageData.getIsMms()) { // MMS case + if (draftMessageData.hasAttachments()) { + if (hasAttachmentsChanged) { + // Calculate message attachments size and show it. + new AsyncUpdateMessageBodySizeTask(getContext(), mMessageBodySize) + .executeOnThreadPool(attachments, null, null); + } else { + // No update. Just show previous size. + mMessageBodySize.setVisibility(View.VISIBLE); + } + } else { + mMessageBodySize.setVisibility(View.INVISIBLE); + } + } else { // SMS case + // Update the SMS text counter. + final int messageCount = draftMessageData.getNumMessagesToBeSent(); + final int codePointsRemaining = + draftMessageData.getCodePointsRemainingInCurrentMessage(); + // Show the counter only if we are going to send more than one message OR we are getting + // close. + if (messageCount > 1 + || codePointsRemaining <= CODEPOINTS_REMAINING_BEFORE_COUNTER_SHOWN) { + // Update the remaining characters and number of messages required. + final String counterText = + messageCount > 1 + ? codePointsRemaining + " / " + messageCount + : String.valueOf(codePointsRemaining); + mMessageBodySize.setText(counterText); + mMessageBodySize.setVisibility(View.VISIBLE); + } else { + mMessageBodySize.setVisibility(View.INVISIBLE); + } } // Update the send message button. Self icon uri might be null if self participant data @@ -699,7 +755,6 @@ public class ComposeMessageView extends LinearLayout } // Update the text hint on the message box depending on the attachment type. - final List<MessagePartData> attachments = draftMessageData.getReadOnlyAttachments(); final int attachmentCount = attachments.size(); if (attachmentCount == 0) { final SubscriptionListEntry subscriptionListEntry = diff --git a/src/com/android/messaging/ui/conversationlist/ShareIntentActivity.java b/src/com/android/messaging/ui/conversationlist/ShareIntentActivity.java index 25d5ea3..412177e 100644 --- a/src/com/android/messaging/ui/conversationlist/ShareIntentActivity.java +++ b/src/com/android/messaging/ui/conversationlist/ShareIntentActivity.java @@ -103,7 +103,7 @@ public class ShareIntentActivity extends BaseBugleActivity implements } mDraftMessage = sharedText != null ? MessageData.createSharedMessage(sharedText) : null; - } else if (ContentType.isMediaType(contentType)) { + } else if (PendingAttachmentData.isSupportedMediaType(contentType)) { if (contentUri != null) { mDraftMessage = MessageData.createSharedMessage(null); addSharedPartToDraft(contentType, contentUri); @@ -139,7 +139,7 @@ public class ShareIntentActivity extends BaseBugleActivity implements } strBuffer.append(sharedText); } - } else if (ContentType.isMediaType(actualContentType)) { + } else if (PendingAttachmentData.isSupportedMediaType(actualContentType)) { uriMap.put(uri, actualContentType); } else { // Unsupported content type. diff --git a/src/com/android/messaging/ui/mediapicker/DocumentImagePicker.java b/src/com/android/messaging/ui/mediapicker/DocumentImagePicker.java index bb267da..d6de128 100644 --- a/src/com/android/messaging/ui/mediapicker/DocumentImagePicker.java +++ b/src/com/android/messaging/ui/mediapicker/DocumentImagePicker.java @@ -30,8 +30,8 @@ import com.android.messaging.util.ImageUtils; import com.android.messaging.util.SafeAsyncTask; /** - * Wraps around the functionalities to allow the user to pick images from the document - * picker. Instances of this class must be tied to a Fragment which is able to delegate activity + * Wraps around the functionalities to allow the user to pick an image/video/audio from the document + * picker. Instances of this class must be tied to a Fragment which is able to delegate activity * result callbacks. */ public class DocumentImagePicker { @@ -79,8 +79,8 @@ public class DocumentImagePicker { * Must be called from the fragment/activity's onActivityResult(). */ public void onActivityResult(final int requestCode, final int resultCode, final Intent data) { - if (requestCode == UIIntents.REQUEST_PICK_IMAGE_FROM_DOCUMENT_PICKER && - resultCode == Activity.RESULT_OK) { + if (requestCode == UIIntents.REQUEST_PICK_MEDIA_FROM_DOCUMENT_PICKER + && resultCode == Activity.RESULT_OK) { // Sometimes called after media item has been picked from the document picker. String url = data.getStringExtra(EXTRA_PHOTO_URL); if (url == null) { diff --git a/src/com/android/messaging/ui/mediapicker/GalleryGridItemView.java b/src/com/android/messaging/ui/mediapicker/GalleryGridItemView.java index 3d71fe6..48eaa5d 100644 --- a/src/com/android/messaging/ui/mediapicker/GalleryGridItemView.java +++ b/src/com/android/messaging/ui/mediapicker/GalleryGridItemView.java @@ -17,6 +17,7 @@ package com.android.messaging.ui.mediapicker; import android.content.Context; import android.database.Cursor; +import android.graphics.PorterDuff; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; @@ -24,13 +25,17 @@ import android.view.TouchDelegate; import android.view.View; import android.widget.CheckBox; import android.widget.FrameLayout; -import android.widget.ImageView.ScaleType; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; import com.android.messaging.R; import com.android.messaging.datamodel.DataModel; import com.android.messaging.datamodel.data.GalleryGridItemData; import com.android.messaging.ui.AsyncImageView; import com.android.messaging.ui.ConversationDrawables; +import com.android.messaging.util.ContentType; import com.google.common.annotations.VisibleForTesting; import java.util.concurrent.TimeUnit; @@ -53,6 +58,11 @@ public class GalleryGridItemView extends FrameLayout { GalleryGridItemData mData; private AsyncImageView mImageView; private CheckBox mCheckBox; + private RelativeLayout mAdditionalInfo; + private ImageView mIcon; + private LinearLayout mFileInfo; + private TextView mFileName; + private TextView mFileType; private HostInterface mHostInterface; private final OnClickListener mOnClickListener = new OnClickListener() { @Override @@ -69,9 +79,14 @@ public class GalleryGridItemView extends FrameLayout { @Override protected void onFinishInflate() { super.onFinishInflate(); - mImageView = (AsyncImageView) findViewById(R.id.image); + mImageView = (AsyncImageView) findViewById(R.id.thumbnail); mCheckBox = (CheckBox) findViewById(R.id.checkbox); mCheckBox.setOnClickListener(mOnClickListener); + mAdditionalInfo = (RelativeLayout) findViewById(R.id.additional_info); + mIcon = (ImageView) findViewById(R.id.icon); + mFileInfo = (LinearLayout) findViewById(R.id.file_info); + mFileName = (TextView) findViewById(R.id.file_name); + mFileType = (TextView) findViewById(R.id.file_type); setOnClickListener(mOnClickListener); final OnLongClickListener longClickListener = new OnLongClickListener() { @Override @@ -136,24 +151,58 @@ public class GalleryGridItemView extends FrameLayout { private void updateImageView() { if (mData.isDocumentPickerItem()) { - mImageView.setScaleType(ScaleType.CENTER); setBackgroundColor(ConversationDrawables.get().getConversationThemeColor()); - mImageView.setImageResourceId(null); - mImageView.setImageResource(R.drawable.ic_photo_library_light); - mImageView.setContentDescription(getResources().getString( - R.string.pick_image_from_document_library_content_description)); + mIcon.setImageResource(R.drawable.ic_photo_library_light); + mIcon.clearColorFilter(); + mImageView.setVisibility(GONE); + mIcon.setVisibility(VISIBLE); + mFileInfo.setVisibility(GONE); + mAdditionalInfo.setVisibility(VISIBLE); } else { - mImageView.setScaleType(ScaleType.CENTER_CROP); - setBackgroundColor(getResources().getColor(R.color.gallery_image_default_background)); - mImageView.setImageResourceId(mData.getImageRequestDescriptor()); - final long dateSeconds = mData.getDateSeconds(); - final boolean isValidDate = (dateSeconds > 0); - final int templateId = isValidDate ? - R.string.mediapicker_gallery_image_item_description : - R.string.mediapicker_gallery_image_item_description_no_date; - String contentDescription = String.format(getResources().getString(templateId), - dateSeconds * TimeUnit.SECONDS.toMillis(1)); - mImageView.setContentDescription(contentDescription); + final String contentType = mData.getContentType(); + if (ContentType.isAudioType(contentType)) { + final Context context = getContext(); + setBackgroundColor( + getResources().getColor(R.color.gallery_image_default_background)); + mIcon.setImageDrawable( + context.getContentResolver() + .getTypeInfo(contentType) + .getIcon() + .loadDrawable(context)); + mIcon.setColorFilter( + ConversationDrawables.get().getConversationThemeColor(), + PorterDuff.Mode.SRC_IN); + mFileName.setText(mData.getFileName()); + String[] type = contentType.split("/"); + mFileType.setText(type[1].toUpperCase() + " " + type[0]); + mImageView.setVisibility(GONE); + mIcon.setVisibility(VISIBLE); + mFileInfo.setVisibility(VISIBLE); + mAdditionalInfo.setVisibility(VISIBLE); + } else { // For image and video types + mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP); + setBackgroundColor( + getResources().getColor(R.color.gallery_image_default_background)); + mImageView.setImageResourceId(mData.getImageRequestDescriptor()); + mImageView.setVisibility(VISIBLE); + if (ContentType.isVideoType(mData.getContentType())) { + mIcon.setImageResource(R.drawable.ic_video_play_light); + mIcon.clearColorFilter(); + mIcon.setVisibility(VISIBLE); + } else { + mIcon.setVisibility(GONE); + } + mFileInfo.setVisibility(GONE); + mAdditionalInfo.setVisibility(VISIBLE); + final long dateSeconds = mData.getDateSeconds(); + final boolean isValidDate = (dateSeconds > 0); + final int templateId = isValidDate ? + R.string.mediapicker_gallery_image_item_description : + R.string.mediapicker_gallery_image_item_description_no_date; + String contentDescription = String.format(getResources().getString(templateId), + dateSeconds * TimeUnit.SECONDS.toMillis(1)); + mImageView.setContentDescription(contentDescription); + } } } } diff --git a/src/com/android/messaging/ui/mediapicker/GalleryGridView.java b/src/com/android/messaging/ui/mediapicker/GalleryGridView.java index 2265dd5..39912f9 100644 --- a/src/com/android/messaging/ui/mediapicker/GalleryGridView.java +++ b/src/com/android/messaging/ui/mediapicker/GalleryGridView.java @@ -43,16 +43,16 @@ import java.util.Iterator; import java.util.Map; /** - * Shows a list of galley images from external storage in a GridView with multi-select - * capabilities, and with the option to intent out to a standalone image picker. + * Shows a list of galley mediae from external storage in a GridView with multi-select capabilities, + * and with the option to intent out to a standalone media picker. */ public class GalleryGridView extends MediaPickerGridView implements GalleryGridItemView.HostInterface, PersistentInstanceState, DraftMessageDataListener { /** - * Implemented by the owner of this GalleryGridView instance to communicate on image - * picking and multi-image selection events. + * Implemented by the owner of this GalleryGridView instance to communicate on media picking and + * multi-media selection events. */ public interface GalleryGridViewListener { void onDocumentPickerItemClicked(); @@ -127,7 +127,7 @@ public class GalleryGridView extends MediaPickerGridView implements final MessagePartData item = mSelectedImages.remove(data.getImageUri()); mListener.onItemUnselected(item); if (mSelectedImages.size() == 0) { - // No image is selected any more, turn off multi-select mode. + // No media is selected any more, turn off multi-select mode. setMultiSelectEnabled(false); } } else { diff --git a/src/com/android/messaging/ui/mediapicker/GalleryMediaChooser.java b/src/com/android/messaging/ui/mediapicker/GalleryMediaChooser.java index 1b8c2dc..c9b544d 100644 --- a/src/com/android/messaging/ui/mediapicker/GalleryMediaChooser.java +++ b/src/com/android/messaging/ui/mediapicker/GalleryMediaChooser.java @@ -39,7 +39,7 @@ import com.android.messaging.util.Assert; import com.android.messaging.util.OsUtil; /** - * Chooser which allows the user to select one or more existing images or videos + * Chooser which allows the user to select one or more existing images or videos or audios. */ class GalleryMediaChooser extends MediaChooser implements GalleryGridView.GalleryGridViewListener, MediaPickerDataListener { @@ -54,7 +54,9 @@ class GalleryMediaChooser extends MediaChooser implements @Override public int getSupportedMediaTypes() { - return MediaPicker.MEDIA_TYPE_IMAGE | MediaPicker.MEDIA_TYPE_VIDEO; + return (MediaPicker.MEDIA_TYPE_IMAGE + | MediaPicker.MEDIA_TYPE_VIDEO + | MediaPicker.MEDIA_TYPE_AUDIO); } @Override @@ -63,7 +65,7 @@ class GalleryMediaChooser extends MediaChooser implements mAdapter.setHostInterface(null); // The loader is started only if startMediaPickerDataLoader() is called if (OsUtil.hasStoragePermission()) { - mBindingRef.getData().destroyLoader(MediaPickerData.GALLERY_IMAGE_LOADER); + mBindingRef.getData().destroyLoader(MediaPickerData.GALLERY_MEDIA_LOADER); } return super.destroyView(); } @@ -121,7 +123,7 @@ class GalleryMediaChooser extends MediaChooser implements protected View createView(final ViewGroup container) { final LayoutInflater inflater = getLayoutInflater(); final View view = inflater.inflate( - R.layout.mediapicker_image_chooser, + R.layout.mediapicker_gallery_chooser, container /* root */, false /* attachToRoot */); @@ -167,7 +169,7 @@ class GalleryMediaChooser extends MediaChooser implements public void onMediaPickerDataUpdated(final MediaPickerData mediaPickerData, final Object data, final int loaderId) { mBindingRef.ensureBound(mediaPickerData); - Assert.equals(MediaPickerData.GALLERY_IMAGE_LOADER, loaderId); + Assert.equals(MediaPickerData.GALLERY_MEDIA_LOADER, loaderId); Cursor rawCursor = null; if (data instanceof Cursor) { rawCursor = (Cursor) data; @@ -202,8 +204,9 @@ class GalleryMediaChooser extends MediaChooser implements } private void startMediaPickerDataLoader() { - mBindingRef.getData().startLoader(MediaPickerData.GALLERY_IMAGE_LOADER, mBindingRef, null, - this); + mBindingRef + .getData() + .startLoader(MediaPickerData.GALLERY_MEDIA_LOADER, mBindingRef, null, this); } @Override diff --git a/src/com/android/messaging/ui/mediapicker/MediaPicker.java b/src/com/android/messaging/ui/mediapicker/MediaPicker.java index 8e5198b..b8fce8f 100644 --- a/src/com/android/messaging/ui/mediapicker/MediaPicker.java +++ b/src/com/android/messaging/ui/mediapicker/MediaPicker.java @@ -159,7 +159,7 @@ public class MediaPicker extends Fragment implements DraftMessageSubscriptionDat @VisibleForTesting final Binding<MediaPickerData> mBinding = BindingBase.createBinding(this); - /** Handles picking image from the document picker */ + /** Handles picking a media from the document picker. */ private DocumentImagePicker mDocumentImagePicker; /** Provides subscription-related data to access per-subscription configurations. */ diff --git a/src/com/android/messaging/util/UriUtil.java b/src/com/android/messaging/util/UriUtil.java index 0e931c4..ceff50c 100644 --- a/src/com/android/messaging/util/UriUtil.java +++ b/src/com/android/messaging/util/UriUtil.java @@ -26,6 +26,7 @@ import androidx.annotation.NonNull; import android.text.TextUtils; import com.android.messaging.Factory; +import com.android.messaging.datamodel.GalleryBoundCursorLoader; import com.android.messaging.datamodel.MediaScratchFileProvider; import com.android.messaging.util.Assert.DoesNotRunOnMainThread; import com.google.common.io.ByteStreams; @@ -130,6 +131,18 @@ public class UriUtil { } /** + * Gets the content:// style URI for the given MediaStore row Id in the files table on the + * external volume. + * + * @param id the MediaStore row Id to get the URI for + * @return the URI to the files table on the external storage. + */ + public static Uri getContentUriForMediaStoreId(final long id) { + return MediaStore.Files.getContentUri( + GalleryBoundCursorLoader.MEDIA_SCANNER_VOLUME_EXTERNAL, id); + } + + /** * Gets the size in bytes for the content uri. Currently we only support content in the * scratch space. */ diff --git a/src/com/android/messaging/widget/WidgetConversationListService.java b/src/com/android/messaging/widget/WidgetConversationListService.java index 264b98c..b67bd79 100644 --- a/src/com/android/messaging/widget/WidgetConversationListService.java +++ b/src/com/android/messaging/widget/WidgetConversationListService.java @@ -159,10 +159,9 @@ public class WidgetConversationListService extends RemoteViewsService { // Error // Only show the fail icon if it is not a group conversation. // And also require that we be the default sms app. - final boolean showError = conv.getIsFailedStatus() && - isDefaultSmsApp; - final boolean showDraft = conv.getShowDraft() && - isDefaultSmsApp; + final boolean showError = + conv.getIsFailedStatus() && !conv.getIsGroup() && isDefaultSmsApp; + final boolean showDraft = conv.getShowDraft() && isDefaultSmsApp; remoteViews.setViewVisibility(R.id.conversation_failed_status_icon, showError && includeAvatar ? View.VISIBLE : View.GONE); diff --git a/tests/src/com/android/messaging/datamodel/data/TestDataFactory.java b/tests/src/com/android/messaging/datamodel/data/TestDataFactory.java index 8527e2b..033caa2 100644 --- a/tests/src/com/android/messaging/datamodel/data/TestDataFactory.java +++ b/tests/src/com/android/messaging/datamodel/data/TestDataFactory.java @@ -279,7 +279,7 @@ public class TestDataFactory { new Object[] { Long.valueOf(1), "/sdcard/image2", 200, 200, "image/png" }, new Object[] { Long.valueOf(2), "/sdcard/image3", 300, 300, "image/jpeg" }, }; - return new FakeCursor(GalleryGridItemData.IMAGE_PROJECTION, sGalleryCursorColumns, + return new FakeCursor(GalleryGridItemData.MEDIA_PROJECTION, sGalleryCursorColumns, cursorData); } diff --git a/tests/src/com/android/messaging/ui/mediapicker/GalleryGridItemViewTest.java b/tests/src/com/android/messaging/ui/mediapicker/GalleryGridItemViewTest.java index 83d8ac9..304cc74 100644 --- a/tests/src/com/android/messaging/ui/mediapicker/GalleryGridItemViewTest.java +++ b/tests/src/com/android/messaging/ui/mediapicker/GalleryGridItemViewTest.java @@ -55,7 +55,7 @@ public class GalleryGridItemViewTest extends ViewTest<GalleryGridItemView> { final String imageUrl, final boolean showCheckbox, final boolean isSelected) { - final AsyncImageView imageView = (AsyncImageView) view.findViewById(R.id.image); + final AsyncImageView imageView = (AsyncImageView) view.findViewById(R.id.thumbnail); final CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkbox); assertNotNull(imageView); diff --git a/tests/src/com/android/messaging/ui/mediapicker/MediaPickerTest.java b/tests/src/com/android/messaging/ui/mediapicker/MediaPickerTest.java index 4a7040e..eaf9338 100644 --- a/tests/src/com/android/messaging/ui/mediapicker/MediaPickerTest.java +++ b/tests/src/com/android/messaging/ui/mediapicker/MediaPickerTest.java @@ -97,7 +97,7 @@ public class MediaPickerTest extends FragmentTestCase<MediaPicker> { public void testDefaultTabs() { Mockito.when(mMockMediaPickerData.getSelectedChooserIndex()).thenReturn(0); initFragment(MediaPicker.MEDIA_TYPE_ALL, new Integer[] { - MediaPickerData.GALLERY_IMAGE_LOADER }, + MediaPickerData.GALLERY_MEDIA_LOADER }, false); final MediaPicker mediaPicker = getFragment(); final View view = mediaPicker.getView(); @@ -114,7 +114,7 @@ public class MediaPickerTest extends FragmentTestCase<MediaPicker> { public void testFilterTabsBeforeAttach() { Mockito.when(mMockMediaPickerData.getSelectedChooserIndex()).thenReturn(0); initFragment(MediaPicker.MEDIA_TYPE_IMAGE, new Integer[] { - MediaPickerData.GALLERY_IMAGE_LOADER }, + MediaPickerData.GALLERY_MEDIA_LOADER }, true); final MediaPicker mediaPicker = getFragment(); final View view = mediaPicker.getView(); |
