package com.gh4a.utils; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.support.customtabs.CustomTabsIntent; import android.support.v4.os.ParcelableCompat; import android.support.v4.os.ParcelableCompatCreatorCallbacks; import android.widget.Toast; import com.gh4a.R; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; public class IntentUtils { public static void launchBrowser(Context context, Uri uri) { launchBrowser(context, uri, 0); } public static void launchBrowser(Context context, Uri uri, int flags) { Intent intent = createBrowserIntent(context, uri); if (intent != null) { intent.addFlags(flags); context.startActivity(intent); } else { Toast.makeText(context, R.string.no_browser_found, Toast.LENGTH_LONG).show(); } } // We want to forward the URI to a browser, but our own intent filter matches // the browser's intent filters. We therefore resolve the intent by ourselves, // strip our own entry from the list and pass the result to the system's // activity chooser. // When doing that, pass a dummy URI to the resolver and swap in our real URI // later, as otherwise the system might return our package only if it's set // to handle the Github URIs by default private static Uri buildDummyUri(Uri uri) { return uri.buildUpon().authority("www.somedummy.com").build(); } private static Intent createBrowserIntent(Context context, Uri uri) { final Uri dummyUri = buildDummyUri(uri); final Intent browserIntent = new Intent(Intent.ACTION_VIEW, dummyUri) .addCategory(Intent.CATEGORY_BROWSABLE); return createActivityChooserIntent(context, browserIntent, uri); } public static Intent createViewerOrBrowserIntent(Context context, Uri uri, String mime) { final Uri dummyUri = buildDummyUri(uri); final Intent viewIntent = new Intent(Intent.ACTION_VIEW).setDataAndType(dummyUri, mime); final Intent resolvedViewIntent = createActivityChooserIntent(context, viewIntent, uri); if (resolvedViewIntent != null) { return resolvedViewIntent; } return createBrowserIntent(context, uri); } public static void openInCustomTabOrBrowser(Activity activity, Uri uri) { String pkg = CustomTabsHelper.getPackageNameToUse(activity); if (pkg != null) { int color = UiUtils.resolveColor(activity, R.attr.colorPrimary); CustomTabsIntent i = new CustomTabsIntent.Builder() .setToolbarColor(color) .build(); i.intent.setPackage(pkg); i.intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.launchUrl(activity, uri); } else { launchBrowser(activity, uri, Intent.FLAG_ACTIVITY_NEW_TASK); } } private static Intent createActivityChooserIntent(Context context, Intent intent, Uri uri) { final PackageManager pm = context.getPackageManager(); final List<ResolveInfo> activities = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); final ArrayList<Intent> chooserIntents = new ArrayList<>(); final String ourPackageName = context.getPackageName(); Collections.sort(activities, new ResolveInfo.DisplayNameComparator(pm)); for (ResolveInfo resInfo : activities) { ActivityInfo info = resInfo.activityInfo; if (!info.enabled || !info.exported) { continue; } if (info.packageName.equals(ourPackageName)) { continue; } Intent targetIntent = new Intent(intent); targetIntent.setPackage(info.packageName); targetIntent.setDataAndType(uri, intent.getType()); chooserIntents.add(targetIntent); } if (chooserIntents.isEmpty()) { return null; } final Intent lastIntent = chooserIntents.remove(chooserIntents.size() - 1); if (chooserIntents.isEmpty()) { // there was only one, no need to show the chooser return lastIntent; } Intent chooserIntent = Intent.createChooser(lastIntent, null); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, chooserIntents.toArray(new Intent[chooserIntents.size()])); return chooserIntent; } public static class InitialCommentMarker implements Parcelable { public final long commentId; public final Date date; public InitialCommentMarker(long commentId) { this(commentId, null); } public InitialCommentMarker(Date date) { this(-1, date); } private InitialCommentMarker(long commentId, Date date) { this.commentId = commentId; this.date = date; } public boolean matches(long id, Date date) { if (commentId >= 0 && id >= 0) { return commentId == id; } if (date != null && this.date != null) { return date.after(this.date); } return false; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { out.writeLong(commentId); out.writeLong(date != null ? date.getTime() : -1); } public static final Parcelable.Creator<InitialCommentMarker> CREATOR = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<InitialCommentMarker>() { @Override public InitialCommentMarker createFromParcel(Parcel in, ClassLoader loader) { long commentId = in.readLong(); long timeMillis = in.readLong(); return new InitialCommentMarker(commentId, timeMillis != -1 ? new Date(timeMillis) : null); } @Override public InitialCommentMarker[] newArray(int size) { return new InitialCommentMarker[size]; } }); } }