Home | History | Annotate | Download | only in conversationlist
      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.conversationlist;
     18 
     19 import android.app.Fragment;
     20 import android.content.ContentResolver;
     21 import android.content.Intent;
     22 import android.media.MediaMetadataRetriever;
     23 import android.net.Uri;
     24 import android.os.Bundle;
     25 import android.text.TextUtils;
     26 
     27 import com.android.messaging.Factory;
     28 import com.android.messaging.datamodel.data.ConversationListItemData;
     29 import com.android.messaging.datamodel.data.MessageData;
     30 import com.android.messaging.datamodel.data.PendingAttachmentData;
     31 import com.android.messaging.ui.BaseBugleActivity;
     32 import com.android.messaging.ui.UIIntents;
     33 import com.android.messaging.util.Assert;
     34 import com.android.messaging.util.ContentType;
     35 import com.android.messaging.util.LogUtil;
     36 import com.android.messaging.util.MediaMetadataRetrieverWrapper;
     37 import com.android.messaging.util.FileUtil;
     38 
     39 import java.io.IOException;
     40 import java.util.ArrayList;
     41 
     42 public class ShareIntentActivity extends BaseBugleActivity implements
     43         ShareIntentFragment.HostInterface {
     44 
     45     private MessageData mDraftMessage;
     46 
     47     @Override
     48     protected void onCreate(final Bundle savedInstanceState) {
     49         super.onCreate(savedInstanceState);
     50 
     51         final Intent intent = getIntent();
     52         if (Intent.ACTION_SEND.equals(intent.getAction()) &&
     53                 (!TextUtils.isEmpty(intent.getStringExtra("address")) ||
     54                 !TextUtils.isEmpty(intent.getStringExtra(Intent.EXTRA_EMAIL)))) {
     55             // This is really more like a SENDTO intent because a destination is supplied.
     56             // It's coming through the SEND intent because that's the intent that is used
     57             // when invoking the chooser with Intent.createChooser().
     58             final Intent convIntent = UIIntents.get().getLaunchConversationActivityIntent(this);
     59             // Copy the important items from the original intent to the new intent.
     60             convIntent.putExtras(intent);
     61             convIntent.setAction(Intent.ACTION_SENDTO);
     62             convIntent.setDataAndType(intent.getData(), intent.getType());
     63             // We have to fire off the intent and finish before trying to show the fragment,
     64             // otherwise we get some flashing.
     65             startActivity(convIntent);
     66             finish();
     67             return;
     68         }
     69         new ShareIntentFragment().show(getFragmentManager(), "ShareIntentFragment");
     70     }
     71 
     72     @Override
     73     public void onAttachFragment(final Fragment fragment) {
     74         final Intent intent = getIntent();
     75         final String action = intent.getAction();
     76         if (Intent.ACTION_SEND.equals(action)) {
     77             final Uri contentUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
     78             final String contentType = extractContentType(contentUri, intent.getType());
     79             if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.DEBUG)) {
     80                 LogUtil.d(LogUtil.BUGLE_TAG, String.format(
     81                         "onAttachFragment: contentUri=%s, intent.getType()=%s, inferredType=%s",
     82                         contentUri, intent.getType(), contentType));
     83             }
     84             if (ContentType.TEXT_PLAIN.equals(contentType)) {
     85                 final String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
     86                 if (sharedText != null) {
     87                     mDraftMessage = MessageData.createSharedMessage(sharedText);
     88                 } else {
     89                     mDraftMessage = null;
     90                 }
     91             } else if (ContentType.isImageType(contentType) ||
     92                     ContentType.isVCardType(contentType) ||
     93                     ContentType.isAudioType(contentType) ||
     94                     ContentType.isVideoType(contentType)) {
     95                 if (contentUri != null) {
     96                     mDraftMessage = MessageData.createSharedMessage(null);
     97                     addSharedImagePartToDraft(contentType, contentUri);
     98                 } else {
     99                     mDraftMessage = null;
    100                 }
    101             } else {
    102                 // Unsupported content type.
    103                 Assert.fail("Unsupported shared content type for " + contentUri + ": " + contentType
    104                         + " (" + intent.getType() + ")");
    105             }
    106         } else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
    107             final String contentType = intent.getType();
    108             if (ContentType.isImageType(contentType)) {
    109                 // Handle sharing multiple images.
    110                 final ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(
    111                         Intent.EXTRA_STREAM);
    112                 if (imageUris != null && imageUris.size() > 0) {
    113                     mDraftMessage = MessageData.createSharedMessage(null);
    114                     for (final Uri imageUri : imageUris) {
    115                         final String actualContentType = extractContentType(imageUri, contentType);
    116                         addSharedImagePartToDraft(actualContentType, imageUri);
    117                     }
    118                 } else {
    119                     mDraftMessage = null;
    120                 }
    121             } else {
    122                 // Unsupported content type.
    123                 Assert.fail("Unsupported shared content type: " + contentType);
    124             }
    125         } else {
    126             // Unsupported action.
    127             Assert.fail("Unsupported action type for sharing: " + action);
    128         }
    129     }
    130 
    131     private static String extractContentType(final Uri uri, final String contentType) {
    132         if (uri == null) {
    133             return contentType;
    134         }
    135         // First try looking at file extension.  This is less reliable in some ways but it's
    136         // recommended by
    137         // https://developer.android.com/training/secure-file-sharing/retrieve-info.html
    138         // Some implementations of MediaMetadataRetriever get things horribly
    139         // wrong for common formats such as jpeg (reports as video/ffmpeg)
    140         final ContentResolver resolver = Factory.get().getApplicationContext().getContentResolver();
    141         final String typeFromExtension = resolver.getType(uri);
    142         if (typeFromExtension != null) {
    143             return typeFromExtension;
    144         }
    145         final MediaMetadataRetrieverWrapper retriever = new MediaMetadataRetrieverWrapper();
    146         try {
    147             retriever.setDataSource(uri);
    148             final String extractedType = retriever.extractMetadata(
    149                     MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
    150             if (extractedType != null) {
    151                 return extractedType;
    152             }
    153         } catch (final IOException e) {
    154             LogUtil.i(LogUtil.BUGLE_TAG, "Could not determine type of " + uri, e);
    155         } finally {
    156             retriever.release();
    157         }
    158         return contentType;
    159     }
    160 
    161     private void addSharedImagePartToDraft(final String contentType, final Uri imageUri) {
    162         if (FileUtil.isInPrivateDir(imageUri)) {
    163             Assert.fail("Cannot send private file " + imageUri.toString());
    164         } else {
    165             mDraftMessage.addPart(PendingAttachmentData.createPendingAttachmentData(contentType,
    166                     imageUri));
    167         }
    168     }
    169 
    170     @Override
    171     public void onConversationClick(final ConversationListItemData conversationListItemData) {
    172         UIIntents.get().launchConversationActivity(
    173                 this, conversationListItemData.getConversationId(), mDraftMessage);
    174         finish();
    175     }
    176 
    177     @Override
    178     public void onCreateConversationClick() {
    179         UIIntents.get().launchCreateNewConversationActivity(this, mDraftMessage);
    180         finish();
    181     }
    182 }
    183