Bug 1385464 - Resolve missing resources and api changes; r?JanH draft
authorPetru Lingurar <petru.lingurar@softvision.ro>
Thu, 07 Jun 2018 13:44:36 +0300
changeset 805151 131447d0972b69e8b4433fca8691b035675f0c13
parent 805150 6134b856355972b089d34607ae896e3b57cff1bb
child 805152 38eb7cb5de04ac3bbc30f72b380f3e1ea59ff31a
push id112580
push userplingurar@mozilla.com
push dateThu, 07 Jun 2018 10:56:45 +0000
reviewersJanH
bugs1385464
milestone62.0a1
Bug 1385464 - Resolve missing resources and api changes; r?JanH - LeanplumActionBarActivity was removed because Support Library 26 deprecated ActionBarActivity. Class was already not in use. - CustomTabsService added two new methods which we need to override. Tested to make sure that previous functionality was maintained but with the addition of the two new methods maybe that feature could be improved. - For checking layout direction we'll use our own new method from ViewUtil which mimics what the now restricted method from the support library would do. - Upgraded to use AppCompatResources#getDrawable(..) in place of the now restricted AppCompatDrawableManager.get().getDrawable(..). MozReview-Commit-ID: 6UpPPVYyPPP
mobile/android/app/src/main/res/layout/bookmark_add_folder.xml
mobile/android/app/src/main/res/layout/bookmark_edit_with_full_page.xml
mobile/android/app/src/main/res/layout/bookmark_folder_select.xml
mobile/android/base/java/org/mozilla/gecko/customtabs/GeckoCustomTabsService.java
mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
mobile/android/base/java/org/mozilla/gecko/tabs/TabStripDividerItem.java
mobile/android/base/java/org/mozilla/gecko/tabs/TabStripView.java
mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutItemView.java
mobile/android/base/java/org/mozilla/gecko/util/ResourceDrawableUtils.java
mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java
mobile/android/base/java/org/mozilla/gecko/widget/DefaultItemAnimatorBase.java
mobile/android/base/java/org/mozilla/gecko/widget/GridSpacingDecoration.java
mobile/android/config/proguard/proguard-leanplum.cfg
mobile/android/thirdparty/com/leanplum/activities/LeanplumActionBarActivity.java
--- a/mobile/android/app/src/main/res/layout/bookmark_add_folder.xml
+++ b/mobile/android/app/src/main/res/layout/bookmark_add_folder.xml
@@ -13,17 +13,17 @@
     android:background="@android:color/white">
 
     <android.support.v7.widget.Toolbar
         android:id="@+id/toolbar"
         android:layout_width="match_parent"
         android:layout_height="?actionBarSize"
         android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
         android:background="@color/text_and_tabs_tray_grey"
-        app:navigationIcon="@drawable/abc_ic_clear_mtrl_alpha"
+        app:navigationIcon="@drawable/abc_ic_clear_material"
         app:subtitleTextColor="@android:color/white"
         app:title="@string/bookmark_add_folder"
         app:titleTextColor="@android:color/white" />
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
--- a/mobile/android/app/src/main/res/layout/bookmark_edit_with_full_page.xml
+++ b/mobile/android/app/src/main/res/layout/bookmark_edit_with_full_page.xml
@@ -13,17 +13,17 @@
 
     <android.support.v7.widget.Toolbar
         android:id="@+id/toolbar"
         android:layout_width="match_parent"
         android:layout_height="56dp"
         android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
         android:background="@color/text_and_tabs_tray_grey"
         android:minHeight="?actionBarSize"
-        app:navigationIcon="@drawable/abc_ic_clear_mtrl_alpha"
+        app:navigationIcon="@drawable/abc_ic_clear_material"
         app:subtitleTextColor="@android:color/white"
         app:titleTextColor="@android:color/white" />
 
     <ScrollView
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
         <LinearLayout
--- a/mobile/android/app/src/main/res/layout/bookmark_folder_select.xml
+++ b/mobile/android/app/src/main/res/layout/bookmark_folder_select.xml
@@ -12,17 +12,17 @@
     android:background="@android:color/white">
 
     <android.support.v7.widget.Toolbar
         android:id="@+id/toolbar"
         android:layout_width="match_parent"
         android:layout_height="?actionBarSize"
         android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
         android:background="@color/text_and_tabs_tray_grey"
-        app:navigationIcon="@drawable/abc_ic_ab_back_mtrl_am_alpha"
+        app:navigationIcon="@drawable/abc_ic_ab_back_material"
         app:subtitleTextColor="@android:color/white"
         app:title="@string/bookmark_select_folder" />
 
     <android.support.v7.widget.RecyclerView
         android:id="@+id/folder_recycler_view"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/GeckoCustomTabsService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/GeckoCustomTabsService.java
