GalleryMediaChooser.java revision 461a34b466cb4b13dbbc2ec6330b31e217b2ac4e
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
17package com.android.messaging.ui.mediapicker;
18
19import android.Manifest;
20import android.content.pm.PackageManager;
21import android.database.Cursor;
22import android.database.MatrixCursor;
23import android.database.MergeCursor;
24import android.support.v7.app.ActionBar;
25import android.view.LayoutInflater;
26import android.view.Menu;
27import android.view.MenuInflater;
28import android.view.MenuItem;
29import android.view.View;
30import android.view.ViewGroup;
31
32import com.android.messaging.Factory;
33import com.android.messaging.R;
34import com.android.messaging.datamodel.data.GalleryGridItemData;
35import com.android.messaging.datamodel.data.MediaPickerData;
36import com.android.messaging.datamodel.data.MessagePartData;
37import com.android.messaging.datamodel.data.MediaPickerData.MediaPickerDataListener;
38import com.android.messaging.util.Assert;
39import com.android.messaging.util.OsUtil;
40
41/**
42 * Chooser which allows the user to select one or more existing images or videos
43 */
44class 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