package me.ccrama.redditslide.util; import android.app.Activity; import android.app.PendingIntent; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.customtabs.CustomTabsCallback; import android.support.customtabs.CustomTabsClient; import android.support.customtabs.CustomTabsIntent; import android.support.customtabs.CustomTabsServiceConnection; import android.support.customtabs.CustomTabsSession; import android.support.v4.content.ContextCompat; import android.text.Html; import android.util.Log; import net.dean.jraw.models.Submission; import java.util.Set; import me.ccrama.redditslide.Activities.MakeExternal; import me.ccrama.redditslide.Activities.ReaderMode; import me.ccrama.redditslide.Activities.Website; import me.ccrama.redditslide.BuildConfig; import me.ccrama.redditslide.R; import me.ccrama.redditslide.Reddit; import me.ccrama.redditslide.SettingValues; import me.ccrama.redditslide.SubmissionViews.PopulateSubmissionViewHolder; public class LinkUtil { private static CustomTabsSession mCustomTabsSession; private static CustomTabsClient mClient; private static CustomTabsServiceConnection mConnection; private LinkUtil() { } public static Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } /** * Opens the {@code url} using the method the user has set in their preferences (custom tabs, * internal, external) falling back as needed * @param url URL to open * @param color Color to provide to the browser UI if applicable * @param contextActivity The current activity */ public static void openUrl(@NonNull String url, int color, @NonNull Activity contextActivity) { if (!SettingValues.web) { // External browser Reddit.defaultShare(url, contextActivity); return; } String packageName = CustomTabsHelper.getPackageNameToUse(contextActivity); if (packageName != null) { Intent intent = new Intent(contextActivity, MakeExternal.class); intent.putExtra(Website.EXTRA_URL, url); PendingIntent pendingIntent = PendingIntent.getActivity(contextActivity, 0, intent, 0); CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(getSession()) .setToolbarColor(color) .setShowTitle(true) .setStartAnimations(contextActivity, R.anim.slide_up_fade_in, 0) .setExitAnimations(contextActivity, 0, R.anim.slide_down_fade_out) .addDefaultShareMenuItem() .addMenuItem(contextActivity.getString(R.string.open_links_externally), pendingIntent) .setCloseButtonIcon(drawableToBitmap(ContextCompat.getDrawable(contextActivity, R.drawable.ic_arrow_back_white_24dp))); try { CustomTabsIntent customTabsIntent = builder.build(); customTabsIntent.intent.setPackage(packageName); customTabsIntent.launchUrl(contextActivity, formatURL(url)); } catch (ActivityNotFoundException anfe) { Log.w(LogUtil.getTag(), "Unknown url: " + anfe); Reddit.defaultShare(url, contextActivity); } } else { if(SettingValues.reader && (!SettingValues.readerNight || SettingValues.isNight())){ //Reader mode Intent i = new Intent(contextActivity, ReaderMode.class); i.putExtra(ReaderMode.EXTRA_URL, url); i.putExtra(ReaderMode.EXTRA_COLOR, color); contextActivity.startActivity(i); } else { // Internal browser Intent i = new Intent(contextActivity, Website.class); i.putExtra(Website.EXTRA_URL, url); i.putExtra(Website.EXTRA_COLOR, color); contextActivity.startActivity(i); } } } public static void openUrl(@NonNull String url, int color, @NonNull Activity contextActivity, int adapterPosition, Submission submission) { if (!SettingValues.web) { // External browser Reddit.defaultShare(url, contextActivity); return; } String packageName = CustomTabsHelper.getPackageNameToUse(contextActivity); if (packageName != null) { Intent intent = new Intent(contextActivity, MakeExternal.class); intent.putExtra(Website.EXTRA_URL, url); PendingIntent pendingIntent = PendingIntent.getActivity(contextActivity, 0, intent, 0); CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(getSession()) .setToolbarColor(color) .setShowTitle(true) .setStartAnimations(contextActivity, R.anim.slide_up_fade_in, 0) .setExitAnimations(contextActivity, 0, R.anim.slide_down_fade_out) .addDefaultShareMenuItem() .addMenuItem(contextActivity.getString(R.string.open_links_externally), pendingIntent) .setCloseButtonIcon(drawableToBitmap(ContextCompat.getDrawable(contextActivity, R.drawable.ic_arrow_back_white_24dp))); try { CustomTabsIntent customTabsIntent = builder.build(); customTabsIntent.intent.setPackage(packageName); customTabsIntent.launchUrl(contextActivity, formatURL(url)); } catch (ActivityNotFoundException anfe) { Log.w(LogUtil.getTag(), "Unknown url: " + anfe); Reddit.defaultShare(url, contextActivity); } } else { if(SettingValues.reader && (!SettingValues.readerNight || SettingValues.isNight())){ //Reader mode Intent i = new Intent(contextActivity, ReaderMode.class); i.putExtra(ReaderMode.EXTRA_URL, url); PopulateSubmissionViewHolder.addAdaptorPosition(i, submission, adapterPosition); i.putExtra(ReaderMode.EXTRA_COLOR, color); contextActivity.startActivity(i); } else { // Internal browser Intent i = new Intent(contextActivity, Website.class); i.putExtra(Website.EXTRA_URL, url); PopulateSubmissionViewHolder.addAdaptorPosition(i, submission, adapterPosition); i.putExtra(Website.EXTRA_COLOR, color); contextActivity.startActivity(i); } } } /** * Corrects mistakes users might make when typing URLs, e.g. case sensitivity in the scheme * and converts to Uri * @param url URL to correct * @return corrected as a Uri */ public static Uri formatURL(String url) { if (url.startsWith("//")) { url = "https:" + url; } if (url.startsWith("/")) { url = "https://reddit.com" + url; } if (!url.contains("://") && !url.startsWith("mailto:")) { url = "http://" + url; } Uri uri = Uri.parse(url); Uri toReturn; try { toReturn = uri.normalizeScheme(); } catch(NoSuchMethodError e){ toReturn = uri; } return toReturn; } /** * Opens the {@code url} externally or shows an application chooser if it is set to open in this * application * @param url URL to open * @param context Current context * @param encoded If the URL is HTML encoded (e.g. includes {@code &}) */ public static void openExternally(String url, Context context, Boolean encoded) { if (encoded) url = Html.fromHtml(url).toString(); Uri uri = formatURL(url); openExternally(uri, context); } /** * Opens the {@code uri} externally or shows an application chooser if it is set to open in this * application * @param uri URI to open * @param context Current context */ public static void openExternally(Uri uri, Context context) { final String id = BuildConfig.APPLICATION_ID; final Intent intent = new Intent(Intent.ACTION_VIEW, uri); final PackageManager packageManager = context.getPackageManager(); String resolvedName; try { resolvedName = intent.resolveActivity(packageManager).getPackageName(); } catch(Exception e){ resolvedName = context.getPackageName(); } if (resolvedName == null) return; if (resolvedName.matches(id)) { context.startActivity( Intent.createChooser(intent, context.getString(R.string.misc_link_chooser)) ); return; } context.startActivity(intent); } public static CustomTabsSession getSession() { if (mClient == null) { mCustomTabsSession = null; } else if (mCustomTabsSession == null) { mCustomTabsSession = mClient.newSession(new CustomTabsCallback() { @Override public void onNavigationEvent(int navigationEvent, Bundle extras) { Log.w(LogUtil.getTag(), "onNavigationEvent: Code = " + navigationEvent); } }); } return mCustomTabsSession; } }