@@ -98,9 +98,19 @@ public class GeckoCustomTabsService exte
     }
 
     @Override
     protected Bundle extraCommand(String commandName, Bundle bundle) {
         Log.v(LOGTAG, "extraCommand()");
 
         return null;
     }
+
+    @Override
+    protected boolean requestPostMessageChannel(CustomTabsSessionToken sessionToken, Uri postMessageOrigin) {
+        return false;
+    }
+
+    @Override
+    protected int postMessage(CustomTabsSessionToken sessionToken, String message, Bundle extras) {
+        return RESULT_FAILURE_DISALLOWED;
+    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
+++ b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
@@ -228,17 +228,17 @@ public class GeckoPreferences
         }
     }
 
     private void updateHomeAsUpIndicator() {
         final ActionBar actionBar = getSupportActionBar();
         if (actionBar == null) {
             return;
         }
-        actionBar.setHomeAsUpIndicator(android.support.v7.appcompat.R.drawable.abc_ic_ab_back_mtrl_am_alpha);
+        actionBar.setHomeAsUpIndicator(android.support.v7.appcompat.R.drawable.abc_ic_ab_back_material);
     }
 
     /**
      * We only call this method for pre-HC versions of Android.
      */
     private void updateTitleForPrefsResource(int res) {
         // At present we only need to do this for non-leaf prefs views
         // and the locale switcher itself.
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabStripDividerItem.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabStripDividerItem.java
@@ -1,26 +1,26 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tabs;
 
-import org.mozilla.gecko.R;
-
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.support.v4.content.ContextCompat;
 import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.ViewUtils;
 import android.view.View;
 
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.util.ViewUtil;
+
 class TabStripDividerItem extends RecyclerView.ItemDecoration {
     private final int margin;
     private final int dividerWidth;
     private final int dividerHeight;
     private final int dividerPaddingBottom;
     private final Paint dividerPaint;
 
     TabStripDividerItem(Context context) {
@@ -34,17 +34,17 @@ class TabStripDividerItem extends Recycl
         dividerPaint.setStyle(Paint.Style.FILL_AND_STROKE);
     }
 
     /**
      * Return whether a divider should be drawn on the left side of the tab represented by
      * {@code view}.
      */
     private static boolean drawLeftDividerForView(View view, RecyclerView parent) {
-        final boolean isLTR = !ViewUtils.isLayoutRtl(parent);
+        final boolean isLTR = !ViewUtil.isLayoutRtl(parent);
         final int position = parent.getChildAdapterPosition(view);
         // No left divider if this is the leftmost tab or this tab is currently pressed.
         final boolean isLeftmostTab = isLTR ? position == 0 : position == parent.getAdapter().getItemCount() - 1;
         if (isLeftmostTab || view.isPressed()) {
             return false;
         }
 
         final int selectedPosition = ((TabStripView) parent).getPositionForSelectedTab();
@@ -66,17 +66,17 @@ class TabStripDividerItem extends Recycl
     }
 
     @Override
     public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
         final int position = parent.getChildAdapterPosition(view);
 
         // RTL positions start from the right, but offsets are still LTR since view is LTR.
         final int leftOffset, rightOffset;
-        if (ViewUtils.isLayoutRtl(parent)) {
+        if (ViewUtil.isLayoutRtl(parent)) {
             leftOffset = position == parent.getAdapter().getItemCount() - 1 ? 0 : margin;
             rightOffset = position == 0 ? 0 : margin;
         } else {
             leftOffset = position == 0 ? 0 : margin;
             rightOffset = position == parent.getAdapter().getItemCount() - 1 ? 0 : margin;
         }
 
         outRect.set(leftOffset, 0, rightOffset, 0);
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabStripView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabStripView.java
@@ -1,38 +1,38 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tabs;
 
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Tab;
-import org.mozilla.gecko.Tabs;
-import org.mozilla.gecko.util.ThreadUtils;
-
 import android.animation.Animator;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.LinearGradient;
 import android.graphics.Paint;
 import android.graphics.Shader;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.ViewUtils;
 import android.support.v7.widget.helper.ItemTouchHelper;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.animation.DecelerateInterpolator;
 
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.Tab;
+import org.mozilla.gecko.Tabs;
+import org.mozilla.gecko.util.ThreadUtils;
+import org.mozilla.gecko.util.ViewUtil;
+
 import java.util.ArrayList;
 import java.util.List;
 
 public class TabStripView extends RecyclerView
                           implements TabsTouchHelperCallback.DragListener {
     private static final int ANIM_TIME_MS = 200;
     private static final DecelerateInterpolator ANIM_INTERPOLATOR = new DecelerateInterpolator();
 
@@ -221,17 +221,17 @@ public class TabStripView extends Recycl
         if (w == oldw) {
             return;
         }
 
         // Gradient argb color stops.
         final int transparent = 0x0;
         final int inBetween = 0x11292C29;
         final int darkest = 0xDD292C29;
-        if (ViewUtils.isLayoutRtl(this)) {
+        if (ViewUtil.isLayoutRtl(this)) {
             fadingEdgePaint.setShader(new LinearGradient(0, 0, fadingEdgeSize, 0,
                     new int[] { darkest, inBetween, transparent },
                     new float[] { 0, 0.6f, 1.0f }, Shader.TileMode.CLAMP));
         } else {
             fadingEdgePaint.setShader(new LinearGradient(w - fadingEdgeSize, 0, w, 0,
                     new int[] { transparent, inBetween, darkest },
                     new float[] { 0, 0.4f, 1.0f }, Shader.TileMode.CLAMP));
         }
@@ -264,17 +264,17 @@ public class TabStripView extends Recycl
 
             return Math.max(0.0f, Math.min(strength, 1.0f));
         }
     }
 
     @Override
     public void draw(Canvas canvas) {
         super.draw(canvas);
-        final boolean isLTR = !ViewUtils.isLayoutRtl(this);
+        final boolean isLTR = !ViewUtil.isLayoutRtl(this);
         final float strength = getFadingEdgeStrength(isLTR);
         if (strength > 0.0f) {
             if (isLTR) {
                 final int w = getWidth();
                 canvas.drawRect(w - fadingEdgeSize, getTop(), w, getBottom(), fadingEdgePaint);
             } else {
                 canvas.drawRect(0, getTop(), fadingEdgeSize, getBottom(), fadingEdgePaint);
             }
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutItemView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutItemView.java
@@ -1,40 +1,40 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tabs;
 
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Tab;
-import org.mozilla.gecko.Tabs;
-import org.mozilla.gecko.icons.IconResponse;
-import org.mozilla.gecko.icons.Icons;
-import org.mozilla.gecko.widget.FaviconView;
-import org.mozilla.gecko.widget.HoverDelegateWithReset;
-import org.mozilla.gecko.widget.TabThumbnailWrapper;
-import org.mozilla.gecko.widget.TouchDelegateWithReset;
-import org.mozilla.gecko.widget.themed.ThemedRelativeLayout;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.support.v7.widget.ViewUtils;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.Checkable;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.Tab;
+import org.mozilla.gecko.Tabs;
+import org.mozilla.gecko.icons.IconResponse;
+import org.mozilla.gecko.icons.Icons;
+import org.mozilla.gecko.util.ViewUtil;
+import org.mozilla.gecko.widget.FaviconView;
+import org.mozilla.gecko.widget.HoverDelegateWithReset;
+import org.mozilla.gecko.widget.TabThumbnailWrapper;
+import org.mozilla.gecko.widget.TouchDelegateWithReset;
+import org.mozilla.gecko.widget.themed.ThemedRelativeLayout;
+
 import java.util.concurrent.Future;
 
 public class TabsLayoutItemView extends LinearLayout
                                 implements Checkable {
     private static final String LOGTAG = "Gecko" + TabsLayoutItemView.class.getSimpleName();
     private static final int[] STATE_CHECKED = { android.R.attr.state_checked };
     private boolean mChecked;
 
@@ -124,17 +124,17 @@ public class TabsLayoutItemView extends 
 
                 setTouchDelegate(new TouchDelegateWithReset(hitRect, mCloseButton));
                 setHoverDelegate(new HoverDelegateWithReset(hitRect, mCloseButton));
             }
         });
     }
 
     private Rect getHitRectRelatively(int targetHitArea) {
-        final boolean isRtl = ViewUtils.isLayoutRtl(this);
+        final boolean isRtl = ViewUtil.isLayoutRtl(this);
         final Rect hitRect = new Rect();
         hitRect.top = 0;
         hitRect.right = isRtl ? targetHitArea : getWidth();
         hitRect.left = isRtl ? 0 : getWidth() - targetHitArea;
         hitRect.bottom = targetHitArea;
         return hitRect;
     }
 
--- a/mobile/android/base/java/org/mozilla/gecko/util/ResourceDrawableUtils.java
+++ b/mobile/android/base/java/org/mozilla/gecko/util/ResourceDrawableUtils.java
@@ -5,38 +5,32 @@
 package org.mozilla.gecko.util;
 
 import android.content.Context;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
-import android.support.v7.widget.AppCompatDrawableManager;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.TextUtils;
 import android.util.Log;
 
-import org.mozilla.gecko.util.GeckoJarReader;
-import org.mozilla.gecko.util.ThreadUtils;
-import org.mozilla.gecko.util.UIAsyncTask;
-
 import java.io.InputStream;
 import java.net.URL;
 
 import static org.mozilla.gecko.util.BitmapUtils.getBitmapFromDataURI;
 import static org.mozilla.gecko.util.BitmapUtils.getResource;
 
 public class ResourceDrawableUtils {
     private static final String LOGTAG = "ResourceDrawableUtils";
 
     public static Drawable getDrawable(@NonNull final Context context,
                                        @DrawableRes final int drawableID) {
-        // TODO: upgrade this call to use AppCompatResources when upgrading to support library >= 24.2
-        // https://developer.android.com/reference/android/support/v7/content/res/AppCompatResources.html#getDrawable(android.content.Context,%20int)
-        return AppCompatDrawableManager.get().getDrawable(context, drawableID);
+        return AppCompatResources.getDrawable(context, drawableID);
     }
 
     public interface BitmapLoader {
         public void onBitmapFound(Drawable d);
     }
 
     public static void runOnBitmapFoundOnUiThread(final BitmapLoader loader, final Drawable d) {
         if (ThreadUtils.isOnUiThread()) {
--- a/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java
+++ b/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java
@@ -190,9 +190,19 @@ public class ViewUtil {
     @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
     private static void setTextDirectionRtlCompat17(TextView textView, boolean isRtl) {
         if (isRtl) {
             textView.setTextDirection(View.TEXT_DIRECTION_RTL);
         } else {
             textView.setTextDirection(View.TEXT_DIRECTION_LTR);
         }
     }
+
+    /**
+     * Get if the resolved layout direction is <em>right to left</em> or <em>left to right</em>.
+     * @param view View to get layout direction for
+     * @return <code>true</code> if the horizontal layout direction of this view is from <em>right to left</em><br>
+     *     <code>false</code> if the horizontal layout direction of this view is from <em>left to right</em>
+     */
+    public static boolean isLayoutRtl(final View view) {
+        return ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL;
+    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/widget/DefaultItemAnimatorBase.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/DefaultItemAnimatorBase.java
@@ -1,17 +1,18 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.widget;
 
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
 import android.support.annotation.NonNull;
-import android.support.v4.animation.AnimatorCompatHelper;
 import android.support.v4.view.ViewCompat;
 import android.support.v4.view.ViewPropertyAnimatorCompat;
 import android.support.v4.view.ViewPropertyAnimatorListener;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.SimpleItemAnimator;
 import android.view.View;
 
 import java.util.ArrayList;
@@ -36,16 +37,18 @@ import java.util.List;
  *       values before resetting the current animation, so this class does not provide the reset
  *       service itself.</li>
  *   <li>{@link #resetViewProperties(View)} is used to reset a view any time an animation ends or
  *       gets canceled - you should redefine resetViewProperties if the version here doesn't reset
  *       all of the properties you're animating.</li>
  * </ul>
  */
 public class DefaultItemAnimatorBase extends SimpleItemAnimator {
+    private static TimeInterpolator defaultInterpolator;
+
     private List<RecyclerView.ViewHolder> pendingRemovals = new ArrayList<>();
     private List<RecyclerView.ViewHolder> pendingAdditions = new ArrayList<>();
     private List<MoveInfo> pendingMoves = new ArrayList<>();
     private List<ChangeInfo> pendingChanges = new ArrayList<>();
 
     private List<List<RecyclerView.ViewHolder>> additionsList = new ArrayList<>();
     private List<List<MoveInfo>> movesList = new ArrayList<>();
     private List<List<ChangeInfo>> changesList = new ArrayList<>();
@@ -476,17 +479,20 @@ public class DefaultItemAnimatorBase ext
                     additionsList.remove(i);
                 }
             }
         }
         dispatchFinishedWhenDone();
     }
 
     protected void resetAnimation(RecyclerView.ViewHolder holder) {
-        AnimatorCompatHelper.clearInterpolator(holder.itemView);
+        if (defaultInterpolator == null) {
+            defaultInterpolator = new ValueAnimator().getInterpolator();
+        }
+        holder.itemView.animate().setInterpolator(defaultInterpolator);
         endAnimation(holder);
     }
 
     @Override
     public boolean isRunning() {
         return (!pendingAdditions.isEmpty() ||
                 !pendingChanges.isEmpty() ||
                 !pendingMoves.isEmpty() ||
--- a/mobile/android/base/java/org/mozilla/gecko/widget/GridSpacingDecoration.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/GridSpacingDecoration.java
@@ -3,19 +3,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.widget;
 
 import android.graphics.Rect;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.ViewUtils;
 import android.view.View;
 
+import org.mozilla.gecko.util.ViewUtil;
+
 /**
  * An ItemDecoration for a GridLayoutManager that provides fixed spacing (but not fixed padding)
  * to create fixed sized items, with no spacing on the outer edges of the outer items.
  * <p>
  * So, for example, if there are 2 columns and the spacing is s, then the first column gets a right
  * padding of s/2 and the second column gets a left paddding of s/2.  If there are three columns
  * then the first column gets a right padding of 2s/3, the second column gets left and right
  * paddings of s/3, and the third column gets a left padding of 2s/3.
@@ -37,16 +38,16 @@ public class GridSpacingDecoration exten
             return;
         }
 
         final GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
         final int spanCount = layoutManager.getSpanCount();
         // If we're RTL then column counts start from the right, but view is still LTR (i.e. offsets
         // are still LTR), so compute offsets using the LTR column position (also note that this
         // only works because offsets in a given column are the same for LTR and RTL layouts).
-        final int LTRColumn = ViewUtils.isLayoutRtl(parent) ? (spanCount - 1) - (position % spanCount) : position % spanCount;
+        final int LTRColumn = ViewUtil.isLayoutRtl(parent) ? (spanCount - 1) - (position % spanCount) : position % spanCount;
 
         final int columnLeftOffset = (int) (((float) LTRColumn / (float) spanCount) * horizontalSpacing);
         final int columnRightOffset = (int) (((float) (spanCount - (LTRColumn + 1)) / (float) spanCount) * horizontalSpacing);
 
         outRect.set(columnLeftOffset, verticalPadding, columnRightOffset, verticalPadding);
     }
 }
--- a/mobile/android/config/proguard/proguard-leanplum.cfg
+++ b/mobile/android/config/proguard/proguard-leanplum.cfg
@@ -333,16 +333,15 @@
 -keep class com.leanplum.utils.BitmapUtil { public private protected *; }
 
 -keep class com.leanplum.LocationManagerImplementation { *; }
 
 -keep class com.leanplum.messagetemplates.BaseMessageOptions { *; }
 
 #-dontwarn android.support.v7.**
 -keep class android.support.v7.app.AppCompatActivity
--keep class android.support.v7.app.ActionBarActivity
 #-keep interface android.support.v7.** { *; }
 
 -printmapping out.map
 -renamesourcefileattribute SourceFile
 -keepattributes SourceFile,LineNumberTable
 
 -optimizations !code/allocation/variable
deleted file mode 100644
--- a/mobile/android/thirdparty/com/leanplum/activities/LeanplumActionBarActivity.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2013, Leanplum, Inc. All rights reserved.
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.leanplum.activities;
-
-import android.annotation.SuppressLint;
-import android.content.res.Resources;
-import android.support.v7.app.ActionBarActivity;
-
-import com.leanplum.Leanplum;
-import com.leanplum.LeanplumActivityHelper;
-
-@SuppressLint("Registered")
-@SuppressWarnings("deprecation")
-public class LeanplumActionBarActivity extends ActionBarActivity {
-  private LeanplumActivityHelper helper;
-
-  private LeanplumActivityHelper getHelper() {
-    if (helper == null) {
-      helper = new LeanplumActivityHelper(this);
-    }
-    return helper;
-  }
-
-  @Override
-  protected void onPause() {
-    super.onPause();
-    getHelper().onPause();
-  }
-
-  @Override
-  protected void onStop() {
-    super.onStop();
-    getHelper().onStop();
-  }
-
-  @Override
-  protected void onResume() {
-    super.onResume();
-    getHelper().onResume();
-  }
-
-  @Override
-  public Resources getResources() {
-    if (Leanplum.isTestModeEnabled() || !Leanplum.isResourceSyncingEnabled()) {
-      return super.getResources();
-    }
-    return getHelper().getLeanplumResources(super.getResources());
-  }
-
-  @Override
-  public void setContentView(final int layoutResID) {
-    if (Leanplum.isTestModeEnabled() || !Leanplum.isResourceSyncingEnabled()) {
-      super.setContentView(layoutResID);
-      return;
-    }
-    getHelper().setContentView(layoutResID);
-  }
-}