Home | History | Annotate | Download | only in mediapicker
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.messaging.ui.mediapicker;
     18 
     19 import android.Manifest;
     20 import android.content.pm.PackageManager;
     21 import android.database.Cursor;
     22 import android.database.MatrixCursor;
     23 import android.database.MergeCursor;
     24 import android.support.v7.app.ActionBar;
     25 import android.view.LayoutInflater;
     26 import android.view.Menu;
     27 import android.view.MenuInflater;
     28 import android.view.MenuItem;
     29 import android.view.View;
     30 import android.view.ViewGroup;
     31 
     32 import com.android.messaging.Factory;
     33 import com.android.messaging.R;
     34 import com.android.messaging.datamodel.data.GalleryGridItemData;
     35 import com.android.messaging.datamodel.data.MediaPickerData;
     36 import com.android.messaging.datamodel.data.MessagePartData;
     37 import com.android.messaging.datamodel.data.MediaPickerData.MediaPickerDataListener;
     38 import com.android.messaging.util.Assert;
     39 import com.android.messaging.util.OsUtil;
     40 
     41 /**
     42  * Chooser which allows the user to select one or more existing images or videos
     43  */
     44 class GalleryMediaChooser extends MediaChooser implements
     45         GalleryGridView.GalleryGridViewListener, MediaPickerDataListener {
     46     private final GalleryGridAdapter mAdapter;
     47     private GalleryGridView mGalleryGridView;
     48     private View mMissingPermissionView;
     49 
     50     GalleryMediaChooser(final MediaPicker mediaPicker) {
     51         super(mediaPicker);
     52         mAdapter = new GalleryGridAdapter(Factory.get().getApplicationContext(), null);
     53     }
     54 
     55     @Override
     56     public int getSupportedMediaTypes() {
     57         return MediaPicker.MEDIA_TYPE_IMAGE | MediaPicker.MEDIA_TYPE_VIDEO;
     58     }
     59 
     60     @Override
     61     public View destroyView() {
     62         mGalleryGridView.setAdapter(null);
     63         mAdapter.setHostInterface(null);
     64         // The loader is started only if startMediaPickerDataLoader() is called
     65         if (OsUtil.hasStoragePermission()) {
     66             mBindingRef.getData().destroyLoader(MediaPickerData.GALLERY_IMAGE_LOADER);
     67         }
     68         return super.destroyView();
     69     }
     70 
     71     @Override
     72     public int getIconResource() {
     73         return R.drawable.ic_image_light;
     74     }
     75 
     76     @Override
     77     public int getIconDescriptionResource() {
     78         return R.string.mediapicker_galleryChooserDescription;
     79     }
     80 
     81     @Override
     82     public boolean canSwipeDown() {
     83         return mGalleryGridView.canSwipeDown();
     84     }
     85 
     86     @Override
     87     public void onItemSelected(final MessagePartData item) {
     88         mMediaPicker.dispatchItemsSelected(item, !mGalleryGridView.isMultiSelectEnabled());
     89     }
     90 
     91     @Override
     92     public void onItemUnselected(final MessagePartData item) {
     93         mMediaPicker.dispatchItemUnselected(item);
     94     }
     95 
     96     @Override
     97     public void onConfirmSelection() {
     98         // The user may only confirm if multiselect is enabled.
     99         Assert.isTrue(mGalleryGridView.isMultiSelectEnabled());
    100         mMediaPicker.dispatchConfirmItemSelection();
    101     }
    102 
    103     @Override
    104     public void onUpdate() {
    105         mMediaPicker.invalidateOptionsMenu();
    106     }
    107 
    108     @Override
    109     public void onCreateOptionsMenu(final MenuInflater inflater, final Menu menu) {
    110         if (mView != null) {
    111             mGalleryGridView.onCreateOptionsMenu(inflater, menu);
    112         }
    113     }
    114 
    115     @Override
    116     public boolean onOptionsItemSelected(final MenuItem item) {
    117         return (mView != null) ? mGalleryGridView.onOptionsItemSelected(item) : false;
    118     }
    119 
    120     @Override
    121     protected View createView(final ViewGroup container) {
    122         final LayoutInflater inflater = getLayoutInflater();
    123         final View view = inflater.inflate(
    124                 R.layout.mediapicker_image_chooser,
    125                 container /* root */,
    126                 false /* attachToRoot */);
    127 
    128         mGalleryGridView = (GalleryGridView) view.findViewById(R.id.gallery_grid_view);
    129         mAdapter.setHostInterface(mGalleryGridView);
    130         mGalleryGridView.setAdapter(mAdapter);
    131         mGalleryGridView.setHostInterface(this);
    132         mGalleryGridView.setDraftMessageDataModel(mMediaPicker.getDraftMessageDataModel());
    133         if (OsUtil.hasStoragePermission()) {
    134             startMediaPickerDataLoader();
    135         }
    136 
    137         mMissingPermissionView = view.findViewById(R.id.missing_permission_view);
    138         updateForPermissionState(OsUtil.hasStoragePermission());
    139         return view;
    140     }
    141 
    142     @Override
    143     int getActionBarTitleResId() {
    144         return R.string.mediapicker_gallery_title;
    145     }
    146 
    147     @Override
    148     public void onDocumentPickerItemClicked() {
    149         mMediaPicker.launchDocumentPicker();
    150     }
    151 
    152     @Override
    153     void updateActionBar(final ActionBar actionBar) {
    154         super.updateActionBar(actionBar);
    155         if (mGalleryGridView == null) {
    156             return;
    157         }
    158         final int selectionCount = mGalleryGridView.getSelectionCount();
    159         if (selectionCount > 0 && mGalleryGridView.isMultiSelectEnabled()) {
    160             actionBar.setTitle(getContext().getResources().getString(
    161                     R.string.mediapicker_gallery_title_selection,
    162                     selectionCount));
    163         }
    164     }
    165 
    166     @Override
    167     public void onMediaPickerDataUpdated(final MediaPickerData mediaPickerData, final Object data,
    168             final int loaderId) {
    169         mBindingRef.ensureBound(mediaPickerData);
    170         Assert.equals(MediaPickerData.GALLERY_IMAGE_LOADER, loaderId);
    171         Cursor rawCursor = null;
    172         if (data instanceof Cursor) {
    173             rawCursor = (Cursor) data;
    174         }
    175         // Before delivering the cursor, wrap around the local gallery cursor
    176         // with an extra item for document picker integration in the front.
    177         final MatrixCursor specialItemsCursor =
    178                 new MatrixCursor(GalleryGridItemData.SPECIAL_ITEM_COLUMNS);
    179         specialItemsCursor.addRow(new Object[] { GalleryGridItemData.ID_DOCUMENT_PICKER_ITEM });
    180         final MergeCursor cursor =
    181                 new MergeCursor(new Cursor[] { specialItemsCursor, rawCursor });
    182         mAdapter.swapCursor(cursor);
    183     }
    184 
    185     @Override
    186     public void onResume() {
    187         if (OsUtil.hasStoragePermission()) {
    188             // Work around a bug in MediaStore where cursors querying the Files provider don't get
    189             // updated for changes to Images.Media or Video.Media.
    190             startMediaPickerDataLoader();
    191         }
    192     }
    193 
    194     @Override
    195     protected void setSelected(final boolean selected) {
    196         super.setSelected(selected);
    197         if (selected && !OsUtil.hasStoragePermission()) {
    198             mMediaPicker.requestPermissions(
    199                     new String[] { Manifest.permission.READ_EXTERNAL_STORAGE },
    200                     MediaPicker.GALLERY_PERMISSION_REQUEST_CODE);
    201         }
    202     }
    203 
    204     private void startMediaPickerDataLoader() {
    205         mBindingRef.getData().startLoader(MediaPickerData.GALLERY_IMAGE_LOADER, mBindingRef, null,
    206                 this);
    207     }
    208 
    209     @Override
    210     protected void onRequestPermissionsResult(
    211             final int requestCode, final String permissions[], final int[] grantResults) {
    212         if (requestCode == MediaPicker.GALLERY_PERMISSION_REQUEST_CODE) {
    213             final boolean permissionGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
    214             if (permissionGranted) {
    215                 startMediaPickerDataLoader();
    216             }
    217             updateForPermissionState(permissionGranted);
    218         }
    219     }
    220 
    221     private void updateForPermissionState(final boolean granted) {
    222         // onRequestPermissionsResult can sometimes get called before createView().
    223         if (mGalleryGridView == null) {
    224             return;
    225         }
    226 
    227         mGalleryGridView.setVisibility(granted ? View.VISIBLE : View.GONE);
    228         mMissingPermissionView.setVisibility(granted ? View.GONE : View.VISIBLE);
    229     }
    230 }
    231