Files
packages_apps_Messaging/src/com/android/messaging/ui/mediapicker/GalleryMediaChooser.java
Taesu Lee 6c77158718 Support video attachments through GalleryMediaChooser
GalleryMediaChooser supports video types and more image types also. And
video thumbnails are overlaid with the play button image to distinguish
between images and videos.

Note:
 1. EXTRA_ALLOW_MULTIPLE is not specified for ACTION_GET_CONTENT.
 2. Files, methods and variables' name are still including "image".
 3. Content descriptions are not updated.

Test: Manual

Change-Id: I961928f150e4ae8ee80a1fba2f20c37fb5426669
Signed-off-by: Taesu Lee <taesu82.lee@samsung.com>
2020-02-19 18:36:32 +09:00

232 lines
8.1 KiB
Java

/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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 com.android.messaging.ui.mediapicker;
import android.Manifest;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MergeCursor;
import androidx.appcompat.app.ActionBar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.android.messaging.Factory;
import com.android.messaging.R;
import com.android.messaging.datamodel.data.GalleryGridItemData;
import com.android.messaging.datamodel.data.MediaPickerData;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.datamodel.data.MediaPickerData.MediaPickerDataListener;
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
*/
class GalleryMediaChooser extends MediaChooser implements
GalleryGridView.GalleryGridViewListener, MediaPickerDataListener {
private final GalleryGridAdapter mAdapter;
private GalleryGridView mGalleryGridView;
private View mMissingPermissionView;
GalleryMediaChooser(final MediaPicker mediaPicker) {
super(mediaPicker);
mAdapter = new GalleryGridAdapter(Factory.get().getApplicationContext(), null);
}
@Override
public int getSupportedMediaTypes() {
return MediaPicker.MEDIA_TYPE_IMAGE | MediaPicker.MEDIA_TYPE_VIDEO;
}
@Override
public View destroyView() {
mGalleryGridView.setAdapter(null);
mAdapter.setHostInterface(null);
// The loader is started only if startMediaPickerDataLoader() is called
if (OsUtil.hasStoragePermission()) {
mBindingRef.getData().destroyLoader(MediaPickerData.GALLERY_MEDIA_LOADER);
}
return super.destroyView();
}
@Override
public int getIconResource() {
return R.drawable.ic_image_light;
}
@Override
public int getIconDescriptionResource() {
return R.string.mediapicker_galleryChooserDescription;
}
@Override
public boolean canSwipeDown() {
return mGalleryGridView.canSwipeDown();
}
@Override
public void onItemSelected(final MessagePartData item) {
mMediaPicker.dispatchItemsSelected(item, !mGalleryGridView.isMultiSelectEnabled());
}
@Override
public void onItemUnselected(final MessagePartData item) {
mMediaPicker.dispatchItemUnselected(item);
}
@Override
public void onConfirmSelection() {
// The user may only confirm if multiselect is enabled.
Assert.isTrue(mGalleryGridView.isMultiSelectEnabled());
mMediaPicker.dispatchConfirmItemSelection();
}
@Override
public void onUpdate() {
mMediaPicker.invalidateOptionsMenu();
}
@Override
public void onCreateOptionsMenu(final MenuInflater inflater, final Menu menu) {
if (mView != null) {
mGalleryGridView.onCreateOptionsMenu(inflater, menu);
}
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
return (mView != null) ? mGalleryGridView.onOptionsItemSelected(item) : false;
}
@Override
protected View createView(final ViewGroup container) {
final LayoutInflater inflater = getLayoutInflater();
final View view = inflater.inflate(
R.layout.mediapicker_gallery_chooser,
container /* root */,
false /* attachToRoot */);
mGalleryGridView = (GalleryGridView) view.findViewById(R.id.gallery_grid_view);
mAdapter.setHostInterface(mGalleryGridView);
mGalleryGridView.setAdapter(mAdapter);
mGalleryGridView.setHostInterface(this);
mGalleryGridView.setDraftMessageDataModel(mMediaPicker.getDraftMessageDataModel());
if (OsUtil.hasStoragePermission()) {
startMediaPickerDataLoader();
}
mMissingPermissionView = view.findViewById(R.id.missing_permission_view);
updateForPermissionState(OsUtil.hasStoragePermission());
return view;
}
@Override
int getActionBarTitleResId() {
return R.string.mediapicker_gallery_title;
}
@Override
public void onDocumentPickerItemClicked() {
mMediaPicker.launchDocumentPicker();
}
@Override
void updateActionBar(final ActionBar actionBar) {
super.updateActionBar(actionBar);
if (mGalleryGridView == null) {
return;
}
final int selectionCount = mGalleryGridView.getSelectionCount();
if (selectionCount > 0 && mGalleryGridView.isMultiSelectEnabled()) {
actionBar.setTitle(getContext().getResources().getString(
R.string.mediapicker_gallery_title_selection,
selectionCount));
}
}
@Override
public void onMediaPickerDataUpdated(final MediaPickerData mediaPickerData, final Object data,
final int loaderId) {
mBindingRef.ensureBound(mediaPickerData);
Assert.equals(MediaPickerData.GALLERY_MEDIA_LOADER, loaderId);
Cursor rawCursor = null;
if (data instanceof Cursor) {
rawCursor = (Cursor) data;
}
// Before delivering the cursor, wrap around the local gallery cursor
// with an extra item for document picker integration in the front.
final MatrixCursor specialItemsCursor =
new MatrixCursor(GalleryGridItemData.SPECIAL_ITEM_COLUMNS);
specialItemsCursor.addRow(new Object[] { GalleryGridItemData.ID_DOCUMENT_PICKER_ITEM });
final MergeCursor cursor =
new MergeCursor(new Cursor[] { specialItemsCursor, rawCursor });
mAdapter.swapCursor(cursor);
}
@Override
public void onResume() {
if (OsUtil.hasStoragePermission()) {
// Work around a bug in MediaStore where cursors querying the Files provider don't get
// updated for changes to Images.Media or Video.Media.
startMediaPickerDataLoader();
}
}
@Override
protected void setSelected(final boolean selected) {
super.setSelected(selected);
if (selected && !OsUtil.hasStoragePermission()) {
mMediaPicker.requestPermissions(
new String[] { Manifest.permission.READ_EXTERNAL_STORAGE },
MediaPicker.GALLERY_PERMISSION_REQUEST_CODE);
}
}
private void startMediaPickerDataLoader() {
mBindingRef
.getData()
.startLoader(MediaPickerData.GALLERY_MEDIA_LOADER, mBindingRef, null, this);
}
@Override
protected void onRequestPermissionsResult(
final int requestCode, final String permissions[], final int[] grantResults) {
if (requestCode == MediaPicker.GALLERY_PERMISSION_REQUEST_CODE) {
final boolean permissionGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (permissionGranted) {
startMediaPickerDataLoader();
}
updateForPermissionState(permissionGranted);
}
}
private void updateForPermissionState(final boolean granted) {
// onRequestPermissionsResult can sometimes get called before createView().
if (mGalleryGridView == null) {
return;
}
mGalleryGridView.setVisibility(granted ? View.VISIBLE : View.GONE);
mMissingPermissionView.setVisibility(granted ? View.GONE : View.VISIBLE);
}
}