Merge pull request #5385 from goblinr/MAPSME-144-ext-facebook-native-ads

[android] facebook native ads
This commit is contained in:
Aleksandr Zatsepin 2017-02-17 15:36:28 +03:00 committed by GitHub
commit 0c38a94364
17 changed files with 366 additions and 359 deletions

View file

@ -48,6 +48,9 @@ dependencies {
compile('com.crashlytics.sdk.android:crashlytics-ndk:1.1.2@aar') { transitive = true }
// 3-party
compile 'com.facebook.android:facebook-android-sdk:4.8.0'
compile('com.facebook.android:audience-network-sdk:4.8.0') {
exclude group: 'com.google.android.gms'
}
compile 'com.google.code.gson:gson:2.6.1'
compile 'com.pushwoosh:pushwoosh:4.10.7'
compile 'com.my.tracker:mytracker-sdk:1.3.5'

View file

@ -24,20 +24,12 @@ void InjectMetadata(JNIEnv * env, jclass const clazz, jobject const mapObject, f
}
}
jobject CreateBanner(JNIEnv * env, string const & id, string const & titleId,
string const & messageId, string const & iconId,
string const & url, vector<string> const & sourceTypes)
jobject CreateBanner(JNIEnv * env, string const & id)
{
auto const types = strings::JoinStrings(sourceTypes, ", ");
static jmethodID const bannerCtorId = jni::GetConstructorID(
env, g_bannerClazz,
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;)V");
static jmethodID const bannerCtorId =
jni::GetConstructorID(env, g_bannerClazz, "(Ljava/lang/String;)V");
return env->NewObject(g_bannerClazz, bannerCtorId, jni::ToJavaString(env, id),
jni::ToJavaString(env, titleId), jni::ToJavaString(env, messageId),
jni::ToJavaString(env, iconId), jni::ToJavaString(env, url),
jni::ToJavaString(env, types));
return env->NewObject(g_bannerClazz, bannerCtorId, jni::ToJavaString(env, id));
}
jobject CreateMapObject(JNIEnv * env, int mapObjectType, string const & title,
@ -65,9 +57,7 @@ jobject CreateMapObject(JNIEnv * env, place_page::Info const & info)
{
jobject jbanner = nullptr;
if (info.HasBanner())
jbanner = CreateBanner(env, info.GetBannerId(), info.GetBannerTitleId(),
info.GetBannerMessageId(), info.GetBannerIconId(),
info.GetBannerUrl(), info.GetRawTypes());
jbanner = CreateBanner(env, info.GetBanner().m_bannerId);
if (info.IsBookmark())
{
// public Bookmark(@IntRange(from = 0) int categoryId, @IntRange(from = 0) int bookmarkId,

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/black_24"/>
<corners android:radius="@dimen/cardview_default_radius"/>
<padding
android:left="@dimen/cardview_default_radius"
android:right="@dimen/cardview_default_radius"/>
</shape>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:color="@color/warm_gray"
android:width="1dp"/>
<corners android:radius="@dimen/cardview_default_radius"/>
<padding
android:left="@dimen/margin_half"
android:right="@dimen/margin_half"
android:top="@dimen/placepage_banner_button_margin_top"
android:bottom="@dimen/placepage_banner_button_margin_top"/>
</shape>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:color="@color/warm_gray_night"
android:width="1dp"/>
<corners android:radius="@dimen/cardview_default_radius"/>
<padding
android:left="@dimen/margin_half"
android:right="@dimen/margin_half"
android:top="@dimen/placepage_banner_button_margin_top"
android:bottom="@dimen/placepage_banner_button_margin_top"/>
</shape>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/white_24"/>
<corners android:radius="@dimen/cardview_default_radius"/>
<padding
android:left="@dimen/cardview_default_radius"
android:right="@dimen/cardview_default_radius"/>
</shape>

View file

@ -4,76 +4,109 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/placepage_banner_height"
android:paddingLeft="@dimen/margin_base"
android:paddingRight="@dimen/margin_base"
android:paddingTop="@dimen/margin_half"
android:background="?bannerBackground"
android:clipToPadding="false"
tools:layout_height="wrap_content">
<ImageView
android:id="@+id/iv__banner_icon"
android:layout_width="@dimen/placepage_banner_icon_size"
android:layout_height="@dimen/placepage_banner_icon_size"
android:layout_marginTop="@dimen/margin_half_plus"
android:layout_marginLeft="@dimen/margin_base"
android:layout_marginStart="@dimen/margin_base"
android:layout_marginRight="@dimen/margin_base"
android:layout_marginEnd="@dimen/margin_base"
android:scaleType="centerCrop"
android:visibility="gone"
tools:src="@drawable/about_logo"
tools:visibility="visible"
tools:layout_width="@dimen/placepage_banner_icon_size_full"
tools:layout_height="@dimen/placepage_banner_icon_size_full"
tools:layout_marginRight="0dp"
tools:layout_marginEnd="0dp"
tools:layout_marginTop="@dimen/margin_base"/>
<TextView
android:id="@+id/tv__banner_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_base"
android:layout_marginLeft="@dimen/margin_base"
android:layout_marginRight="@dimen/margin_base"
android:layout_toEndOf="@id/iv__banner_icon"
android:layout_toRightOf="@id/iv__banner_icon"
android:maxLines="1"
android:minLines="1"
android:textAppearance="@style/MwmTextAppearance.Body3.Primary"
android:fontFamily="@string/robotoMedium"
tools:paddingTop="0dp"
tools:text="Закажи одежду в интернет-магазине Wildberries."
tools:targetApi="jelly_bean"
tools:maxLines="2"/>
<TextView
android:id="@+id/tv__banner_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv__banner_title"
android:layout_marginTop="@dimen/margin_half_plus"
android:layout_marginLeft="@dimen/margin_base"
android:layout_marginRight="@dimen/margin_base"
android:layout_toEndOf="@id/iv__banner_icon"
android:layout_toRightOf="@id/iv__banner_icon"
android:textAppearance="@style/MwmTextAppearance.Body4"
android:visibility="gone"
tools:text="Бесплатная курьерская доставка по России!\n\nКоллекции женской, мужской и детской одежды, обуви,
а также товары для дома и спорта. Цены."
tools:visibility="visible"/>
<TextView
android:id="@+id/tv__banner"
android:id="@+id/tv__action_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv__banner_message"
android:layout_marginBottom="@dimen/margin_base"
android:layout_marginTop="@dimen/margin_half_plus"
android:layout_marginLeft="@dimen/margin_base"
android:layout_marginRight="@dimen/margin_base"
android:layout_toEndOf="@id/iv__banner_icon"
android:layout_toRightOf="@id/iv__banner_icon"
android:textAppearance="@style/MwmTextAppearance.Banner"
android:text="@string/advertisement"
android:visibility="gone"
android:layout_height="@dimen/margin_base_plus"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginLeft="@dimen/margin_half"
android:layout_marginStart="@dimen/margin_half"
android:textSize="@dimen/text_size_body_4"
android:textColor="?warmGray"
android:background="?adsActionBackground"
android:foreground="?clickableBackground"
android:visibility="visible"
tools:text="Заказать"
tools:visibility="visible"/>
<RelativeLayout
android:id="@+id/data_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/tv__action_small"
android:layout_toStartOf="@id/tv__action_small"
android:layout_marginBottom="@dimen/margin_half">
<ImageView
android:id="@+id/iv__banner_icon"
android:layout_width="@dimen/placepage_banner_icon_size"
android:layout_height="@dimen/placepage_banner_icon_size"
android:layout_marginRight="@dimen/margin_half"
android:layout_marginEnd="@dimen/margin_half"
android:scaleType="centerCrop"
android:visibility="gone"
tools:src="@drawable/about_logo"
tools:visibility="visible"/>
<LinearLayout
android:id="@+id/banner_title"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/iv__banner_icon"
android:layout_toRightOf="@id/iv__banner_icon"
android:gravity="center_vertical">
<TextView
android:id="@+id/tv__ads"
android:layout_width="wrap_content"
android:layout_height="@dimen/margin_half_plus"
android:layout_marginRight="@dimen/margin_quarter"
android:layout_marginEnd="@dimen/margin_quarter"
android:textSize="@dimen/text_size_banner"
android:textColor="?adsText"
android:gravity="center"
android:background="?adsBackground"
android:text="@string/advertisement"/>
<TextView
android:id="@+id/tv__banner_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:minLines="1"
android:textAppearance="@style/MwmTextAppearance.Body4"
android:textColor="?textBannerTitle"
android:fontFamily="@string/robotoMedium"
android:ellipsize="end"
tools:text="Закажи одежду в интернет-магазине Wildberries."
tools:targetApi="jelly_bean"/>
</LinearLayout>
<TextView
android:id="@+id/tv__banner_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/MwmTextAppearance.Body4"
android:maxLines="3"
android:ellipsize="end"
tools:text="Бесплатная курьерская доставка по России!\n\nКоллекции женской, мужской и детской одежды, обуви,
а также товары для дома и спорта. Цены."
tools:maxLines="5"
android:layout_below="@+id/banner_title"
android:layout_toRightOf="@+id/iv__banner_icon"
android:layout_toEndOf="@+id/iv__banner_icon"/>
</RelativeLayout>
<TextView
android:id="@+id/tv__action_large"
android:layout_width="match_parent"
android:layout_height="@dimen/placepage_banner_button_height"
android:layout_below="@id/data_frame"
android:layout_marginLeft="@dimen/neg_margin_base"
android:layout_marginRight="@dimen/neg_margin_base"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:background="?bannerButtonBackground"
android:foreground="?clickableBackground"
android:gravity="center"
android:visibility="gone"
tools:text="Заказать"
tools:visibility="visible"/>
</RelativeLayout>

View file

@ -21,11 +21,17 @@
<color name="black_secondary">#8A000000</color> <!-- 54% black -->
<color name="black_lightest">#61000000</color> <!-- 38% black -->
<color name="black_8">#14000000</color> <!-- 8% black -->
<color name="black_24">#3D000000</color> <!-- 24% black -->
<color name="black_60">#99000000</color> <!-- 24% black -->
<color name="white_primary">#FFFFFFFF</color> <!-- 100% white -->
<color name="white_secondary">#B3FFFFFF</color> <!-- 70% white -->
<color name="white_lightest">#4CFFFFFF</color> <!-- 50% white -->
<color name="white_8">#14FFFFFF</color> <!-- 8% white -->
<color name="white_24">#3DFFFFFF</color> <!-- 24% black -->
<color name="white_60">#99FFFFFF</color> <!-- 24% black -->
<color name="warm_gray">#FF999691</color>
<color name="warm_gray_night">#FF999691</color>
<color name="icon_tint">#FF757575</color>
<color name="icon_tint_night">#FFC4C6C7</color>
@ -151,9 +157,13 @@
<color name="bg_brand_opentable_pressed">#FFFC5965</color>
<!-- Banner colors-->
<color name="bg_banner_color">#FFF8E1</color>
<color name="bg_banner_color_night">#555A5A</color>
<color name="bg_banner_color">#FFFFFBF3</color>
<color name="bg_banner_color_night">#FF555A5A</color>
<color name="text_banner_color">#28000000</color>
<color name="text_banner_color_night">#28FFFFFF</color>
<color name="bg_banner_button_color">#FFF3EBDA</color>
<color name="bg_banner_button_color_night">#4CFFFAE1</color>
<color name="text_ads_color">#FFFFFBF2</color>
<color name="text_ads_color_night">#FFFFFBF2</color>
</resources>

View file

@ -164,9 +164,10 @@
<dimen name="placepage_margin_rating">20dp</dimen>
<!-- Banner-->
<dimen name="placepage_banner_height">46dp</dimen>
<dimen name="placepage_banner_icon_size">22dp</dimen>
<dimen name="placepage_banner_icon_size_full">40dp</dimen>
<dimen name="placepage_banner_height">64dp</dimen>
<dimen name="placepage_banner_icon_size">40dp</dimen>
<dimen name="placepage_banner_button_height">36dp</dimen>
<dimen name="placepage_banner_button_margin_top">5dp</dimen>
<!-- Place page taxi-->
<dimen name="placepage_taxi_button_min_width">96dp</dimen>

View file

@ -70,11 +70,18 @@
<attr name="bannerText" format="color"/>
<attr name="bannerBackground" format="color"/>
<attr name="bannerButtonBackground" format="color"/>
<attr name="adsBackground" format="reference"/>
<attr name="adsText" format="color"/>
<attr name="adsActionBackground" format="reference"/>
<attr name="textBannerTitle" format="color"/>
<attr name="steadyIconTint" format="color"/>
<attr name="steadyIconBackground" format="reference"/>
<attr name="activeIconTint" format="color"/>
<attr name="activeIconBackground" format="reference"/>
<attr name="warmGray" format="color"/>
</declare-styleable>
<declare-styleable name="ThemeAttrs.NavButtons">

View file

@ -86,11 +86,18 @@
<item name="bannerText">@color/text_banner_color</item>
<item name="bannerBackground">@color/bg_banner_color</item>
<item name="bannerButtonBackground">@color/bg_banner_button_color</item>
<item name="adsBackground">@drawable/bg_ads</item>
<item name="adsText">@color/text_ads_color</item>
<item name="adsActionBackground">@drawable/bg_ads_action</item>
<item name="textBannerTitle">@color/black_60</item>
<item name="steadyIconTint">@color/black_secondary</item>
<item name="steadyIconBackground">@drawable/bg_steady_icon</item>
<item name="activeIconTint">@color/bg_cards</item>
<item name="activeIconBackground">@drawable/bg_active_icon</item>
<item name="warmGray">@color/warm_gray</item>
</style>
<!-- Night theme -->
@ -180,10 +187,17 @@
<item name="bannerText">@color/text_banner_color_night</item>
<item name="bannerBackground">@color/bg_banner_color_night</item>
<item name="bannerButtonBackground">@color/bg_banner_button_color_night</item>
<item name="adsBackground">@drawable/bg_ads_night</item>
<item name="adsText">@color/text_ads_color_night</item>
<item name="adsActionBackground">@drawable/bg_ads_action_night</item>
<item name="textBannerTitle">@color/white_60</item>
<item name="steadyIconTint">@color/white_secondary</item>
<item name="steadyIconBackground">@drawable/bg_steady_icon_night</item>
<item name="activeIconTint">@color/bg_cards_night</item>
<item name="activeIconBackground">@drawable/bg_active_icon_night</item>
<item name="warmGray">@color/warm_gray_night</item>
</style>
</resources>

View file

@ -89,7 +89,6 @@ import com.mapswithme.maps.widget.placepage.PlacePageView.State;
import com.mapswithme.util.Animations;
import com.mapswithme.util.BottomSheetHelper;
import com.mapswithme.util.InputUtils;
import com.mapswithme.util.NetworkPolicy;
import com.mapswithme.util.ThemeUtils;
import com.mapswithme.util.UiUtils;
import com.mapswithme.util.Utils;
@ -1597,7 +1596,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
updateSearchBar();
}
mPlacePage.refreshViews(null);
mPlacePage.refreshViews();
}
private void adjustCompassAndTraffic(int offsetY)
@ -1654,7 +1653,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
@Override
public void showNavigation(boolean show)
{
mPlacePage.refreshViews(null);
mPlacePage.refreshViews();
if (mNavigationController != null)
mNavigationController.show(show);
refreshFade();

View file

@ -6,7 +6,7 @@ import android.support.annotation.Nullable;
public final class Banner implements Parcelable
{
public static final Banner EMPTY = new Banner(null, null, null, null, null, null);
public static final Banner EMPTY = new Banner((String) null);
public static final Creator<Banner> CREATOR = new Creator<Banner>()
{
@ -25,36 +25,15 @@ public final class Banner implements Parcelable
@Nullable
private final String mId;
@Nullable
private final String mTitle;
@Nullable
private final String mMessage;
@Nullable
private final String mIconUrl;
@Nullable
private final String mUrl;
@Nullable
private final String mTypes;
public Banner(@Nullable String id, @Nullable String title, @Nullable String message,
@Nullable String iconUrl, @Nullable String url, @Nullable String types)
public Banner(@Nullable String id)
{
mId = id;
mTitle = title;
mMessage = message;
mIconUrl = iconUrl;
mUrl = url;
mTypes = types;
}
protected Banner(Parcel in)
{
mId = in.readString();
mTitle = in.readString();
mMessage = in.readString();
mIconUrl = in.readString();
mUrl = in.readString();
mTypes = in.readString();
}
@Nullable
@ -63,36 +42,6 @@ public final class Banner implements Parcelable
return mId;
}
@Nullable
public String getTitle()
{
return mTitle;
}
@Nullable
public String getMessage()
{
return mMessage;
}
@Nullable
public String getIconUrl()
{
return mIconUrl;
}
@Nullable
public String getUrl()
{
return mUrl;
}
@Nullable
public String getTypes()
{
return mTypes;
}
@Override
public int describeContents()
{
@ -103,11 +52,6 @@ public final class Banner implements Parcelable
public void writeToParcel(Parcel dest, int flags)
{
dest.writeString(mId);
dest.writeString(mTitle);
dest.writeString(mMessage);
dest.writeString(mIconUrl);
dest.writeString(mUrl);
dest.writeString(mTypes);
}
@Override
@ -115,11 +59,6 @@ public final class Banner implements Parcelable
{
return "Banner{" +
"mId='" + mId + '\'' +
", mTitle='" + mTitle + '\'' +
", mMessage='" + mMessage + '\'' +
", mIconUrl='" + mIconUrl + '\'' +
", mUrl='" + mUrl + '\'' +
", mTypes='" + mTypes + '\'' +
'}';
}
}

View file

@ -1,40 +1,49 @@
package com.mapswithme.maps.widget.placepage;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.res.Resources;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.mapswithme.maps.MwmApplication;
import com.facebook.ads.Ad;
import com.facebook.ads.AdError;
import com.facebook.ads.AdListener;
import com.facebook.ads.AdSettings;
import com.facebook.ads.NativeAd;
import com.mapswithme.maps.BuildConfig;
import com.mapswithme.maps.R;
import com.mapswithme.maps.bookmarks.data.Banner;
import com.mapswithme.util.ConnectionState;
import com.mapswithme.util.CrashlyticsUtils;
import com.mapswithme.util.Config;
import com.mapswithme.util.UiUtils;
import com.mapswithme.util.log.Logger;
import com.mapswithme.util.log.LoggerFactory;
import com.mapswithme.util.statistics.Statistics;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.mapswithme.util.SharedPropertiesUtils.isShowcaseSwitchedOnLocal;
final class BannerController implements View.OnClickListener
final class BannerController implements AdListener
{
private static final int DURATION_DEFAULT =
MwmApplication.get().getResources().getInteger(R.integer.anim_default);
private static final Logger LOGGER = LoggerFactory.INSTANCE
.getLogger(LoggerFactory.Type.MISC);
private static final String TAG = BannerController.class.getName();
private static boolean isTouched(@Nullable View view, @NonNull MotionEvent event)
{
return view != null && !UiUtils.isHidden(view) && UiUtils.isViewTouched(event, view);
}
@Nullable
private Banner mBanner;
@Nullable
private OnBannerClickListener mListener;
@NonNull
private final View mFrame;
@ -45,137 +54,98 @@ final class BannerController implements View.OnClickListener
@Nullable
private final TextView mMessage;
@Nullable
private final View mAdMarker;
private final TextView mActionSmall;
@Nullable
private final TextView mActionLarge;
private final float mCloseFrameHeight;
private final float mCloseIconSize;
private final float mOpenIconSize;
private final float mMarginBase;
private final float mMarginHalfPlus;
@NonNull
private final Resources mResources;
@Nullable
private NativeAd mNativeAd;
private boolean mOpened = false;
@Nullable
private ValueAnimator mIconAnimator;
BannerController(@NonNull View bannerView, @Nullable OnBannerClickListener listener)
BannerController(@NonNull View bannerView)
{
mFrame = bannerView;
mFrame.setOnClickListener(this);
mListener = listener;
mResources = mFrame.getResources();
mCloseFrameHeight = mResources.getDimension(R.dimen.placepage_banner_height);
mCloseIconSize = mResources.getDimension(R.dimen.placepage_banner_icon_size);
mOpenIconSize = mResources.getDimension(R.dimen.placepage_banner_icon_size_full);
mMarginBase = mResources.getDimension(R.dimen.margin_base);
mMarginHalfPlus = mResources.getDimension(R.dimen.margin_half_plus);
Resources resources = mFrame.getResources();
mCloseFrameHeight = resources.getDimension(R.dimen.placepage_banner_height);
mIcon = (ImageView) bannerView.findViewById(R.id.iv__banner_icon);
mTitle = (TextView) bannerView.findViewById(R.id.tv__banner_title);
mMessage = (TextView) bannerView.findViewById(R.id.tv__banner_message);
mAdMarker = bannerView.findViewById(R.id.tv__banner);
mActionSmall = (TextView) bannerView.findViewById(R.id.tv__action_small);
mActionLarge = (TextView) bannerView.findViewById(R.id.tv__action_large);
}
void updateData(@Nullable Banner banner)
{
UiUtils.hide(mFrame);
mBanner = banner;
boolean showBanner = banner != null && ConnectionState.isConnected()
&& isShowcaseSwitchedOnLocal();
UiUtils.showIf(showBanner, mFrame);
if (!showBanner)
if (mBanner == null || TextUtils.isEmpty(mBanner.getId()) || !isShowcaseSwitchedOnLocal()
|| Config.getAdForbidden())
return;
loadIcon(banner);
setLabelSafely(mTitle, mBanner.getTitle());
setLabelSafely(mMessage, mBanner.getMessage());
if (UiUtils.isLandscape(mFrame.getContext()))
open();
else
Statistics.INSTANCE.trackEvent(Statistics.EventName.PP_BANNER_SHOW,
Statistics.params()
.add("tags:", mBanner.getTypes())
.add("banner:", mBanner.getId())
.add("state:", "0"));
if (BuildConfig.DEBUG)
{
AdSettings.addTestDevice("c36b141fff9e11866d8cf9c601d2b7e0");
AdSettings.addTestDevice("189055740336d9d2687f41a775eaf867");
AdSettings.addTestDevice("36dd04f33c4cf92e3b7d21e9a5a9d985");
AdSettings.addTestDevice("b39d3c00580d17b291ff4e161a423525");
AdSettings.addTestDevice("51bae0d8b2ba8290659840f9098e3026");
AdSettings.addTestDevice("583a068aa7293c6743855343251e1fad");
AdSettings.addTestDevice("c1c9f7f1c06b8c2c4e15607e5c766cb3");
}
mNativeAd = new NativeAd(mFrame.getContext(), mBanner.getId());
mNativeAd.setAdListener(BannerController.this);
mNativeAd.loadAd(EnumSet.of(NativeAd.MediaCacheFlag.ICON));
UiUtils.show(mFrame);
}
private void setLabelSafely(@Nullable TextView label, @Nullable String labelId)
{
if (label == null)
return;
if (TextUtils.isEmpty(labelId))
{
CrashlyticsUtils.logException(new Resources.NotFoundException("An empty string id obtained for: "
+ mBanner));
return;
}
try
{
String packageName = mFrame.getContext().getPackageName();
String value = mResources.getString(mResources.getIdentifier(labelId, "string", packageName));
label.setText(value);
}
catch (Resources.NotFoundException e)
{
CrashlyticsUtils.logException(new IllegalStateException("Unknown banner is found: " + mBanner, e));
}
}
boolean isShowing()
boolean isBannerVisible()
{
return !UiUtils.isHidden(mFrame);
}
void open()
{
if (!isShowing() || mBanner == null || mOpened)
if (!isBannerVisible() || mNativeAd == null || mBanner == null || mOpened)
return;
mOpened = true;
setFrameHeight(WRAP_CONTENT);
setIconParams(mOpenIconSize, 0, mMarginBase, new Runnable()
{
@Override
public void run()
{
loadIcon(mBanner);
}
});
UiUtils.show(mMessage, mAdMarker);
loadIcon(mNativeAd);
if (mMessage != null)
mMessage.setMaxLines(Integer.MAX_VALUE);
if (mTitle != null)
mTitle.setMaxLines(2);
if (mActionSmall != null)
UiUtils.hide(mActionSmall);
if (mActionLarge != null)
UiUtils.show(mActionLarge);
Statistics.INSTANCE.trackEvent(Statistics.EventName.PP_BANNER_SHOW,
Statistics.params()
.add("tags:", mBanner.getTypes())
.add("banner:", mBanner.getId())
.add("state:", "1"));
}
boolean close()
{
if (!isShowing() || mBanner == null || !mOpened)
if (!isBannerVisible() || mNativeAd == null || mBanner == null || !mOpened)
return false;
mOpened = false;
setFrameHeight((int) mCloseFrameHeight);
setIconParams(mCloseIconSize, mMarginBase, mMarginHalfPlus, new Runnable()
{
@Override
public void run()
{
loadIcon(mBanner);
}
});
UiUtils.hide(mMessage, mAdMarker);
UiUtils.hide(mIcon);
if (mMessage != null)
mMessage.setMaxLines(3);
if (mTitle != null)
mTitle.setMaxLines(1);
mFrame.setOnClickListener(null);
if (mActionSmall != null)
UiUtils.show(mActionSmall);
if (mActionLarge != null)
UiUtils.hide(mActionLarge);
return true;
}
@ -192,112 +162,80 @@ final class BannerController implements View.OnClickListener
mFrame.setLayoutParams(lp);
}
private void setIconParams(final float size, final float marginRight, final float marginTop,
final @Nullable Runnable listener)
{
if (mIcon == null || UiUtils.isHidden(mIcon))
{
if (listener != null)
listener.run();
return;
}
if (mIconAnimator != null)
mIconAnimator.cancel();
final ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) mIcon.getLayoutParams();
final float startSize = lp.height;
final float startRight = lp.rightMargin;
final float startTop = lp.topMargin;
mIconAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
if (mIconAnimator == null)
{
if (listener != null)
listener.run();
return;
}
mIconAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
float t = (float) animation.getAnimatedValue();
int newSize = (int) (startSize + t * (size - startSize));
lp.height = newSize;
lp.width = newSize;
lp.rightMargin = (int) (startRight + t * (marginRight - startRight));
lp.topMargin = (int) (startTop + t * (marginTop - startTop));
mIcon.setLayoutParams(lp);
}
});
mIconAnimator.addListener(new UiUtils.SimpleAnimatorListener()
{
@Override
public void onAnimationEnd(Animator animation)
{
if (listener != null)
listener.run();
}
});
mIconAnimator.setDuration(DURATION_DEFAULT);
mIconAnimator.start();
}
private void loadIcon(@NonNull Banner banner)
private void loadIcon(@NonNull NativeAd nativeAd)
{
if (mIcon == null)
return;
if (TextUtils.isEmpty(banner.getIconUrl()))
{
UiUtils.hide(mIcon);
return;
}
Glide.with(mIcon.getContext())
.load(banner.getIconUrl())
.centerCrop()
.listener(new RequestListener<String, GlideDrawable>()
{
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target,
boolean isFirstResource)
{
UiUtils.hide(mIcon);
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model,
Target<GlideDrawable> target, boolean isFromMemoryCache,
boolean isFirstResource)
{
UiUtils.show(mIcon);
return false;
}
})
.into(mIcon);
UiUtils.show(mIcon);
NativeAd.Image icon = nativeAd.getAdIcon();
NativeAd.downloadAndDisplayImage(icon, mIcon);
}
@Override
public void onClick(View v)
public void onError(Ad ad, AdError adError)
{
if (mListener == null || mBanner == null)
UiUtils.hide(mFrame);
LOGGER.e(TAG, adError.getErrorMessage());
}
@Override
public void onAdLoaded(Ad ad)
{
if (mNativeAd == null || mBanner == null)
return;
if (mOpened)
mListener.onBannerClick(mBanner);
if (mTitle != null)
mTitle.setText(mNativeAd.getAdTitle());
if (mMessage != null)
mMessage.setText(mNativeAd.getAdBody());
if (mActionSmall != null)
mActionSmall.setText(mNativeAd.getAdCallToAction());
if (mActionLarge != null)
mActionLarge.setText(mNativeAd.getAdCallToAction());
List<View> clickableViews = new ArrayList<>();
clickableViews.add(mTitle);
clickableViews.add(mActionSmall);
clickableViews.add(mActionLarge);
mNativeAd.registerViewForInteraction(mFrame, clickableViews);
if (UiUtils.isLandscape(mFrame.getContext()))
{
if (!mOpened)
open();
else
loadIcon(mNativeAd);
}
else if (!mOpened)
{
close();
Statistics.INSTANCE.trackEvent(Statistics.EventName.PP_BANNER_SHOW,
Statistics.params()
.add("banner:", mBanner.getId())
.add("state:", "0"));
}
else
{
loadIcon(mNativeAd);
}
}
@Override
public void onAdClicked(Ad ad)
{
if (mBanner == null)
return;
Statistics.INSTANCE.trackEvent(Statistics.EventName.PP_BANNER_CLICK,
Statistics.params()
.add("tags:", mBanner.getTypes())
.add("banner:", mBanner.getId())
.add("state:", mOpened ? "1" : "0"));
}
interface OnBannerClickListener
boolean isActionButtonTouched(@NonNull MotionEvent event)
{
void onBannerClick(@NonNull Banner banner);
return isTouched(mActionSmall, event) || isTouched(mActionLarge, event)
|| isTouched(mTitle, event);
}
}

