package com.alexvasilkov.android.commons.utils; import android.annotation.TargetApi; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.provider.CalendarContract; import android.provider.ContactsContract; import android.provider.MediaStore; import android.provider.Telephony; import android.text.SpannableString; import android.text.Spanned; import java.util.TimeZone; public class Intents { public static final String MIME_TYPE_HTML = "text/html"; public static final String MIME_TYPE_TEXT = "text/plain"; public static final String MIME_TYPE_EMAIL = "message/rfc822"; public static Builder get(Context context) { return new Builder(context); } private Intents() { } public static class Builder { private final Context context; private boolean useChooser; private CharSequence chooserTitle; private Integer requestCode; private Builder(Context context) { this.context = context; } public Builder useChooser(boolean useChooser) { this.useChooser = useChooser; return this; } public Builder useChooser() { return useChooser(true); } public Builder chooserTitle(CharSequence chooserTitle) { this.chooserTitle = chooserTitle; return this; } public Builder requestCode(Integer requestCode) { this.requestCode = requestCode; return this; } /** * Return builder for sharing request.<br/> * Opens chooser dialog (if useChooser() method is called before) with all apps that can share provided text.<br/> * Uses Intent.ACTION_SEND action and "plain/text" mime type. */ public ShareBuilder share() { return new ShareBuilder(this); } /** * Opens given url in the default browser. */ public boolean openWebBrowser(String url) { return open(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); } /** * Opens standard dialer app with prefilled phone number. */ public boolean dial(String phone) { return open(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phone))); } /** * Opens Google Play app details screen for specified package. Opens browser if Google Play app is not found. */ public boolean openGooglePlay(String appPackage) { boolean started = open(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackage))); if (!started) started = openWebBrowser("http://play.google.com/store/apps/details?id=" + appPackage); return started; } /** * Opens YouTube app with given video id. */ public boolean openYouTube(String videoId) { boolean started = open(new Intent(Intent.ACTION_VIEW, Uri.parse(String.format("vnd.youtube:%s", videoId)))); if (!started) started = openWebBrowser(String.format("http://m.youtube.com/watch?v=%s", videoId)); return started; } /** * Opens phone picker activity. See also {@link IntentsHandler#onPickPhoneResult(android.content.Context, android.content.Intent)} */ public boolean pickPhoneNumber() { if (requestCode == null) throw new NullPointerException("Activity request code is required when picking phone number"); Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE); return open(intent); } /** * Opens gallery image picker activity. You can get picked image's Uri using {@link android.content.Intent#getData()} * inside {@link android.app.Activity#onActivityResult(int, int, android.content.Intent)} method. */ public boolean pickPhotoFromGallery() { if (requestCode == null) throw new NullPointerException("Activity request code is required when picking image"); Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); intent.setType("image/*"); return open(intent); } /** * Returns builder for sms sending request. */ public SmsBuilder sendSms() { return new SmsBuilder(this); } /** * Returns builder for "add calendar event" request. */ public EmailBuilder sendEmail() { return new EmailBuilder(this); } /** * Returns builder for "add calendar event" request. */ public AddToCalendarBuilder addToCalendar() { return new AddToCalendarBuilder(this); } public boolean open(Intent intent) { intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); try { startActivity(useChooser ? Intent.createChooser(intent, chooserTitle) : intent); return true; } catch (ActivityNotFoundException e) { try { startActivity(Intent.createChooser(intent, chooserTitle)); return true; } catch (ActivityNotFoundException e2) { e2.printStackTrace(); return false; } } } private void startActivity(Intent intent) { if (requestCode == null) { context.startActivity(intent); } else { ((Activity) context).startActivityForResult(intent, requestCode); } } } public static class ShareBuilder { private final Builder builder; private String title, text; private ShareBuilder(Builder builder) { this.builder = builder; } public ShareBuilder title(String title) { this.title = title; return this; } public ShareBuilder text(String text) { this.text = text; return this; } public boolean open() { if (text == null) throw new NullPointerException("Sharing text cannot be null"); Intent intent = new Intent(Intent.ACTION_SEND); intent.setType(MIME_TYPE_TEXT); if (title != null) intent.putExtra(Intent.EXTRA_SUBJECT, title); intent.putExtra(Intent.EXTRA_TEXT, text); return builder.open(intent); } } public static class SmsBuilder { private final Builder builder; private String phone, text; private SmsBuilder(Builder builder) { this.builder = builder; } public SmsBuilder phone(String phone) { this.phone = phone; return this; } public SmsBuilder text(String text) { this.text = text; return this; } public boolean open() { Intent intent; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (phone == null || phone.length() == 0) { intent = new Intent(Intent.ACTION_SEND); intent.setType(MIME_TYPE_TEXT); if (text != null) intent.putExtra(Intent.EXTRA_TEXT, text); } else { intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:" + Uri.encode(phone))); if (text != null) intent.putExtra("sms_body", text); } String defaultSmsPackageName = Telephony.Sms.getDefaultSmsPackage(builder.context); if (defaultSmsPackageName != null) intent.setPackage(defaultSmsPackageName); } else { intent = new Intent(Intent.ACTION_VIEW); intent.setType("vnd.android-dir/mms-sms"); if (phone != null && phone.length() > 0) intent.putExtra("address", phone); if (text != null) intent.putExtra("sms_body", text); } return builder.open(intent); } } public static class EmailBuilder { private final Builder builder; private String[] toEmails, ccEmails, bccEmails; private String subject; private Spanned body; private String mimeType; private String attachedFileUri; private EmailBuilder(Builder builder) { this.builder = builder; } public EmailBuilder toEmails(String... toEmails) { this.toEmails = toEmails; return this; } public EmailBuilder ccEmails(String... ccEmails) { this.ccEmails = ccEmails; return this; } public EmailBuilder bccEmails(String... bccEmails) { this.bccEmails = bccEmails; return this; } public EmailBuilder subject(String subject) { this.subject = subject; return this; } public EmailBuilder body(Spanned body) { this.body = body; return this; } public EmailBuilder body(String body) { this.body = new SpannableString(body); return this; } public EmailBuilder mimeType(String mimeType) { this.mimeType = mimeType; return this; } public EmailBuilder asHtml() { return mimeType(MIME_TYPE_HTML); } public EmailBuilder asPlainText() { return mimeType(MIME_TYPE_TEXT); } public EmailBuilder attachment(String attachedFileUri) { this.attachedFileUri = attachedFileUri; return this; } public boolean open() { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType(mimeType == null ? MIME_TYPE_EMAIL : mimeType); if (toEmails != null) intent.putExtra(Intent.EXTRA_EMAIL, toEmails); if (ccEmails != null) intent.putExtra(Intent.EXTRA_CC, ccEmails); if (bccEmails != null) intent.putExtra(Intent.EXTRA_BCC, bccEmails); if (subject != null) intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject); if (body != null) intent.putExtra(Intent.EXTRA_TEXT, body); if (attachedFileUri != null) { intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.putExtra(Intent.EXTRA_STREAM, Uri.parse(attachedFileUri)); } return builder.open(intent); } } public static class AddToCalendarBuilder { private final Builder builder; private long beginTime, endTime; private TimeZone tz; private boolean isAllDay; private String title, description, location; private AddToCalendarBuilder(Builder builder) { this.builder = builder; } public AddToCalendarBuilder begin(long beginTime) { this.beginTime = beginTime; return this; } public AddToCalendarBuilder end(long endTime) { this.endTime = endTime; return this; } public AddToCalendarBuilder timezone(TimeZone tz) { this.tz = tz; return this; } public AddToCalendarBuilder allDay(boolean isAllDay) { this.isAllDay = isAllDay; return this; } public AddToCalendarBuilder allDay() { return allDay(true); } public AddToCalendarBuilder title(String title) { this.title = title; return this; } public AddToCalendarBuilder description(String description) { this.description = description; return this; } public AddToCalendarBuilder location(String location) { this.location = location; return this; } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public boolean open() { Intent intent = new Intent(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { intent.setAction(Intent.ACTION_INSERT); intent.setData(CalendarContract.Events.CONTENT_URI); } else { intent.setAction(Intent.ACTION_EDIT); intent.setType("vnd.android.cursor.item/event"); } if (tz != null) { // sending timezone is now working, so we will add timezone offset manually if (beginTime != 0) { long offsetDiff = tz.getOffset(beginTime) - TimeZone.getDefault().getOffset(beginTime); beginTime += offsetDiff; } if (endTime != 0) { long offsetDiff = tz.getOffset(endTime) - TimeZone.getDefault().getOffset(endTime); endTime += offsetDiff; } } if (beginTime == 0) { // begin time seems to be mandatory for some apps beginTime = System.currentTimeMillis(); } if (endTime == 0) { // begin time seems to be mandatory for some apps endTime = beginTime + 60 * 60 * 1000; } if (beginTime != 0) intent.putExtra("beginTime", beginTime); if (endTime != 0) intent.putExtra("endTime", endTime); if (isAllDay) intent.putExtra("allDay", true); if (title != null) intent.putExtra("title", title); if (description != null) intent.putExtra("description", description); if (location != null) intent.putExtra("eventLocation", location); return builder.open(intent); } } }