/**
* Wire
* Copyright (C) 2016 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.waz.zclient.utils;
import android.app.PendingIntent;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.waz.api.EphemeralExpiration;
import com.waz.utils.wrappers.AndroidURI;
import com.waz.utils.wrappers.AndroidURIUtil;
import com.waz.utils.wrappers.URI;
import com.waz.zclient.LaunchActivity;
import com.waz.zclient.MainActivity;
import com.waz.zclient.PopupActivity;
import com.waz.zclient.R;
import com.waz.zclient.controllers.notifications.ShareSavedImageActivity;
import hugo.weaving.DebugLog;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
public class IntentUtils {
public static final String WIRE_SCHEME = "wire";
public static final String EMAIL_VERIFIED_HOST_TOKEN = "email-verified";
public static final String PASSWORD_RESET_SUCCESSFUL_HOST_TOKEN = "password-reset-successful";
public static final String SMS_CODE_TOKEN = "verify-phone";
public static final String INVITE_HOST_TOKEN = "connect";
public static final String APP_PAGE_HOST_TOKEN = "app-page";
public static final String EXTRA_LAUNCH_FROM_SAVE_IMAGE_NOTIFICATION = "EXTRA_LAUNCH_FROM_SAVE_IMAGE_NOTIFICATION";
private static final String EXTRA_LAUNCH_CONVERSATION_IDS = "EXTRA_LAUNCH_CONVERSATION_IDS";
private static final String EXTRA_LAUNCH_FROM_NOTIFICATION = "EXTRA_LAUNCH_FROM_NOTIFICATION";
private static final String EXTRA_LAUNCH_FROM_SHARING = "EXTRA_LAUNCH_FROM_SHARING";
private static final String EXTRA_LAUNCH_CONVERSATION_MESSAGE = "EXTRA_LAUNCH_CONVERSATION_MESSAGE";
private static final String EXTRA_LAUNCH_CONVERSATION_FILES = "EXTRA_LAUNCH_CONVERSATION_FILES";
private static final String EXTRA_LAUNCH_START_CALL = "EXTRA_LAUNCH_START_CALL";
private static final String EXTRA_LAUNCH_EPHEMERAL_EXPIRATION = "EXTRA_LAUNCH_EPHEMERAL_EXPIRATION";
public static final String LOCALYTICS_DEEPLINK_SETTINGS = "settings";
public static final String LOCALYTICS_DEEPLINK_SEARCH = "search";
public static final String LOCALYTICS_DEEPLINK_PROFILE = "profile";
private static final String GOOGLE_MAPS_INTENT_URI = "geo:0,0?q=%s,%s";
private static final String GOOGLE_MAPS_WITH_LABEL_INTENT_URI = "geo:0,0?q=%s,%s(%s)";
private static final String GOOGLE_MAPS_INTENT_PACKAGE = "com.google.android.apps.maps";
private static final String GOOGLE_MAPS_WEB_LINK = "http://maps.google.com/maps?z=%d&q=loc:%f+%f+(%s)";
private static final String IMAGE_MIME_TYPE = "image/*";
public static boolean isEmailVerificationIntent(@Nullable Intent intent) {
if (intent == null) {
return false;
}
Uri data = intent.getData();
return data != null &&
WIRE_SCHEME.equals(data.getScheme()) &&
EMAIL_VERIFIED_HOST_TOKEN.equals(data.getHost());
}
public static boolean isPasswordResetIntent(@Nullable Intent intent) {
if (intent == null) {
return false;
}
Uri data = intent.getData();
return data != null &&
WIRE_SCHEME.equals(data.getScheme()) &&
PASSWORD_RESET_SUCCESSFUL_HOST_TOKEN.equals(data.getHost());
}
public static boolean isInviteIntent(@Nullable Intent intent) {
String token = getInviteToken(intent);
return !TextUtils.isEmpty(token);
}
public static boolean isSmsIntent(@Nullable Intent intent) {
if (intent == null) {
return false;
}
Uri data = intent.getData();
return data != null &&
WIRE_SCHEME.equals(data.getScheme()) &&
SMS_CODE_TOKEN.equals(data.getHost());
}
@DebugLog
public static String getSmsCode(@Nullable Intent intent) {
if (intent == null) {
return null;
}
Uri data = intent.getData();
if (isSmsIntent(intent) &&
data.getPath() != null &&
data.getPath().length() > 1
) {
return data.getPath().substring(1);
}
return null;
}
@DebugLog
public static String getInviteToken(@Nullable Intent intent) {
if (intent == null) {
return null;
}
Uri data = intent.getData();
if (data != null &&
WIRE_SCHEME.equals(data.getScheme()) &&
INVITE_HOST_TOKEN.equals(data.getHost())) {
return data.getQueryParameter("code");
}
return null;
}
public static String getAppPage(@Nullable Intent intent) {
if (intent == null ||
TextUtils.isEmpty(intent.getStringExtra("deeplink"))) {
return null;
}
Uri data = Uri.parse(intent.getStringExtra("deeplink"));
if (data != null &&
WIRE_SCHEME.equals(data.getScheme()) &&
APP_PAGE_HOST_TOKEN.equals(data.getHost())) {
return data.getQueryParameter("page");
}
return null;
}
public static Intent resetAppPage(@Nullable Intent intent) {
if (intent == null) {
return null;
}
intent.putExtra(LaunchActivity.APP_PAGE, "");
return intent;
}
public static boolean isLaunchFromNotificationIntent(@Nullable Intent intent) {
return intent != null &&
intent.getBooleanExtra(EXTRA_LAUNCH_FROM_NOTIFICATION, false);
}
public static boolean isLaunchFromSharingIntent(@Nullable Intent intent) {
return intent != null &&
intent.getBooleanExtra(EXTRA_LAUNCH_FROM_SHARING, false);
}
public static void clearLaunchIntentExtra(@Nullable Intent intent) {
if (intent == null) {
return;
}
intent.removeExtra(EXTRA_LAUNCH_FROM_SHARING);
intent.removeExtra(EXTRA_LAUNCH_FROM_NOTIFICATION);
intent.removeExtra(EXTRA_LAUNCH_START_CALL);
intent.removeExtra(EXTRA_LAUNCH_CONVERSATION_IDS);
intent.removeExtra(EXTRA_LAUNCH_CONVERSATION_MESSAGE);
}
public static Intent getAppLaunchIntent(@NonNull Context context,
String conversationId,
@Nullable String sharedText) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(EXTRA_LAUNCH_FROM_SHARING, true);
intent.putExtra(EXTRA_LAUNCH_CONVERSATION_MESSAGE, sharedText != null ? sharedText : "");
intent.putStringArrayListExtra(EXTRA_LAUNCH_CONVERSATION_IDS, new ArrayList<>(Collections.singletonList(conversationId)));
return intent;
}
public static Intent getAppLaunchIntent(@NonNull Context context,
List<String> conversationIds,
@Nullable String sharedText,
EphemeralExpiration expiration) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(EXTRA_LAUNCH_FROM_SHARING, true);
intent.putExtra(EXTRA_LAUNCH_CONVERSATION_MESSAGE, sharedText != null ? sharedText : "");
intent.putStringArrayListExtra(EXTRA_LAUNCH_CONVERSATION_IDS, new ArrayList<>(conversationIds));
intent.putExtra(EXTRA_LAUNCH_EPHEMERAL_EXPIRATION, expiration.milliseconds);
return intent;
}
private static ArrayList<Uri> mapToAndroidUris(List<URI> uris) { //NOPMD
ArrayList<Uri> androidUris = new ArrayList<>(uris.size());
for (URI uri: uris) {
androidUris.add(AndroidURIUtil.unwrap(uri));
}
return androidUris;
}
public static Intent getAppLaunchIntent(@NonNull Context context,
String conversationId,
List<URI> sharedFiles,
EphemeralExpiration expiration) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(EXTRA_LAUNCH_FROM_SHARING, true);
intent.putParcelableArrayListExtra(EXTRA_LAUNCH_CONVERSATION_FILES, mapToAndroidUris(sharedFiles));
intent.putStringArrayListExtra(EXTRA_LAUNCH_CONVERSATION_IDS, new ArrayList<>(Collections.singletonList(conversationId)));
intent.putExtra(EXTRA_LAUNCH_EPHEMERAL_EXPIRATION, expiration.milliseconds);
return intent;
}
public static Intent getAppLaunchIntent(@NonNull Context context,
List<String> conversationIds,
List<URI> sharedFiles,
EphemeralExpiration expiration) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(EXTRA_LAUNCH_FROM_SHARING, true);
intent.putParcelableArrayListExtra(EXTRA_LAUNCH_CONVERSATION_FILES, mapToAndroidUris(sharedFiles));
intent.putStringArrayListExtra(EXTRA_LAUNCH_CONVERSATION_IDS, new ArrayList<>(conversationIds));
intent.putExtra(EXTRA_LAUNCH_EPHEMERAL_EXPIRATION, expiration.milliseconds);
return intent;
}
public static Intent getAppLaunchIntent(@NonNull Context context, String conversationId) {
return getAppLaunchIntent(context, conversationId, (String) null);
}
public static Intent getAppLaunchIntent(@NonNull Context context) {
return getAppLaunchIntent(context, new ArrayList<String>(), (String) null, EphemeralExpiration.NONE);
}
public static PendingIntent getNotificationAppLaunchIntent(@NonNull Context context) {
return getNotificationAppLaunchIntent(context, null, (int) System.currentTimeMillis());
}
public static PendingIntent getNotificationAppLaunchIntent(@NonNull Context context, String conversationId, int requestCode) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(EXTRA_LAUNCH_FROM_NOTIFICATION, true);
intent.putExtra(EXTRA_LAUNCH_START_CALL, false);
intent.putStringArrayListExtra(EXTRA_LAUNCH_CONVERSATION_IDS, new ArrayList<>(Collections.singletonList(conversationId)));
return PendingIntent.getActivity(context, requestCode, intent, 0);
}
public static PendingIntent getNotificationCallIntent(@NonNull Context context, String conversationId, int requestCode) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(EXTRA_LAUNCH_FROM_NOTIFICATION, true);
intent.putExtra(EXTRA_LAUNCH_START_CALL, true);
intent.putStringArrayListExtra(EXTRA_LAUNCH_CONVERSATION_IDS, new ArrayList<>(Collections.singletonList(conversationId)));
return PendingIntent.getActivity(context, requestCode, intent, 0);
}
public static PendingIntent getNotificationReplyIntent(Context context, String conversationId, int requestCode) {
Intent intent = new Intent(context, PopupActivity.class);
intent.putExtra(EXTRA_LAUNCH_FROM_NOTIFICATION, true);
intent.putStringArrayListExtra(EXTRA_LAUNCH_CONVERSATION_IDS, new ArrayList<>(Collections.singletonList(conversationId)));
return PendingIntent.getActivity(context, requestCode, intent, 0);
}
public static PendingIntent getGalleryIntent(Context context, URI uri) {
// TODO: AN-2276 - Replace with ShareCompat.IntentBuilder
Uri androidUri = AndroidURIUtil.unwrap(uri);
Intent galleryIntent = new Intent(Intent.ACTION_VIEW);
galleryIntent.setDataAndTypeAndNormalize(androidUri, IMAGE_MIME_TYPE);
galleryIntent.setClipData(new ClipData(null, new String[] {IMAGE_MIME_TYPE}, new ClipData.Item(androidUri)));
galleryIntent.putExtra(Intent.EXTRA_STREAM, androidUri);
return PendingIntent.getActivity(context, 0, galleryIntent, 0);
}
public static PendingIntent getPendingShareIntent(Context context, URI uri) {
Intent shareIntent = new Intent(context, ShareSavedImageActivity.class);
shareIntent.putExtra(Intent.EXTRA_STREAM, AndroidURIUtil.unwrap(uri));
shareIntent.putExtra(IntentUtils.EXTRA_LAUNCH_FROM_SAVE_IMAGE_NOTIFICATION, true);
return PendingIntent.getActivity(context, 0, shareIntent, 0);
}
public static Intent getDebugReportIntent(Context context, URI fileUri) {
String versionName;
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
versionName = packageInfo.versionName;
} catch (Exception e) {
versionName = "n/a";
}
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("vnd.android.cursor.dir/email");
String[] to = {"support@wire.com"};
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_STREAM, AndroidURIUtil.unwrap(fileUri));
intent.putExtra(Intent.EXTRA_TEXT, context.getString(R.string.debug_report__body));
intent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.debug_report__title, versionName));
return intent;
}
public static String getLaunchConversationId(Intent intent) {
List<String> convIds = intent.getStringArrayListExtra(EXTRA_LAUNCH_CONVERSATION_IDS);
return convIds == null || convIds.isEmpty() ? null : convIds.get(0);
}
public static List<String> getLaunchConversationIds(Intent intent) {
return intent.getStringArrayListExtra(EXTRA_LAUNCH_CONVERSATION_IDS);
}
public static String getLaunchConversationSharedText(Intent intent) {
return intent.getStringExtra(EXTRA_LAUNCH_CONVERSATION_MESSAGE);
}
private static List<Uri> getParcelableArrayListExtra(Intent intent) {
List<Uri> files = intent.getParcelableArrayListExtra(EXTRA_LAUNCH_CONVERSATION_FILES);
if (files == null) {
return Collections.emptyList();
} else {
return files;
}
}
public static List<URI> getLaunchConversationSharedFiles(Intent intent) {
List<URI> androidUris = new ArrayList<>();
for (Uri uri: getParcelableArrayListExtra(intent)) {
androidUris.add(new AndroidURI(uri));
}
return androidUris;
}
public static EphemeralExpiration getEphemeralExpiration(Intent intent) {
return EphemeralExpiration.getForMillis(intent.getLongExtra(EXTRA_LAUNCH_EPHEMERAL_EXPIRATION, EphemeralExpiration.NONE.milliseconds));
}
public static boolean isStartCallNotificationIntent(Intent intent) {
return intent.getBooleanExtra(EXTRA_LAUNCH_START_CALL, false);
}
public static Intent getSavedImageShareIntent(Context context, URI uri) {
Uri androidUri = AndroidURIUtil.unwrap(uri);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setClipData(new ClipData(null, new String[] {IMAGE_MIME_TYPE}, new ClipData.Item(androidUri)));
shareIntent.putExtra(Intent.EXTRA_STREAM, androidUri);
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shareIntent.setDataAndTypeAndNormalize(androidUri, IMAGE_MIME_TYPE);
return Intent.createChooser(shareIntent,
context.getString(R.string.notification__image_saving__action__share));
}
public static boolean isLaunchFromSaveImageNotificationIntent(@Nullable Intent intent) {
return intent != null &&
intent.getBooleanExtra(EXTRA_LAUNCH_FROM_SAVE_IMAGE_NOTIFICATION, false);
}
public static Intent getGoogleMapsIntent(Context context, float lat, float lon, int zoom, String name) {
Uri gmmIntentUri;
if (StringUtils.isBlank(name)) {
gmmIntentUri = Uri.parse(String.format(GOOGLE_MAPS_INTENT_URI, lat, lon));
} else {
gmmIntentUri = Uri.parse(String.format(GOOGLE_MAPS_WITH_LABEL_INTENT_URI, lat, lon, name));
}
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage(GOOGLE_MAPS_INTENT_PACKAGE);
if (mapIntent.resolveActivity(context.getPackageManager()) == null) {
return getGoogleMapsWebFallbackIntent(context, lat, lon, zoom, name);
}
return mapIntent;
}
private static Intent getGoogleMapsWebFallbackIntent(Context context, float lat, float lon, int zoom, String name) {
String urlEncodedName;
try {
urlEncodedName = URLEncoder.encode(name, "UTF-8");
} catch (UnsupportedEncodingException e) {
urlEncodedName = name;
}
String url = String.format(Locale.getDefault(), GOOGLE_MAPS_WEB_LINK, zoom, lat, lon, urlEncodedName);
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return browserIntent;
}
public static Intent getInviteIntent(String subject, String body) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, body);
return intent;
}
}