View file

@ -99,7 +99,8 @@ class BottomPlacePageAnimationController extends BasePlacePageAnimationControlle
break;
case MotionEvent.ACTION_UP:
final boolean isInside = UiUtils.isViewTouched(event, mDetailsScroll);
if (isInside && mIsGestureStartedInsideView)
final boolean isBannerTouch = mPlacePage.isBannerTouched(event);
if (isInside && !isBannerTouch && mIsGestureStartedInsideView)
mGestureDetector.onTouchEvent(event);
break;
}

View file

@ -43,7 +43,6 @@ import com.mapswithme.maps.MwmActivity;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.maps.api.ParsedMwmRequest;
import com.mapswithme.maps.bookmarks.data.Banner;
import com.mapswithme.maps.bookmarks.data.Bookmark;
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
import com.mapswithme.maps.bookmarks.data.DistanceAndAzimut;
@ -98,7 +97,6 @@ public class PlacePageView extends RelativeLayout
LineCountTextView.OnLineCountCalculatedListener,
RecyclerClickListener,
NearbyAdapter.OnItemClickListener,
BannerController.OnBannerClickListener,
BottomPlacePageAnimationController.OnBannerOpenListener,
EditBookmarkFragment.EditBookmarkListener
{
@ -356,7 +354,7 @@ public class PlacePageView extends RelativeLayout
View bannerView = findViewById(R.id.banner);
if (bannerView != null)
mBannerController = new BannerController(bannerView, this);
mBannerController = new BannerController(bannerView);
mButtons = new PlacePageButtons(this, ppButtons, new PlacePageButtons.ItemListener()
{
@ -744,13 +742,6 @@ public class PlacePageView extends RelativeLayout
});
}
@Override
public void onBannerClick(@NonNull Banner banner)
{
if (!TextUtils.isEmpty(banner.getUrl()))
followUrl(banner.getUrl());
}
@Override
public void onNeedOpenBanner()
{
@ -848,7 +839,7 @@ public class PlacePageView extends RelativeLayout
if (!mIsDocked && !mIsFloating)
{
// After ninepatch background is set from code, all paddings are lost, so we need to restore it later.
int bottom = mBannerController != null && mBannerController.isShowing()
int bottom = mBannerController != null && mBannerController.isBannerVisible()
? 0 : (int) getResources().getDimension(R.dimen.margin_base);
int left = mPreview.getPaddingLeft();
int right = mPreview.getPaddingRight();
@ -941,13 +932,28 @@ public class PlacePageView extends RelativeLayout
return mMapObject != null && (isSponsored() || mMapObject.getBanner() != null);
}
public void refreshViews(@Nullable NetworkPolicy policy)
private void refreshViews(@NonNull NetworkPolicy policy)
{
if (mMapObject == null)
return;
refreshPreview(policy);
refreshViewsInternal();
}
public void refreshViews()
{
if (mMapObject == null)
return;
refreshPreview();
refreshViewsInternal();
}
private void refreshViewsInternal()
{
refreshDetails();
final Location loc = LocationHelper.INSTANCE.getSavedLocation();
switch (mMapObject.getMapObjectType())
@ -1004,7 +1010,18 @@ public class PlacePageView extends RelativeLayout
}
}
private void refreshPreview(@Nullable NetworkPolicy policy)
private void refreshPreview(@NonNull NetworkPolicy policy)
{
if (mBannerController != null)
{
mBannerController.updateData(policy.сanUseNetwork()
? mMapObject.getBanner() : null);
}
refreshPreview();
}
private void refreshPreview()
{
UiUtils.setTextAndHideIfEmpty(mTvTitle, mMapObject.getTitle());
if (mToolbar != null)
@ -1025,12 +1042,6 @@ public class PlacePageView extends RelativeLayout
mTvSponsoredPrice.setText(mSponsoredPrice);
UiUtils.showIf(!isPriceEmpty, mTvSponsoredPrice);
}
if (mBannerController != null)
{
mBannerController.updateData(policy != null && policy.сanUseNetwork()
? mMapObject.getBanner() : null);
}
}
private boolean isSponsored()
@ -1622,4 +1633,9 @@ public class PlacePageView extends RelativeLayout
{
setMapObject(BookmarkManager.INSTANCE.getBookmark(categoryId, bookmarkId), true, null);
}
public boolean isBannerTouched(@NonNull MotionEvent event)
{
return mBannerController != null && mBannerController.isActionButtonTouched(event);
}
}

