From f4edbdde11d0829ba8de78b2504d7e9abc5f7695 Mon Sep 17 00:00:00 2001 From: Arunkumar Date: Mon, 3 Oct 2016 23:45:46 +0530 Subject: [PATCH 01/15] Fix crash when try to extract text from un supported clip items. Fixes #2 --- app/src/main/java/arun/com/chromer/util/Util.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/arun/com/chromer/util/Util.java b/app/src/main/java/arun/com/chromer/util/Util.java index a6ab0986..0946ef46 100644 --- a/app/src/main/java/arun/com/chromer/util/Util.java +++ b/app/src/main/java/arun/com/chromer/util/Util.java @@ -43,6 +43,7 @@ import arun.com.chromer.customtabs.prefetch.ScannerService; import arun.com.chromer.shared.Constants; import arun.com.chromer.views.IntentPickerSheetView; +import timber.log.Timber; /** * Created by Arun on 17/12/2015. @@ -307,11 +308,15 @@ public static boolean isNetworkAvailable(@NonNull Context context) { @Nullable public static String getClipBoardText(@NonNull Context context) { final ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - if (clipboardManager.hasPrimaryClip()) { - final ClipData.Item item = clipboardManager.getPrimaryClip().getItemAt(0); - if (item != null) { - return item.getText().toString(); + try { + if (clipboardManager.hasPrimaryClip() & clipboardManager.getPrimaryClip().getItemCount() != 0) { + final ClipData.Item item = clipboardManager.getPrimaryClip().getItemAt(0); + if (item != null && item.getText() != null) { + return item.getText().toString(); + } } + } catch (Exception ignored) { + Timber.e(ignored.toString()); } return null; } From d7b8f8b85119077eba8ee199fcf49a16e49e2c52 Mon Sep 17 00:00:00 2001 From: Arunkumar Date: Tue, 4 Oct 2016 00:10:16 +0530 Subject: [PATCH 02/15] Fix crash when attempting to create shorcut with a huge icon causing system to through too large transaction exception --- .../callbacks/AddHomeShortcutService.java | 89 ++++++------------- 1 file changed, 29 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/arun/com/chromer/customtabs/callbacks/AddHomeShortcutService.java b/app/src/main/java/arun/com/chromer/customtabs/callbacks/AddHomeShortcutService.java index f23089c6..c53af4ef 100644 --- a/app/src/main/java/arun/com/chromer/customtabs/callbacks/AddHomeShortcutService.java +++ b/app/src/main/java/arun/com/chromer/customtabs/callbacks/AddHomeShortcutService.java @@ -20,7 +20,6 @@ import com.bumptech.glide.Glide; -import java.net.URL; import java.util.concurrent.ExecutionException; import arun.com.chromer.R; @@ -57,38 +56,41 @@ protected void onHandleIntent(Intent intent) { return; } - String shortCutName = getShortcutName(unShortenedUrl, res); - String faviconUrl = res.getFaviconUrl(); + final String shortCutName = getShortcutName(unShortenedUrl, res); + final String faviconUrl = res.getFaviconUrl(); Bitmap favicon = getFaviconBitmap(faviconUrl); - if (favicon != null) { - if (!isValidFavicon(favicon)) { - Palette palette = Palette.from(favicon).generate(); - int iconColor = ColorUtil.getBestFaviconColor(palette); - if (iconColor == -1) { - iconColor = ContextCompat.getColor(this, R.color.primary); - } - favicon = createIcon(iconColor, shortCutName); - } - } else { + if (favicon == null) { favicon = createIcon(ContextCompat.getColor(this, R.color.primary), shortCutName); + } else if (!isValidFavicon(favicon)) { + final Palette palette = Palette.from(favicon).generate(); + int iconColor = ColorUtil.getBestFaviconColor(palette); + if (iconColor == Constants.NO_COLOR) { + iconColor = ContextCompat.getColor(this, R.color.primary); + } + favicon = createIcon(iconColor, shortCutName); } Timber.i("Creating shortcut: %s", shortCutName); + try { + broadcastShortcutIntent(shortCutName, favicon, getWebIntent(unShortenedUrl)); + } catch (Exception e) { + Timber.e("Failed to create shortcut"); + } - Intent webIntent = getWebIntent(unShortenedUrl); - - Intent addIntent = new Intent(Constants.ACTION_INSTALL_SHORTCUT); - addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, webIntent); - addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortCutName); - addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, favicon); - - sendBroadcast(addIntent); showToast(getString(R.string.added) + " " + shortCutName); } } } + private void broadcastShortcutIntent(String shortCutName, Bitmap favicon, Intent webIntent) { + Intent addIntent = new Intent(Constants.ACTION_INSTALL_SHORTCUT); + addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, webIntent); + addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortCutName); + addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, favicon); + sendBroadcast(addIntent); + } + @Nullable private JResult extractWebsiteData(HtmlFetcher fetcher, String unShortenedUrl) { JResult res = null; @@ -112,7 +114,7 @@ private Bitmap getFaviconBitmap(String faviconUrl) { favicon = Glide.with(this) .load(faviconUrl) .asBitmap() - .into(-1, -1) + .into(192, 192) .get(); } catch (InterruptedException | ExecutionException ignored) { @@ -155,7 +157,7 @@ private Bitmap createIcon(@ColorInt int color, String shortCutName) { textPaint.setColor(ColorUtil.getForegroundWhiteOrBlack(color)); textPaint.setStyle(Paint.Style.FILL); - drawTextInCanvasCentre(canvas, textPaint, getLetter(shortCutName)); + drawTextInCanvasCentre(canvas, textPaint, Util.getFirstLetter(shortCutName)); return icon; } @@ -170,40 +172,13 @@ private void drawTextInCanvasCentre(Canvas canvas, Paint paint, String text) { canvas.drawText(text, x, y, paint); } - private String getLetter(String address) { - String result = "X"; - if (address != null) { - try { - URL url = new URL(address); - String host = url.getHost(); - if (host != null && host.length() != 0) { - if (host.startsWith("www")) { - String[] splits = host.split("\\."); - if (splits.length > 1) result = String.valueOf(splits[1].charAt(0)); - else result = String.valueOf(splits[0].charAt(0)); - } else - result = String.valueOf(host.charAt(0)); - } else { - if (address.length() != 0) { - return String.valueOf(address.charAt(0)); - } - } - } catch (Exception e) { - if (address.length() != 0) { - return String.valueOf(address.charAt(0)); - } else return result; - } - } - return result.toUpperCase(); - } - - private boolean isValidFavicon(Bitmap favicon) { + private boolean isValidFavicon(@NonNull Bitmap favicon) { return !(favicon.getWidth() == 16 || favicon.getHeight() == 16 || favicon.getWidth() == 32 || favicon.getHeight() == 32); } private void legacyAdd(@NonNull String unShortenedUrl) { - Intent webIntent = getWebIntent(unShortenedUrl); + final Intent webIntent = getWebIntent(unShortenedUrl); String hostName = Uri.parse(unShortenedUrl).getHost(); String shortcutName = hostName == null ? unShortenedUrl : hostName; @@ -216,20 +191,14 @@ private void legacyAdd(@NonNull String unShortenedUrl) { Intent.ShortcutIconResource.fromContext( getApplicationContext(), R.mipmap.ic_launcher)); - sendBroadcast(addIntent); } private void showToast(@NonNull final String msgToShow) { - Handler handler = new Handler(Looper.getMainLooper()); - handler.post(new Runnable() { - + new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { - Toast.makeText( - AddHomeShortcutService.this, - msgToShow, - Toast.LENGTH_SHORT).show(); + Toast.makeText(AddHomeShortcutService.this, msgToShow, Toast.LENGTH_SHORT).show(); } }); } From c4d04b64c44f14e17cbde97d8d61e2e221e94f60 Mon Sep 17 00:00:00 2001 From: Arunkumar Date: Tue, 4 Oct 2016 00:15:56 +0530 Subject: [PATCH 03/15] Fix crash when user pops out of donate activity quickly. --- .../com/chromer/activities/payments/util/IabHelper.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/arun/com/chromer/activities/payments/util/IabHelper.java b/app/src/main/java/arun/com/chromer/activities/payments/util/IabHelper.java index 2a98aae9..0bfbfebd 100644 --- a/app/src/main/java/arun/com/chromer/activities/payments/util/IabHelper.java +++ b/app/src/main/java/arun/com/chromer/activities/payments/util/IabHelper.java @@ -36,6 +36,8 @@ import java.util.ArrayList; import java.util.List; +import timber.log.Timber; + /** * Provides convenience methods for in-app billing. You can create one instance of this @@ -770,6 +772,10 @@ void flagEndAsync() { int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException { // Query purchases + if (mContext == null) { + Timber.d("User cancelled"); + return BILLING_RESPONSE_RESULT_USER_CANCELED; + } logDebug("Querying owned items, item type: " + itemType); logDebug("Package name: " + mContext.getPackageName()); boolean verificationFailed = false; From 095d82cfe0db83fdd45b71d2b003020fc4dab2bf Mon Sep 17 00:00:00 2001 From: Arunkumar Date: Tue, 4 Oct 2016 00:39:33 +0530 Subject: [PATCH 04/15] Minor fix --- .../java/arun/com/chromer/activities/CustomTabActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java b/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java index 248cec1a..5bd3e492 100644 --- a/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java +++ b/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java @@ -183,6 +183,9 @@ protected void onPostExecute(Void aVoid) { label = mUrl.toUpperCase(); } Timber.d("Setting task description %s", label); + if (mIcon != null && mIcon.getWidth() < 0) { + mIcon = null; + } if (color != Constants.NO_COLOR) { setTaskDescription(new ActivityManager.TaskDescription(label, mIcon, color)); } else { From cc7d54cc6e5197dccd23802728481dc91ee9cbc9 Mon Sep 17 00:00:00 2001 From: Arunkumar Date: Tue, 4 Oct 2016 00:59:11 +0530 Subject: [PATCH 05/15] Improvements to reduce loading flickering. --- .../chromer/activities/CustomTabActivity.java | 3 ++- .../com/chromer/customtabs/CustomTabs.java | 23 +++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java b/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java index 5bd3e492..7006116c 100644 --- a/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java +++ b/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java @@ -57,6 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { .forUrl(url) .forWebHead(isWebhead) .overrideToolbarColor(color) + .noAnimations(Preferences.aggressiveLoading(this)) .prepare() .launch(); Benchmark.end(); @@ -74,7 +75,7 @@ private void delayedGoToBack() { public void run() { moveTaskToBack(true); } - }, 650); + }, 300); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) diff --git a/app/src/main/java/arun/com/chromer/customtabs/CustomTabs.java b/app/src/main/java/arun/com/chromer/customtabs/CustomTabs.java index 69d70f6c..e094dcb1 100644 --- a/app/src/main/java/arun/com/chromer/customtabs/CustomTabs.java +++ b/app/src/main/java/arun/com/chromer/customtabs/CustomTabs.java @@ -119,6 +119,8 @@ public void openUri(Activity activity, Uri uri) { private CustomTabs(Activity context) { mActivity = context; + mForWebHead = false; + mNoAnimations = false; } /** @@ -134,28 +136,31 @@ public static CustomTabs from(@NonNull Activity activity) { /** * Opens the URL on a Custom Tab if possible. Otherwise fallsback to opening it on a WebView. * - * @param activity The host activity. * @param customTabsIntent a CustomTabsIntent to be used if Custom Tabs is available. * @param uri the Uri to be opened. */ - private static void openCustomTab(Activity activity, CustomTabsIntent customTabsIntent, Uri uri) { - final String packageName = getCustomTabPackage(activity); + private void openCustomTab(CustomTabsIntent customTabsIntent, Uri uri) { + final String packageName = getCustomTabPackage(mActivity); if (packageName != null) { customTabsIntent.intent.setPackage(packageName); Intent keepAliveIntent = new Intent() - .setClassName(activity.getPackageName(), KeepAliveService.class.getCanonicalName()); + .setClassName(mActivity.getPackageName(), KeepAliveService.class.getCanonicalName()); customTabsIntent.intent.putExtra(EXTRA_CUSTOM_TABS_KEEP_ALIVE, keepAliveIntent); + + if (mNoAnimations) { + customTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + } try { - customTabsIntent.launchUrl(activity, uri); + customTabsIntent.launchUrl(mActivity, uri); Timber.d("Launched url: %s", uri.toString()); } catch (Exception e) { - CUSTOM_TABS_FALLBACK.openUri(activity, uri); + CUSTOM_TABS_FALLBACK.openUri(mActivity, uri); Timber.e("Called fallback even though a package was found, weird Exception : %s", e.toString()); } } else { Timber.e("Called fallback since no package found!"); - CUSTOM_TABS_FALLBACK.openUri(activity, uri); + CUSTOM_TABS_FALLBACK.openUri(mActivity, uri); } } @@ -293,8 +298,8 @@ public CustomTabs prepare() { */ public void launch() { assertBuilderInitialized(); - CustomTabsIntent customTabsIntent = mIntentBuilder.build(); - openCustomTab(mActivity, customTabsIntent, Uri.parse(mUrl)); + final CustomTabsIntent customTabsIntent = mIntentBuilder.build(); + openCustomTab(customTabsIntent, Uri.parse(mUrl)); // Dispose reference mActivity = null; From 7c9851b9bf72974337930df14f7d648704647e8c Mon Sep 17 00:00:00 2001 From: Arunkumar Date: Sun, 16 Oct 2016 02:00:22 +0530 Subject: [PATCH 06/15] Gradle --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7e6b03ee..902bd2a1 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { maven { url "https://jitpack.io" } } dependencies { - classpath 'com.android.tools.build:gradle:2.2.0-rc1' + classpath 'com.android.tools.build:gradle:2.2.1' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From ce626551a6e47e9a885e4d0e9efd61fd901a3964 Mon Sep 17 00:00:00 2001 From: Arunkumar Date: Sun, 16 Oct 2016 02:13:19 +0530 Subject: [PATCH 07/15] Reverting the flicker improvement changes --- .../com/chromer/activities/CustomTabActivity.java | 4 ++-- .../arun/com/chromer/customtabs/CustomTabs.java | 14 +++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java b/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java index 7006116c..885e0042 100644 --- a/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java +++ b/app/src/main/java/arun/com/chromer/activities/CustomTabActivity.java @@ -57,7 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { .forUrl(url) .forWebHead(isWebhead) .overrideToolbarColor(color) - .noAnimations(Preferences.aggressiveLoading(this)) + // .noAnimations(Preferences.aggressiveLoading(this)) .prepare() .launch(); Benchmark.end(); @@ -75,7 +75,7 @@ private void delayedGoToBack() { public void run() { moveTaskToBack(true); } - }, 300); + }, 650); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) diff --git a/app/src/main/java/arun/com/chromer/customtabs/CustomTabs.java b/app/src/main/java/arun/com/chromer/customtabs/CustomTabs.java index e094dcb1..f1d767b1 100644 --- a/app/src/main/java/arun/com/chromer/customtabs/CustomTabs.java +++ b/app/src/main/java/arun/com/chromer/customtabs/CustomTabs.java @@ -144,12 +144,13 @@ private void openCustomTab(CustomTabsIntent customTabsIntent, Uri uri) { if (packageName != null) { customTabsIntent.intent.setPackage(packageName); - Intent keepAliveIntent = new Intent() - .setClassName(mActivity.getPackageName(), KeepAliveService.class.getCanonicalName()); + + final Intent keepAliveIntent = new Intent(); + keepAliveIntent.setClassName(mActivity.getPackageName(), KeepAliveService.class.getCanonicalName()); customTabsIntent.intent.putExtra(EXTRA_CUSTOM_TABS_KEEP_ALIVE, keepAliveIntent); if (mNoAnimations) { - customTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + // customTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); } try { customTabsIntent.launchUrl(mActivity, uri); @@ -278,17 +279,12 @@ public CustomTabs prepare() { // set defaults mIntentBuilder.setShowTitle(true); mIntentBuilder.enableUrlBarHiding(); - mIntentBuilder.addDefaultShareMenuItem(); // TODO make this conditional + mIntentBuilder.addDefaultShareMenuItem(); - // prepare animations prepareAnimations(); - // prepare toolbar color prepareToolbar(); - // prepare action button prepareActionButton(); - // prepare all the menu items prepareMenuItems(); - // prepare all bottom bar item prepareBottomBar(); return this; } From 5d46566effbf7750ce589a1da4fdc034ef1b6133 Mon Sep 17 00:00:00 2001 From: Arunkumar Date: Sun, 16 Oct 2016 02:27:21 +0530 Subject: [PATCH 08/15] Improving transparent theme --- app/src/main/AndroidManifest.xml | 6 +++--- app/src/main/res/values-v21/styles.xml | 9 +++++++++ app/src/main/res/values/styles.xml | 10 +++++----- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8dcd3e04..24d7e675 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -74,7 +74,7 @@ + android:theme="@style/Theme.AppCompat.Translucent"/> + android:theme="@style/Theme.AppCompat.Translucent"> @@ -140,7 +140,7 @@ android:name=".webheads.helper.ProxyActivity" android:excludeFromRecents="true" android:noHistory="true" - android:theme="@style/Transparent"/> + android:theme="@style/Theme.AppCompat.Translucent"/> @drawable/launch_screen @color/colorPrimaryDarker + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9b3832fb..2ec3ee20 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -71,12 +71,12 @@ @drawable/launch_screen -