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.conversation;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.Intent;
22import android.net.Uri;
23import android.os.Bundle;
24import android.text.TextUtils;
25
26import com.android.messaging.Factory;
27import com.android.messaging.R;
28import com.android.messaging.datamodel.DataModel;
29import com.android.messaging.datamodel.binding.Binding;
30import com.android.messaging.datamodel.binding.BindingBase;
31import com.android.messaging.datamodel.data.LaunchConversationData;
32import com.android.messaging.ui.UIIntents;
33import com.android.messaging.util.ContentType;
34import com.android.messaging.util.LogUtil;
35import com.android.messaging.util.UiUtils;
36import com.android.messaging.util.UriUtil;
37
38import java.io.UnsupportedEncodingException;
39import java.net.URLDecoder;
40
41/**
42 * Launches ConversationActivity for sending a message to, or viewing messages from, a specific
43 * recipient.
44 * <p>
45 * (This activity should be marked noHistory="true" in AndroidManifest.xml)
46 */
47public class LaunchConversationActivity extends Activity implements
48        LaunchConversationData.LaunchConversationDataListener {
49    static final String SMS_BODY = "sms_body";
50    static final String ADDRESS = "address";
51    final Binding<LaunchConversationData> mBinding = BindingBase.createBinding(this);
52    String mSmsBody;
53
54    @Override
55    protected void onCreate(final Bundle savedInstanceState) {
56        super.onCreate(savedInstanceState);
57        if (UiUtils.redirectToPermissionCheckIfNeeded(this)) {
58            return;
59        }
60
61        final Intent intent = getIntent();
62        final String action = intent.getAction();
63        if (Intent.ACTION_SENDTO.equals(action) || Intent.ACTION_VIEW.equals(action)) {
64            String[] recipients = UriUtil.parseRecipientsFromSmsMmsUri(intent.getData());
65            final boolean haveAddress = !TextUtils.isEmpty(intent.getStringExtra(ADDRESS));
66            final boolean haveEmail = !TextUtils.isEmpty(intent.getStringExtra(Intent.EXTRA_EMAIL));
67            if (recipients == null && (haveAddress || haveEmail)) {
68                if (haveAddress) {
69                    recipients = new String[] { intent.getStringExtra(ADDRESS) };
70                } else {
71                    recipients = new String[] { intent.getStringExtra(Intent.EXTRA_EMAIL) };
72                }
73            }
74            mSmsBody = intent.getStringExtra(SMS_BODY);
75            if (TextUtils.isEmpty(mSmsBody)) {
76                // Used by intents sent from the web YouTube (and perhaps others).
77                mSmsBody = getBody(intent.getData());
78                if (TextUtils.isEmpty(mSmsBody)) {
79                    // If that fails, try yet another method apps use to share text
80                    if (ContentType.TEXT_PLAIN.equals(intent.getType())) {
81                        mSmsBody = intent.getStringExtra(Intent.EXTRA_TEXT);
82                    }
83                }
84            }
85            if (recipients != null) {
86                mBinding.bind(DataModel.get().createLaunchConversationData(this));
87                mBinding.getData().getOrCreateConversation(mBinding, recipients);
88            } else {
89                // No recipients were specified in the intent.
90                // Start a new conversation with contact picker. The new conversation will be
91                // primed with the (optional) message in mSmsBody.
92                onGetOrCreateNewConversation(null);
93            }
94        } else {
95            LogUtil.w(LogUtil.BUGLE_TAG, "Unsupported conversation intent action : " + action);
96        }
97        // As of M, activities without a visible window must finish before onResume completes.
98        finish();
99    }
100
101    private String getBody(final Uri uri) {
102        if (uri == null) {
103            return null;
104        }
105        String urlStr = uri.getSchemeSpecificPart();
106        if (!urlStr.contains("?")) {
107            return null;
108        }
109        urlStr = urlStr.substring(urlStr.indexOf('?') + 1);
110        final String[] params = urlStr.split("&");
111        for (final String p : params) {
112            if (p.startsWith("body=")) {
113                try {
114                    return URLDecoder.decode(p.substring(5), "UTF-8");
115                } catch (final UnsupportedEncodingException e) {
116                    // Invalid URL, ignore
117                }
118            }
119        }
120        return null;
121    }
122
123    @Override
124    public void onGetOrCreateNewConversation(final String conversationId) {
125        final Context context = Factory.get().getApplicationContext();
126        UIIntents.get().launchConversationActivityWithParentStack(context, conversationId,
127                mSmsBody);
128    }
129
130    @Override
131    public void onGetOrCreateNewConversationFailed() {
132        UiUtils.showToastAtBottom(R.string.conversation_creation_failure);
133    }
134}
135