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 package com.android.messaging.ui.mediapicker;
17 
18 import android.app.Activity;
19 import android.app.Fragment;
20 import android.content.Intent;
21 import android.net.Uri;
22 import android.os.Bundle;
23 
24 import com.android.messaging.Factory;
25 import com.android.messaging.datamodel.data.PendingAttachmentData;
26 import com.android.messaging.ui.UIIntents;
27 import com.android.messaging.util.ImageUtils;
28 import com.android.messaging.util.SafeAsyncTask;
29 
30 /**
31  * Wraps around the functionalities to allow the user to pick images from the document
32  * picker.  Instances of this class must be tied to a Fragment which is able to delegate activity
33  * result callbacks.
34  */
35 public class DocumentImagePicker {
36 
37     /**
38      * An interface for a listener that listens for when a document has been picked.
39      */
40     public interface SelectionListener {
41         /**
42          * Called when an document is selected from picker. At this point, the file hasn't been
43          * actually loaded and staged in the temp directory, so we are passing in a pending
44          * MessagePartData, which the consumer should use to display a placeholder image.
45          * @param pendingItem a temporary attachment data for showing the placeholder state.
46          */
onDocumentSelected(PendingAttachmentData pendingItem)47         void onDocumentSelected(PendingAttachmentData pendingItem);
48     }
49 
50     // The owning fragment.
51     private final Fragment mFragment;
52 
53     // The listener on the picker events.
54     private final SelectionListener mListener;
55 
56     private static final String EXTRA_PHOTO_URL = "photo_url";
57 
58     /**
59      * Creates a new instance of DocumentImagePicker.
60      * @param activity The activity that owns the picker, or the activity that hosts the owning
61      *        fragment.
62      */
DocumentImagePicker(final Fragment fragment, final SelectionListener listener)63     public DocumentImagePicker(final Fragment fragment,
64             final SelectionListener listener) {
65         mFragment = fragment;
66         mListener = listener;
67     }
68 
69     /**
70      * Intent out to open an image/video from document picker.
71      */
launchPicker()72     public void launchPicker() {
73         UIIntents.get().launchDocumentImagePicker(mFragment);
74     }
75 
76     /**
77      * Must be called from the fragment/activity's onActivityResult().
78      */
onActivityResult(final int requestCode, final int resultCode, final Intent data)79     public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
80         if (requestCode == UIIntents.REQUEST_PICK_IMAGE_FROM_DOCUMENT_PICKER &&
81                 resultCode == Activity.RESULT_OK) {
82             // Sometimes called after media item has been picked from the document picker.
83             String url = data.getStringExtra(EXTRA_PHOTO_URL);
84             if (url == null) {
85                 // we're using the builtin photo picker which supplies the return
86                 // url as it's "data"
87                 url = data.getDataString();
88                 if (url == null) {
89                     final Bundle extras = data.getExtras();
90                     if (extras != null) {
91                         final Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);
92                         if (uri != null) {
93                             url = uri.toString();
94                         }
95                     }
96                 }
97             }
98 
99             // Guard against null uri cases for when the activity returns a null/invalid intent.
100             if (url != null) {
101                 final Uri uri = Uri.parse(url);
102                 prepareDocumentForAttachment(uri);
103             }
104         }
105     }
106 
prepareDocumentForAttachment(final Uri documentUri)107     private void prepareDocumentForAttachment(final Uri documentUri) {
108         // Notify our listener with a PendingAttachmentData containing the metadata.
109         // Asynchronously get the content type for the picked image since
110         // ImageUtils.getContentType() potentially involves I/O and can be expensive.
111         new SafeAsyncTask<Void, Void, String>() {
112             @Override
113             protected String doInBackgroundTimed(final Void... params) {
114                 return ImageUtils.getContentType(
115                         Factory.get().getApplicationContext().getContentResolver(), documentUri);
116             }
117 
118             @Override
119             protected void onPostExecute(final String contentType) {
120                 // Ask the listener to create a temporary placeholder item to show the progress.
121                 final PendingAttachmentData pendingItem =
122                         PendingAttachmentData.createPendingAttachmentData(contentType,
123                                 documentUri);
124                 mListener.onDocumentSelected(pendingItem);
125             }
126         }.executeOnThreadPool();
127     }
128 }
129