View file

@ -36,6 +36,7 @@ public final class Config
private static final String KEY_MISC_USE_MOBILE_DATA = "UseMobileData";
private static final String KEY_MISC_USE_MOBILE_DATA_TIMESTAMP = "UseMobileDataTimestamp";
private static final String KEY_MISC_USE_MOBILE_DATA_ROAMING = "UseMobileDataRoaming";
private static final String KEY_MISC_AD_FORBIDDEN = "AdForbidden";
private Config() {}
@ -383,6 +384,16 @@ public final class Config
setBool(KEY_MISC_USE_MOBILE_DATA_ROAMING, ConnectionState.isInRoaming());
}
public static boolean getAdForbidden()
{
return getBool(KEY_MISC_AD_FORBIDDEN, false);
}
public static void setAdForbidden(boolean value)
{
setBool(KEY_MISC_AD_FORBIDDEN, value);
}
public static void setMobileDataTimeStamp(long timestamp)
{
setLong(KEY_MISC_USE_MOBILE_DATA_TIMESTAMP, timestamp);
@ -398,6 +409,7 @@ public final class Config
return getBool(KEY_MISC_USE_MOBILE_DATA_ROAMING, false);
}
private static native boolean nativeGetBoolean(String name, boolean defaultValue);
private static native void nativeSetBoolean(String name, boolean value);
private static native int nativeGetInt(String name, int defaultValue);