forked from organicmaps/organicmaps
Dynamic bottom ad items.
This commit is contained in:
parent
eb9abbe0c3
commit
83189d1d47
8 changed files with 418 additions and 0 deletions
27
android/res/layout/item_bottom_toolbar.xml
Normal file
27
android/res/layout/item_bottom_toolbar.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_toolbar_button_selector">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv__bottom_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="@dimen/margin_small"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv__bottom_item_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/bottom_panel_height"
|
||||
android:layout_toRightOf="@id/iv__bottom_icon"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="@android:color/white"/>
|
||||
|
||||
<View
|
||||
style="@style/drawerSeparatorMediumPadded"
|
||||
android:layout_below="@id/tv__bottom_item_text"/>
|
||||
|
||||
</RelativeLayout>
|
178
android/src/com/mapswithme/maps/Ads/AdsManager.java
Normal file
178
android/src/com/mapswithme/maps/Ads/AdsManager.java
Normal file
|
@ -0,0 +1,178 @@
|
|||
package com.mapswithme.maps.Ads;
|
||||
|
||||
import com.mapswithme.maps.MWMApplication;
|
||||
import com.mapswithme.util.ConnectionState;
|
||||
import com.mapswithme.util.Constants;
|
||||
import com.mapswithme.util.UiUtils;
|
||||
import com.mapswithme.util.Utils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class AdsManager
|
||||
{
|
||||
private static final String ROOT_MENU_ITEMS_KEY = "AppFeatureBottomMenuItems";
|
||||
private static final String MENU_ITEMS_KEY = "Items";
|
||||
private static final String DEFAULT_KEY = "*";
|
||||
private static final String ID_KEY = "Id";
|
||||
private static final String APP_URL_KEY = "AppURL";
|
||||
private static final String ICON_KEY = "IconURLs";
|
||||
private static final String TITLE_KEY = "Titles";
|
||||
private static final String COLOR_KEY = "Color";
|
||||
private static final String WEB_URL_KEY = "WebURLs";
|
||||
private static final String CACHE_FILE = "menu_ads.json";
|
||||
|
||||
private static List<MenuAd> sMenuAds;
|
||||
|
||||
public static List<MenuAd> getMenuAds()
|
||||
{
|
||||
return sMenuAds;
|
||||
}
|
||||
|
||||
public static void updateMenuAds()
|
||||
{
|
||||
String menuAdsString;
|
||||
if (ConnectionState.isConnected(MWMApplication.get()))
|
||||
{
|
||||
menuAdsString = getJsonAdsFromServer();
|
||||
cacheMenuAds(menuAdsString);
|
||||
}
|
||||
else
|
||||
menuAdsString = getCachedJsonString();
|
||||
|
||||
if (menuAdsString == null)
|
||||
return;
|
||||
|
||||
final JSONObject menuAdsJson;
|
||||
try
|
||||
{
|
||||
menuAdsJson = new JSONObject(menuAdsString);
|
||||
sMenuAds = parseMenuAds(menuAdsJson);
|
||||
} catch (JSONException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void cacheMenuAds(String menuAdsString)
|
||||
{
|
||||
final File cacheFile = new File(MWMApplication.get().getDataStoragePath(), CACHE_FILE);
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(cacheFile))
|
||||
{
|
||||
fileOutputStream.write(menuAdsString.getBytes());
|
||||
fileOutputStream.close();
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getCachedJsonString()
|
||||
{
|
||||
String menuAdsString = null;
|
||||
final File cacheFile = new File(MWMApplication.get().getDataStoragePath(), CACHE_FILE);
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(cacheFile))))
|
||||
{
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null)
|
||||
stringBuilder.append(line);
|
||||
|
||||
menuAdsString = stringBuilder.toString();
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return menuAdsString;
|
||||
}
|
||||
|
||||
private static List<MenuAd> parseMenuAds(JSONObject adsJson) throws JSONException
|
||||
{
|
||||
final List<MenuAd> ads = new ArrayList<>();
|
||||
|
||||
final JSONArray menuItemsJson = adsJson.getJSONObject(ROOT_MENU_ITEMS_KEY).
|
||||
getJSONObject(DEFAULT_KEY).
|
||||
getJSONArray(MENU_ITEMS_KEY);
|
||||
|
||||
final String localeKey = Locale.getDefault().getLanguage();
|
||||
final String density = UiUtils.getDisplayDensityString();
|
||||
for (int i = 0; i < menuItemsJson.length(); i++)
|
||||
{
|
||||
final JSONObject menuItemJson = menuItemsJson.getJSONObject(i);
|
||||
final String icon = getStringByKeyOrDefault(menuItemJson.getJSONObject(ICON_KEY), density);
|
||||
final String webUrl = getStringByKeyOrDefault(menuItemJson.getJSONObject(WEB_URL_KEY), localeKey);
|
||||
final String title = getStringByKeyOrDefault(menuItemJson.getJSONObject(TITLE_KEY), localeKey);
|
||||
|
||||
ads.add(new MenuAd(icon,
|
||||
title,
|
||||
menuItemJson.getString(COLOR_KEY),
|
||||
menuItemJson.getString(ID_KEY),
|
||||
menuItemJson.getString(APP_URL_KEY),
|
||||
webUrl));
|
||||
}
|
||||
|
||||
return ads;
|
||||
}
|
||||
|
||||
private static String getStringByKeyOrDefault(JSONObject json, String key) throws JSONException
|
||||
{
|
||||
String res = json.optString(key);
|
||||
if (res.isEmpty())
|
||||
res = json.optString(DEFAULT_KEY);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static String getJsonAdsFromServer()
|
||||
{
|
||||
BufferedReader reader = null;
|
||||
HttpURLConnection connection = null;
|
||||
try
|
||||
{
|
||||
final URL url = new URL(Constants.Url.MENU_ADS_JSON);
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
final int timeout = 10000;
|
||||
connection.setReadTimeout(timeout);
|
||||
connection.setConnectTimeout(timeout);
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setDoInput(true);
|
||||
// Starts the query
|
||||
connection.connect();
|
||||
final int response = connection.getResponseCode();
|
||||
if (response == HttpURLConnection.HTTP_OK)
|
||||
{
|
||||
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null)
|
||||
builder.append(line).append("\n");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
} catch (java.io.IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
} finally
|
||||
{
|
||||
Utils.closeStream(reader);
|
||||
if (connection != null)
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
102
android/src/com/mapswithme/maps/Ads/MenuAd.java
Normal file
102
android/src/com/mapswithme/maps/Ads/MenuAd.java
Normal file
|
@ -0,0 +1,102 @@
|
|||
package com.mapswithme.maps.Ads;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class MenuAd implements Parcelable
|
||||
{
|
||||
private String mIconUrl;
|
||||
private String mTitle;
|
||||
private String mHexColor;
|
||||
private String mId;
|
||||
private String mAppUrl;
|
||||
private String mWebUrl;
|
||||
|
||||
public MenuAd(String iconUrl, String title, String hexColor, String id, String appUrl, String webUrl)
|
||||
{
|
||||
mIconUrl = iconUrl;
|
||||
mTitle = title;
|
||||
mHexColor = hexColor;
|
||||
mId = id;
|
||||
mAppUrl = appUrl;
|
||||
mWebUrl = webUrl;
|
||||
}
|
||||
|
||||
public MenuAd(Parcel source)
|
||||
{
|
||||
mIconUrl = source.readString();
|
||||
mTitle = source.readString();
|
||||
mHexColor = source.readString();
|
||||
mId = source.readString();
|
||||
mAppUrl = source.readString();
|
||||
mWebUrl = source.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mIconUrl + " " + mTitle + " " + mHexColor + " " + mId + " " + mAppUrl + " " + mWebUrl;
|
||||
}
|
||||
|
||||
public String getAppUrl()
|
||||
{
|
||||
return mAppUrl;
|
||||
}
|
||||
|
||||
public String getHexColor()
|
||||
{
|
||||
return mHexColor;
|
||||
}
|
||||
|
||||
public String getIconUrl()
|
||||
{
|
||||
return mIconUrl;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
public String getWebUrl()
|
||||
{
|
||||
return mWebUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags)
|
||||
{
|
||||
dest.writeString(mIconUrl);
|
||||
dest.writeString(mTitle);
|
||||
dest.writeString(mHexColor);
|
||||
dest.writeString(mId);
|
||||
dest.writeString(mAppUrl);
|
||||
dest.writeString(mWebUrl);
|
||||
}
|
||||
|
||||
public static final Creator<MenuAd> CREATOR = new Creator<MenuAd>()
|
||||
{
|
||||
@Override
|
||||
public MenuAd createFromParcel(Parcel source)
|
||||
{
|
||||
return new MenuAd(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuAd[] newArray(int size)
|
||||
{
|
||||
return new MenuAd[size];
|
||||
}
|
||||
};
|
||||
}
|
|
@ -7,12 +7,16 @@ import android.content.BroadcastReceiver;
|
|||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
@ -21,16 +25,20 @@ import android.view.View.OnClickListener;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.facebook.Session;
|
||||
import com.facebook.SessionState;
|
||||
import com.facebook.UiLifecycleHelper;
|
||||
import com.mapswithme.country.DownloadActivity;
|
||||
import com.mapswithme.maps.Ads.AdsManager;
|
||||
import com.mapswithme.maps.Ads.MenuAd;
|
||||
import com.mapswithme.maps.Framework.OnBalloonListener;
|
||||
import com.mapswithme.maps.LocationButtonImageSetter.ButtonState;
|
||||
import com.mapswithme.maps.MapStorage.Index;
|
||||
import com.mapswithme.maps.api.ParsedMmwRequest;
|
||||
import com.mapswithme.maps.background.WorkerService;
|
||||
import com.mapswithme.maps.bookmarks.BookmarkActivity;
|
||||
import com.mapswithme.maps.bookmarks.BookmarkCategoriesActivity;
|
||||
import com.mapswithme.maps.bookmarks.data.Bookmark;
|
||||
|
@ -59,6 +67,7 @@ import com.mapswithme.util.statistics.Statistics;
|
|||
import com.nvidia.devtech.NvEventQueueActivity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Stack;
|
||||
|
||||
|
@ -115,6 +124,17 @@ public class MWMActivity extends NvEventQueueActivity
|
|||
}
|
||||
};
|
||||
|
||||
// ads in vertical toolbar
|
||||
private BroadcastReceiver mUpdateAdsReceiver = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
updateToolbarAds();
|
||||
}
|
||||
};
|
||||
private boolean mAreToolbarAdsUpdated;
|
||||
|
||||
public static Intent createShowMapIntent(Context context, Index index, boolean doAutoDownload)
|
||||
{
|
||||
return new Intent(context, DownloadResourcesActivity.class)
|
||||
|
@ -725,6 +745,43 @@ public class MWMActivity extends NvEventQueueActivity
|
|||
|
||||
mFbUiHelper = new UiLifecycleHelper(this, mFbStatusCallback);
|
||||
mFbUiHelper.onCreate(savedInstanceState);
|
||||
|
||||
updateToolbarAds();
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mUpdateAdsReceiver, new IntentFilter(WorkerService.ACTION_UPDATE_MENU_ADS));
|
||||
}
|
||||
|
||||
private void updateToolbarAds()
|
||||
{
|
||||
final List<MenuAd> ads = AdsManager.getMenuAds();
|
||||
if (ads != null && !mAreToolbarAdsUpdated)
|
||||
{
|
||||
mAreToolbarAdsUpdated = true;
|
||||
int startAdMenuPosition = 7;
|
||||
for (final MenuAd ad : ads)
|
||||
{
|
||||
final View view = getLayoutInflater().inflate(R.layout.item_bottom_toolbar, mVerticalToolbar, false);
|
||||
final TextView textView = (TextView) view.findViewById(R.id.tv__bottom_item_text);
|
||||
textView.setText(ad.getTitle());
|
||||
try
|
||||
{
|
||||
textView.setTextColor(Color.parseColor(ad.getHexColor()));
|
||||
} catch (IllegalArgumentException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
view.setOnClickListener(new OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
final Intent it = new Intent(Intent.ACTION_VIEW);
|
||||
it.setData(Uri.parse(ad.getAppUrl()));
|
||||
startActivity(it);
|
||||
}
|
||||
});
|
||||
mVerticalToolbar.addView(view, startAdMenuPosition++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpToolbars()
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
|
|||
import com.google.android.gms.common.GooglePlayServicesRepairableException;
|
||||
import com.mapswithme.maps.MapStorage.Index;
|
||||
import com.mapswithme.maps.background.Notifier;
|
||||
import com.mapswithme.maps.background.WorkerService;
|
||||
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
|
||||
import com.mapswithme.maps.guides.GuideInfo;
|
||||
import com.mapswithme.maps.guides.GuidesUtils;
|
||||
|
@ -155,6 +156,8 @@ public class MWMApplication extends android.app.Application implements MapStorag
|
|||
BookmarkManager.getBookmarkManager(getApplicationContext());
|
||||
|
||||
Notifier.schedulePromoNotification();
|
||||
|
||||
WorkerService.startActionUpdateAds(this);
|
||||
}
|
||||
|
||||
public LocationService getLocationService()
|
||||
|
|
|
@ -7,8 +7,10 @@ import android.content.SharedPreferences;
|
|||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mapswithme.maps.Ads.AdsManager;
|
||||
import com.mapswithme.maps.Framework;
|
||||
import com.mapswithme.maps.MWMApplication;
|
||||
import com.mapswithme.maps.R;
|
||||
|
@ -33,6 +35,7 @@ public class WorkerService extends IntentService
|
|||
public static final String ACTION_DOWNLOAD_COUNTRY = "com.mapswithme.maps.action.download_country";
|
||||
public static final String ACTION_PROMO_NOTIFICATION_SHOW = "com.mapswithme.maps.action.notification.show";
|
||||
public static final String ACTION_PROMO_NOTIFICATION_CLICK = "com.mapswithme.maps.action.notification.click";
|
||||
public static final String ACTION_UPDATE_MENU_ADS = "com.mapswithme.maps.action.ads.update";
|
||||
|
||||
private static final String PROMO_SHOW_EVENT_NAME = "PromoShowAndroid";
|
||||
private static final String PROMO_CLICK_EVENT_NAME = "PromoClickAndroid";
|
||||
|
@ -80,6 +83,16 @@ public class WorkerService extends IntentService
|
|||
context.startService(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts this service to perform advertisements update for bottom menu.
|
||||
*/
|
||||
public static void startActionUpdateAds(Context context)
|
||||
{
|
||||
final Intent intent = new Intent(context, WorkerService.class);
|
||||
intent.setAction(WorkerService.ACTION_UPDATE_MENU_ADS);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
public WorkerService()
|
||||
{
|
||||
super("WorkerService");
|
||||
|
@ -109,6 +122,9 @@ public class WorkerService extends IntentService
|
|||
case ACTION_PROMO_NOTIFICATION_CLICK:
|
||||
promoNotificationClicked();
|
||||
break;
|
||||
case ACTION_UPDATE_MENU_ADS:
|
||||
updateMenuAds();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -220,4 +236,12 @@ public class WorkerService extends IntentService
|
|||
startActivity(intent);
|
||||
Statistics.INSTANCE.trackSimpleNamedEvent(PROMO_CLICK_EVENT_NAME);
|
||||
}
|
||||
|
||||
private void updateMenuAds()
|
||||
{
|
||||
AdsManager.updateMenuAds();
|
||||
final Intent broadcast = new Intent(ACTION_UPDATE_MENU_ADS);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ public class Constants
|
|||
public static final String MAIL_MAPSME_SUBSCRIBE = "subscribe@maps.me";
|
||||
|
||||
public static final String DATA_SCHEME_FILE = "file";
|
||||
public static final String MENU_ADS_JSON = "http://application.server/android/features.json";
|
||||
|
||||
private Url() {}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.mapswithme.util;
|
|||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
|
@ -14,8 +15,10 @@ import android.graphics.drawable.BitmapDrawable;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.Animation.AnimationListener;
|
||||
import android.widget.ImageView;
|
||||
|
@ -306,6 +309,29 @@ public final class UiUtils
|
|||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
public static String getDisplayDensityString()
|
||||
{
|
||||
final DisplayMetrics metrics = new DisplayMetrics();
|
||||
((WindowManager) MWMApplication.get().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metrics);
|
||||
switch (metrics.densityDpi)
|
||||
{
|
||||
case DisplayMetrics.DENSITY_LOW:
|
||||
return "ldpi";
|
||||
case DisplayMetrics.DENSITY_MEDIUM:
|
||||
return "mdpi";
|
||||
case DisplayMetrics.DENSITY_HIGH:
|
||||
return "hdpi";
|
||||
case DisplayMetrics.DENSITY_XHIGH:
|
||||
return "xhdpi";
|
||||
case DisplayMetrics.DENSITY_XXHIGH:
|
||||
return "xxhdpi";
|
||||
case DisplayMetrics.DENSITY_XXXHIGH:
|
||||
return "xxxhdpi";
|
||||
}
|
||||
|
||||
return "hdpi";
|
||||
}
|
||||
|
||||
|
||||
// utility class
|
||||
private UiUtils()
|
||||
|
|
Loading…
Add table
Reference in a new issue