From ea2e62124cbb60d85555596370af16b3ddb536c9 Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Sat, 3 Oct 2015 20:12:08 -0400 Subject: [PATCH 1/9] Store internal start/end Date objects, so we can track the date-of-events better, for section-header purposes. --- .../dancedeets/android/models/FullEvent.java | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/dancedeets/android/models/FullEvent.java b/app/src/main/java/com/dancedeets/android/models/FullEvent.java index 70bcedf..4cb005f 100644 --- a/app/src/main/java/com/dancedeets/android/models/FullEvent.java +++ b/app/src/main/java/com/dancedeets/android/models/FullEvent.java @@ -36,8 +36,8 @@ public class FullEvent implements Parcelable, Serializable { protected String mTitle; protected String mDescription; - protected long mStartTime; - protected long mEndTime; + protected Date mStartTime; + protected Date mEndTime; protected boolean mAllDayEvent; protected String mImageUrl; @@ -60,16 +60,13 @@ static public FullEvent parse(JSONObject jsonEvent) throws JSONException { String startTimeString = jsonEvent.getString("start_time"); try { - Date date = isoDateTimeFormatWithTZ.parse(startTimeString); - event.mStartTime = date.getTime(); + event.mStartTime = isoDateTimeFormatWithTZ.parse(startTimeString); } catch (ParseException e1) { try { - Date date = isoDateTimeFormat.parse(startTimeString); - event.mStartTime = date.getTime(); + event.mStartTime = isoDateTimeFormat.parse(startTimeString); } catch (ParseException e2) { try { - Date date = isoDateFormat.parse(startTimeString); - event.mStartTime = date.getTime(); + event.mStartTime = isoDateFormat.parse(startTimeString); event.mAllDayEvent = true; } catch (ParseException e3) { throw new JSONException("ParseException on start_time string: " + startTimeString); @@ -79,16 +76,13 @@ static public FullEvent parse(JSONObject jsonEvent) throws JSONException { if (!jsonEvent.isNull("end_time")) { String endTimeString = jsonEvent.getString("end_time"); try { - Date date = isoDateTimeFormatWithTZ.parse(endTimeString); - event.mEndTime = date.getTime(); + event.mEndTime = isoDateTimeFormatWithTZ.parse(endTimeString); } catch (ParseException e) { try { - Date date = isoDateTimeFormat.parse(endTimeString); - event.mEndTime = date.getTime(); + event.mEndTime = isoDateTimeFormat.parse(endTimeString); } catch (ParseException e2) { try { - Date date = isoDateFormat.parse(endTimeString); - event.mEndTime = date.getTime(); + event.mEndTime = isoDateFormat.parse(endTimeString); } catch (ParseException e3) { throw new JSONException("ParseException on end_time string: " + endTimeString); } @@ -155,10 +149,14 @@ public String getThumbnailUrl() { return mImageUrl; } - public long getStartTimeLong() { + public Date getStartTime() { return mStartTime; } + public long getStartTimeLong() { + return mStartTime.getTime(); + } + public String getStartTimeString() { if (getStartTimeLong() != 0) { if (mAllDayEvent) { @@ -183,13 +181,17 @@ public String getStartTimeString(Locale locale) { } } + public Date getEndTime() { + return mStartTime; + } + public long getEndTimeLong() { - return mEndTime; + return mEndTime.getTime(); } public String getEndTimeString() { - if (getEndTimeLong() != 0) { - if (mEndTime - mStartTime < 1000*60*60*12) { + if (mEndTime != null) { + if (mEndTime.getTime() - mStartTime.getTime() < 1000*60*60*12) { return localizedTimeFormat.format(getEndTimeLong()); } else if (mAllDayEvent) { return localizedDateFormat.format(getEndTimeLong()); @@ -202,8 +204,8 @@ public String getEndTimeString() { } public String getEndTimeString(Locale locale) { - if (getEndTimeLong() != 0) { - if (mEndTime - mStartTime < 1000*60*60*12) { + if (mEndTime != null) { + if (mEndTime.getTime() - mStartTime.getTime() < 1000*60*60*12) { return localizedTimeFormat.format(getEndTimeLong()); } else if (mAllDayEvent) { return DateFormat.getDateInstance(DateFormat.MEDIUM, locale).format(getEndTimeLong()); @@ -217,7 +219,7 @@ public String getEndTimeString(Locale locale) { public String getFullTimeString() { String fullTime = getStartTimeString(); - if (mEndTime != 0) { + if (mEndTime != null) { fullTime += " - " + getEndTimeString(); } return fullTime; @@ -294,8 +296,8 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeString(mId); dest.writeString(mTitle); dest.writeString(mDescription); - dest.writeLong(mStartTime); - dest.writeLong(mEndTime); + dest.writeLong(mStartTime != null ? mStartTime.getTime() : 0); + dest.writeLong(mEndTime != null ? mEndTime.getTime() : 0); dest.writeByte((byte) (mAllDayEvent ? 1 : 0)); dest.writeString(mImageUrl); dest.writeString(mCoverUrl); @@ -332,8 +334,8 @@ private FullEvent(Parcel in) { mTitle = in.readString(); mDescription = in.readString(); - mStartTime = in.readLong(); - mEndTime = in.readLong(); + mStartTime = new Date(in.readLong()); + mEndTime = new Date(in.readLong()); mAllDayEvent = in.readByte() != 0; mImageUrl = in.readString(); From 89c2ce1e561de3a48cab186b6aadede16e7fc023 Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Sun, 4 Oct 2015 16:37:38 -0400 Subject: [PATCH 2/9] Add section-headers (but without stickiness) using the event dates in the event list. --- .../dancedeets/android/EventListFragment.java | 9 +- .../dancedeets/android/EventUIAdapter.java | 119 ++++++++++++++++-- 2 files changed, 113 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/dancedeets/android/EventListFragment.java b/app/src/main/java/com/dancedeets/android/EventListFragment.java index f0b4718..9a0a6d2 100644 --- a/app/src/main/java/com/dancedeets/android/EventListFragment.java +++ b/app/src/main/java/com/dancedeets/android/EventListFragment.java @@ -142,6 +142,7 @@ protected void onEventListFilled() { mEmptyText.setVisibility(View.GONE); } mRetryButton.setVisibility(View.GONE); + eventAdapter.rebuildList(mBundled.mEventList); setListAdapter(eventAdapter); } @@ -214,7 +215,7 @@ public void onClick(View view) { mListDescription = (TextView) rootView.findViewById(R.id.event_list_description); - eventAdapter = new EventUIAdapter(inflater.getContext(), mBundled.mEventList, R.layout.event_row); + eventAdapter = new EventUIAdapter(inflater.getContext()); if (savedInstanceState != null && !mBundled.mWaitingForSearch) { onEventListFilled(); @@ -355,7 +356,9 @@ public void onListItemClick(ListView listView, View view, int position, long id) { super.onListItemClick(listView, view, position, id); - FullEvent event = mBundled.mEventList.get(position); + int translatedPosition = eventAdapter.translatePosition(position); + FullEvent event = mBundled.mEventList.get(translatedPosition); + Log("onListItemClick: fb event id: " + event.getId()); VolleySingleton volley = VolleySingleton.getInstance(); @@ -369,7 +372,7 @@ public void onListItemClick(ListView listView, View view, int position, // Notify the active callbacks interface (the activity, if the // fragment is attached to one) that an item has been selected. if (mCallbacks != null) { - mCallbacks.onEventSelected(mBundled.mEventList, position); + mCallbacks.onEventSelected(mBundled.mEventList, translatedPosition); } } diff --git a/app/src/main/java/com/dancedeets/android/EventUIAdapter.java b/app/src/main/java/com/dancedeets/android/EventUIAdapter.java index d032ba9..d52f1ed 100644 --- a/app/src/main/java/com/dancedeets/android/EventUIAdapter.java +++ b/app/src/main/java/com/dancedeets/android/EventUIAdapter.java @@ -1,6 +1,7 @@ package com.dancedeets.android; import android.content.Context; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -12,6 +13,9 @@ import com.dancedeets.android.models.CoverData; import com.dancedeets.android.models.FullEvent; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Calendar; import java.util.List; /** @@ -19,6 +23,8 @@ */ public class EventUIAdapter extends BaseAdapter { + private static String LOG_TAG = "EventUIAdapter"; + static class ViewBinder { NetworkImageView icon; PlaceholderNetworkImageView cover; @@ -28,28 +34,79 @@ static class ViewBinder { TextView categories; } private LayoutInflater mInflater; - private List mEventList; - private int mResource; + private List mSectionedEventList; + private List mMapping; + private static int mSectionResource = 0; + private static int mResource = R.layout.event_row; + + public enum ItemType { + HEADER(0), + EVENT(1); + + private final int queryArg; + ItemType(int queryArg) { + this.queryArg = queryArg; + } + public int value() { + return queryArg; + } + } + + static DateFormat localizedDateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM); - public EventUIAdapter(Context context, List eventBundleList, int resource) { + public EventUIAdapter(Context context) { mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mEventList = eventBundleList; - mResource = resource; } + + public void rebuildList(List eventBundleList) { + mMapping = new ArrayList<>(); + mSectionedEventList = fillSectionedList(eventBundleList); + } + + private List fillSectionedList(List eventList) { + Calendar lastCal = Calendar.getInstance(); + Calendar curCal = Calendar.getInstance(); + List sectionedList = new ArrayList<>(); + for (int i = 0; i < eventList.size(); i++) { + FullEvent event = eventList.get(i); + curCal.setTime(event.getStartTime()); + if (i == 0 || + curCal.get(Calendar.YEAR) != lastCal.get(Calendar.YEAR) || + curCal.get(Calendar.DAY_OF_YEAR) != lastCal.get(Calendar.DAY_OF_YEAR) + ) { + sectionedList.add(localizedDateFormat.format(event.getStartTimeLong())); + mMapping.add(-1); + } + sectionedList.add(event); + lastCal.setTime(event.getStartTime()); + mMapping.add(i); + } + Log.i(LOG_TAG, " "+sectionedList); + return sectionedList; + } + + public int translatePosition(int position) { + return mMapping.get(position); + } + public int getCount() { - return mEventList.size(); + return mSectionedEventList.size(); } @Override public Object getItem(int position) { - return mEventList.get(position); + return mSectionedEventList.get(position); } @Override public long getItemId(int position) { // The facebook ID is not guaranteed to fit into a 'long', // so we use the hashcode of the string, which should be good enough for uniqueness. - return Math.abs(mEventList.get(position).getId().hashCode()); + if (getItemViewType(position) == ItemType.HEADER.value()) { + return Math.abs(mSectionedEventList.get(position).hashCode()); + } else { + return Math.abs(((FullEvent) mSectionedEventList.get(position)).getId().hashCode()); + } } @Override @@ -58,6 +115,26 @@ public boolean hasStableIds() { return true; } + @Override + public int getViewTypeCount() { + return 2; + } + + protected ItemType getItemType(int position) { + Object o = mSectionedEventList.get(position); + if (o instanceof FullEvent) { + return ItemType.EVENT; + } + else { + return ItemType.HEADER; + } + } + + @Override + public int getItemViewType(int position) { + return getItemType(position).value(); + } + protected void bindView(int position, View view) { FullEvent event = (FullEvent)getItem(position); ImageLoader thumbnailLoader = VolleySingleton.getInstance().getThumbnailLoader(); @@ -87,14 +164,32 @@ protected void bindView(int position, View view) { @Override public View getView(int position, View convertView, ViewGroup parent) { - return createViewFromResource(position, convertView, parent, mResource); + if (getItemType(position) == ItemType.EVENT) { + return createEventViewFromResource(position, convertView, parent); + } else { + return createSectionViewFromResource(position, convertView, parent); + } + } + + private View createSectionViewFromResource(int position, View convertView, + ViewGroup parent) { + TextView view; + if (convertView == null) { + view = (TextView) mInflater.inflate(parent.getResources().getLayout(android.R.layout.simple_list_item_1), null); + view.setTag("sticky"); + } else { + view = (TextView) convertView; + } + view.setText((String)mSectionedEventList.get(position)); + + return view; } - private View createViewFromResource(int position, View convertView, - ViewGroup parent, int resource) { + private View createEventViewFromResource(int position, View convertView, + ViewGroup parent) { View view; if (convertView == null) { - view = mInflater.inflate(resource, parent, false); + view = mInflater.inflate(mResource, parent, false); ViewBinder viewBinder = new ViewBinder(); //viewBinder.icon = (NetworkImageView)view.findViewById(R.id.event_list_icon); viewBinder.cover = (PlaceholderNetworkImageView)view.findViewById(R.id.event_list_cover); From 4ac24d0b48e175eeb13fbe9568a8a76b52e5520e Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Tue, 6 Oct 2015 05:30:29 -0400 Subject: [PATCH 3/9] Updates as part of Android Studio 1.4 update. --- .../java/com/dancedeets/android/CommonActivityTest.java | 2 +- .../java/com/dancedeets/android/EventInfoActivityTest.java | 6 +++--- .../java/com/dancedeets/android/SearchListActivityTest.java | 2 +- robolectric-tests/robolectric-tests.iml | 1 - 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/androidTest/java/com/dancedeets/android/CommonActivityTest.java b/app/src/androidTest/java/com/dancedeets/android/CommonActivityTest.java index 030c6c5..db2eb06 100644 --- a/app/src/androidTest/java/com/dancedeets/android/CommonActivityTest.java +++ b/app/src/androidTest/java/com/dancedeets/android/CommonActivityTest.java @@ -4,8 +4,8 @@ import android.os.Handler; import android.os.Looper; import android.support.test.espresso.Espresso; -import android.support.test.internal.runner.lifecycle.ActivityLifecycleMonitorRegistry; import android.support.test.runner.lifecycle.ActivityLifecycleCallback; +import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; import android.support.test.runner.lifecycle.Stage; import android.test.ActivityInstrumentationTestCase2; import android.view.View; diff --git a/app/src/androidTest/java/com/dancedeets/android/EventInfoActivityTest.java b/app/src/androidTest/java/com/dancedeets/android/EventInfoActivityTest.java index 91827fb..6e378a7 100644 --- a/app/src/androidTest/java/com/dancedeets/android/EventInfoActivityTest.java +++ b/app/src/androidTest/java/com/dancedeets/android/EventInfoActivityTest.java @@ -3,11 +3,11 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.support.test.espresso.action.ViewActions; -import android.support.test.internal.runner.lifecycle.ActivityLifecycleMonitorRegistry; +import android.support.test.espresso.core.deps.guava.base.Charsets; +import android.support.test.espresso.core.deps.guava.io.Resources; +import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; import android.util.Log; -import com.android.support.test.deps.guava.base.Charsets; -import com.android.support.test.deps.guava.io.Resources; import com.dancedeets.android.models.FullEvent; import org.json.JSONArray; diff --git a/app/src/androidTest/java/com/dancedeets/android/SearchListActivityTest.java b/app/src/androidTest/java/com/dancedeets/android/SearchListActivityTest.java index 6f908eb..83c470a 100644 --- a/app/src/androidTest/java/com/dancedeets/android/SearchListActivityTest.java +++ b/app/src/androidTest/java/com/dancedeets/android/SearchListActivityTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; -import static org.hamcrest.text.StringContains.containsString; +import static org.hamcrest.core.StringContains.containsString; /** * Created by lambert on 2014/10/28. diff --git a/robolectric-tests/robolectric-tests.iml b/robolectric-tests/robolectric-tests.iml index df3f549..e60f9ec 100644 --- a/robolectric-tests/robolectric-tests.iml +++ b/robolectric-tests/robolectric-tests.iml @@ -27,7 +27,6 @@ - From 15fae2cce3268a831653cdaf527a4af7ae5c8347 Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Wed, 7 Oct 2015 21:02:27 -0700 Subject: [PATCH 4/9] Fix bugs with tabbing too far over and back, resulting in a crash with the new section-headers. Also fix crash when clicking on section headers (-1). --- .../main/java/com/dancedeets/android/EventListFragment.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/dancedeets/android/EventListFragment.java b/app/src/main/java/com/dancedeets/android/EventListFragment.java index 9a0a6d2..5cdb730 100644 --- a/app/src/main/java/com/dancedeets/android/EventListFragment.java +++ b/app/src/main/java/com/dancedeets/android/EventListFragment.java @@ -216,8 +216,9 @@ public void onClick(View view) { mListDescription = (TextView) rootView.findViewById(R.id.event_list_description); eventAdapter = new EventUIAdapter(inflater.getContext()); + setListAdapter(null); - if (savedInstanceState != null && !mBundled.mWaitingForSearch) { + if (mBundled.mEventList.size() > 0 && !mBundled.mWaitingForSearch) { onEventListFilled(); } @@ -357,6 +358,9 @@ public void onListItemClick(ListView listView, View view, int position, super.onListItemClick(listView, view, position, id); int translatedPosition = eventAdapter.translatePosition(position); + if (translatedPosition < 0) { + return; + } FullEvent event = mBundled.mEventList.get(translatedPosition); Log("onListItemClick: fb event id: " + event.getId()); From 54b6c7f5a314fa17a399acebea9cd7674060f74d Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Wed, 7 Oct 2015 21:52:45 -0700 Subject: [PATCH 5/9] Add a bottom DFP banner, but only show it if we have ad inventory. --- app/build.gradle | 3 +- app/src/main/AndroidManifest.xml | 5 ++ .../android/SearchListActivity.java | 24 ++++++++++ .../res/layout-w240dp/activity_event_list.xml | 14 +++++- .../res/layout-w820dp/activity_event_list.xml | 46 +++++++++++++------ app/src/main/res/layout/fragment_pager.xml | 4 +- app/src/main/res/values/strings.xml | 1 + 7 files changed, 80 insertions(+), 17 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1f17b5e..220014e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -51,7 +51,8 @@ dependencies { // You must install or update the Support Repository through the SDK manager to use this dependency. compile 'com.android.support:support-v4:21.0.3' compile 'com.android.support:support-v13:21.0.0' - // Don't want version 5.2.08, as it's not yet available on devices + //compile 'com.google.android.gms:play-services-ads:8.0.+' + //compile 'com.google.android.gms:play-services-analytics:5.0.+' compile 'com.google.android.gms:play-services:5.0.+' compile 'com.mcxiaoke.volley:library:1.0.19' compile 'it.sephiroth.android.library.imagezoom:imagezoom:+' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0ba81f2..e68e562 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -150,6 +150,11 @@ + + + diff --git a/app/src/main/java/com/dancedeets/android/SearchListActivity.java b/app/src/main/java/com/dancedeets/android/SearchListActivity.java index fc8539d..01a2254 100644 --- a/app/src/main/java/com/dancedeets/android/SearchListActivity.java +++ b/app/src/main/java/com/dancedeets/android/SearchListActivity.java @@ -24,6 +24,10 @@ import com.dancedeets.android.uistate.StateHolder; import com.dancedeets.android.uistate.StateUtil; import com.facebook.login.LoginManager; +import com.google.android.gms.ads.AdListener; +import com.google.android.gms.ads.AdRequest; +import com.google.android.gms.ads.doubleclick.PublisherAdRequest; +import com.google.android.gms.ads.doubleclick.PublisherAdView; import java.util.ArrayList; @@ -93,6 +97,26 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_event_list); + // Set up bottom banner ad + final PublisherAdView mPublisherAdView = (PublisherAdView) findViewById(R.id.publisherAdView); + PublisherAdRequest adRequest = new PublisherAdRequest.Builder() + .addTestDevice(AdRequest.DEVICE_ID_EMULATOR) + .addTestDevice("F92F46CF903B1E0BD86D386FC9813E7F") + .build(); + mPublisherAdView.loadAd(adRequest); + mPublisherAdView.setVisibility(View.GONE); + mPublisherAdView.setAdListener(new AdListener() { + @Override + public void onAdLoaded() { + mPublisherAdView.setVisibility(View.VISIBLE); + } + + @Override + public void onAdFailedToLoad(int errorCode) { + mPublisherAdView.setVisibility(View.GONE); + } + }); + // Locate the viewpager in activity_main.xml mViewPager = (ViewPager) findViewById(R.id.pager); diff --git a/app/src/main/res/layout-w240dp/activity_event_list.xml b/app/src/main/res/layout-w240dp/activity_event_list.xml index af58a5c..3c39570 100644 --- a/app/src/main/res/layout-w240dp/activity_event_list.xml +++ b/app/src/main/res/layout-w240dp/activity_event_list.xml @@ -1,8 +1,20 @@ - + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-w820dp/activity_event_list.xml b/app/src/main/res/layout-w820dp/activity_event_list.xml index 52ace31..d690444 100644 --- a/app/src/main/res/layout-w820dp/activity_event_list.xml +++ b/app/src/main/res/layout-w820dp/activity_event_list.xml @@ -1,24 +1,42 @@ - - - - + + + + + + + + + - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_pager.xml b/app/src/main/res/layout/fragment_pager.xml index 47dbdea..7ffdc6f 100644 --- a/app/src/main/res/layout/fragment_pager.xml +++ b/app/src/main/res/layout/fragment_pager.xml @@ -2,7 +2,9 @@ + android:layout_height="match_parent" + android:layout_weight="1" + > Upcoming Events Ongoing Events Past Events + /26589588/mobile-bottom-banner From af5851f62e1985a83c1a07d02b24e4cb0666b2f3 Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Thu, 8 Oct 2015 01:26:25 -0700 Subject: [PATCH 6/9] Add location to our DfP requests, based on the user's geo location (not search location...still considering this one) --- .../com/dancedeets/android/AdManager.java | 21 +++++++++++++++++++ .../com/dancedeets/android/FetchLocation.java | 6 +++++- .../com/dancedeets/android/LoginActivity.java | 4 ++++ .../android/SearchListActivity.java | 19 ++++++++--------- 4 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/com/dancedeets/android/AdManager.java diff --git a/app/src/main/java/com/dancedeets/android/AdManager.java b/app/src/main/java/com/dancedeets/android/AdManager.java new file mode 100644 index 0000000..dd89e64 --- /dev/null +++ b/app/src/main/java/com/dancedeets/android/AdManager.java @@ -0,0 +1,21 @@ +package com.dancedeets.android; + +import android.location.Location; + +import com.google.android.gms.ads.AdRequest; +import com.google.android.gms.ads.doubleclick.PublisherAdRequest; + +/** + * Created by lambert on 2015/10/08. + */ +public class AdManager { + + public static PublisherAdRequest getAdRequest(Location location) { + PublisherAdRequest adRequest = new PublisherAdRequest.Builder() + .addTestDevice(AdRequest.DEVICE_ID_EMULATOR) + .addTestDevice("F92F46CF903B1E0BD86D386FC9813E7F") + .setLocation(location) + .build(); + return adRequest; + } +} diff --git a/app/src/main/java/com/dancedeets/android/FetchLocation.java b/app/src/main/java/com/dancedeets/android/FetchLocation.java index 6cf728d..034f2db 100644 --- a/app/src/main/java/com/dancedeets/android/FetchLocation.java +++ b/app/src/main/java/com/dancedeets/android/FetchLocation.java @@ -34,7 +34,8 @@ public class FetchLocation implements GoogleApiClient.ConnectionCallbacks { private AddressListener mAddressListener; public interface AddressListener { - public void onAddressFound(Location location, Address address); + void onLocationFound(Location location ); + void onAddressFound(Location location, Address address); } public FetchLocation() { @@ -151,6 +152,9 @@ public void onConnected(Bundle bundle) { mLocation = mLocationProviderApi.getLastLocation(mGoogleApiClient); Log.i(LOG_TAG, "Reverse geocoding: " + mLocation); if (mLocation != null) { + if (mAddressListener != null) { + mAddressListener.onLocationFound(mLocation); + } // It's okay that this has an implicit reference to this parent class. // This class will be around as long as the underlying geocode task is running, // and when this class is destroyed via onStop, we cancel this task. diff --git a/app/src/main/java/com/dancedeets/android/LoginActivity.java b/app/src/main/java/com/dancedeets/android/LoginActivity.java index 91f0b03..6741ebf 100644 --- a/app/src/main/java/com/dancedeets/android/LoginActivity.java +++ b/app/src/main/java/com/dancedeets/android/LoginActivity.java @@ -69,6 +69,10 @@ private static class SendAuthRequest implements FetchLocation.AddressListener { mFetchLocation = fetchLocation; } + @Override + public void onLocationFound(Location location) { + } + @Override public void onAddressFound(Location location, Address address) { // We special-case this because the address.toString() omits SubLocality for some reason, and it's useful to us. diff --git a/app/src/main/java/com/dancedeets/android/SearchListActivity.java b/app/src/main/java/com/dancedeets/android/SearchListActivity.java index 01a2254..fe5fc0d 100644 --- a/app/src/main/java/com/dancedeets/android/SearchListActivity.java +++ b/app/src/main/java/com/dancedeets/android/SearchListActivity.java @@ -25,8 +25,6 @@ import com.dancedeets.android.uistate.StateUtil; import com.facebook.login.LoginManager; import com.google.android.gms.ads.AdListener; -import com.google.android.gms.ads.AdRequest; -import com.google.android.gms.ads.doubleclick.PublisherAdRequest; import com.google.android.gms.ads.doubleclick.PublisherAdView; import java.util.ArrayList; @@ -52,6 +50,8 @@ public class SearchListActivity extends FacebookActivity implements StateHolder< private MyBundledState mBundled; + private PublisherAdView mPublisherAdView; + @Override public MyBundledState buildBundledState() { return new MyBundledState(); @@ -98,12 +98,7 @@ protected void onCreate(Bundle savedInstanceState) { // Set up bottom banner ad - final PublisherAdView mPublisherAdView = (PublisherAdView) findViewById(R.id.publisherAdView); - PublisherAdRequest adRequest = new PublisherAdRequest.Builder() - .addTestDevice(AdRequest.DEVICE_ID_EMULATOR) - .addTestDevice("F92F46CF903B1E0BD86D386FC9813E7F") - .build(); - mPublisherAdView.loadAd(adRequest); + mPublisherAdView = (PublisherAdView) findViewById(R.id.publisherAdView); mPublisherAdView.setVisibility(View.GONE); mPublisherAdView.setAdListener(new AdListener() { @Override @@ -143,7 +138,6 @@ public void onPageSelected(int position) { } } - @Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); @@ -193,8 +187,13 @@ public void startSearchFor(SearchOptions newSearchOptions) { "Keywords", mBundled.mSearchOptions.keywords); } + @Override + public void onLocationFound(Location location) { + // As soon as we get the geo coordinates, load the ad request + mPublisherAdView.loadAd(AdManager.getAdRequest(location)); + } - @Override + @Override public void onAddressFound(Location location, Address address) { String optionalSubLocality = (address != null) ? " (with SubLocality " + address.getSubLocality() + ")" : ""; Crashlytics.log(Log.INFO, LOG_TAG, "Address found: " + address + optionalSubLocality); From 11d2e2790867358b77934c03b11e323cf80f0769 Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Thu, 8 Oct 2015 02:16:09 -0700 Subject: [PATCH 7/9] Split out location fetching and address fetching. Load the location every time for the ad, but only load the address if necessary for our search results. --- .../com/dancedeets/android/FetchAddress.java | 133 ++++++++++++++++++ .../com/dancedeets/android/FetchLocation.java | 107 ++------------ .../com/dancedeets/android/LoginActivity.java | 22 ++- .../android/SearchListActivity.java | 16 ++- 4 files changed, 165 insertions(+), 113 deletions(-) create mode 100644 app/src/main/java/com/dancedeets/android/FetchAddress.java diff --git a/app/src/main/java/com/dancedeets/android/FetchAddress.java b/app/src/main/java/com/dancedeets/android/FetchAddress.java new file mode 100644 index 0000000..a0e8526 --- /dev/null +++ b/app/src/main/java/com/dancedeets/android/FetchAddress.java @@ -0,0 +1,133 @@ +package com.dancedeets.android; + +import android.app.Activity; +import android.location.Address; +import android.location.Geocoder; +import android.location.Location; +import android.text.TextUtils; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** + * Created by lambert on 2014/11/26. + */ +public class FetchAddress implements FetchLocation.LocationListener { + + private static final String LOG_TAG = "FetchLocation"; + + private Geocoder mGeocoder; + + private FetchLocation mFetchLocation; + private Location mLocation; + private ReverseGeocodeTask mReverseGeocodeTask; + private AddressListener mAddressListener; + + public interface AddressListener { + void onAddressFound(Location location, Address address); + } + + public FetchAddress() { + mFetchLocation = new FetchLocation(); + } + + public static String formatAddress(Address address) { + List components = new ArrayList<>(); + // We really need *something* smaller than the AdminArea/State level. + // Especially since there might not be a State sometimes (ie Helsinki, Finland). + if (address.getLocality() != null) { + // Sometimes there is only a Locality: + // LatLong=35.6583942,139.6990928 + // SubLocality=null + // Locality=Shibuya + // SubAdminArea=null + // AdminArea=Tokyo + components.add(address.getLocality()); + } else if (address.getSubAdminArea() != null) { + // Sometimes there is only a SubAdminArea: + // LatLong=60.1836354,24.9206748 + // SubLocality=null + // Locality=null + // SubAdminArea=Helsinki + // AdminArea=null + components.add(address.getSubAdminArea()); + } else if (address.getSubLocality() != null) { + // Sometimes there is only a SubLocality: + // LatLong=40.790278,-73.959722 + // SubLocality=Dundas + // Locality=null + // SubAdminArea=null + // AdminArea=Ontario + // Dundas appears to be the smallest unit of geography, + // so we check for it in the third if-block, hoping to find a proper city first. + components.add(address.getSubLocality()); + } + // Sometimes there is too much data, and we want to drop a lot of it: + // LatLong=40.790278,-73.959722 + // SubLocality=Manhattan + // Locality=New York (the city) + // SubAdminArea=New York (the county) + // AdminArea=New York (the state) + // In this case, we just want to grab the Locality (first if-block above) + + // Then grab the States/Province/etc (for those who have it) + if (address.getAdminArea() != null) { + components.add(address.getAdminArea()); + } + // And finally the Country, which should always be there...unless....I'm on a boat! + // So let's be safe and make this optional, in which case we basically take whatever we can get + if (address.getCountryName() != null) { + components.add(address.getCountryName()); + } + return TextUtils.join(", ", components); + } + + private void onAddressFound(Address address) { + if (mAddressListener != null) { + mAddressListener.onAddressFound(mLocation, address); + } + } + + // FetchLocation should not store this Activity beyond the lifetime of the Activity. + // So we can safely use it to initialize variables here, but that's it. + // If we do want to store it (like in FetchLocationWithDialog), + // then we need to make sure the local reference gets cleaned up appropriately. + public void onStart(Activity activity, AddressListener addressListener) { + Log.i(LOG_TAG, "onStart, called from " + activity); + mAddressListener = addressListener; + // Connect the client. + mGeocoder = new Geocoder(activity, Locale.getDefault()); + mFetchLocation.onStart(activity, this); + } + + + public void onStop() { + Log.i(LOG_TAG, "onStop"); + mFetchLocation.onStop(); + mAddressListener = null; + if (mReverseGeocodeTask != null) { + mReverseGeocodeTask.cancel(true); + } + } + + @Override + public void onLocationFound(Location location) { + mLocation = location; + Log.i(LOG_TAG, "Reverse geocoding: " + mLocation); + if (mLocation != null) { + // It's okay that this has an implicit reference to this parent class. + // This class will be around as long as the underlying geocode task is running, + // and when this class is destroyed via onStop, we cancel this task. + mReverseGeocodeTask = new ReverseGeocodeTask(mGeocoder) { + protected void onPostExecute(Address address) { + onAddressFound(address); + } + }; + mReverseGeocodeTask.execute(mLocation); + } else { + onAddressFound(null); + } + } +} diff --git a/app/src/main/java/com/dancedeets/android/FetchLocation.java b/app/src/main/java/com/dancedeets/android/FetchLocation.java index 034f2db..ddabcf2 100644 --- a/app/src/main/java/com/dancedeets/android/FetchLocation.java +++ b/app/src/main/java/com/dancedeets/android/FetchLocation.java @@ -1,11 +1,8 @@ package com.dancedeets.android; import android.app.Activity; -import android.location.Address; -import android.location.Geocoder; import android.location.Location; import android.os.Bundle; -import android.text.TextUtils; import android.util.Log; import com.google.android.gms.common.ConnectionResult; @@ -14,10 +11,6 @@ import com.google.android.gms.location.FusedLocationProviderApi; import com.google.android.gms.location.LocationServices; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - /** * Created by lambert on 2014/11/26. */ @@ -27,74 +20,19 @@ public class FetchLocation implements GoogleApiClient.ConnectionCallbacks { private GoogleApiClient mGoogleApiClient; private FusedLocationProviderApi mLocationProviderApi = LocationServices.FusedLocationApi; - private Geocoder mGeocoder; - private Location mLocation; - private ReverseGeocodeTask mReverseGeocodeTask; - private AddressListener mAddressListener; + private LocationListener mLocationListener; - public interface AddressListener { - void onLocationFound(Location location ); - void onAddressFound(Location location, Address address); + public interface LocationListener { + void onLocationFound(Location location); } public FetchLocation() { } - public static String formatAddress(Address address) { - List components = new ArrayList<>(); - // We really need *something* smaller than the AdminArea/State level. - // Especially since there might not be a State sometimes (ie Helsinki, Finland). - if (address.getLocality() != null) { - // Sometimes there is only a Locality: - // LatLong=35.6583942,139.6990928 - // SubLocality=null - // Locality=Shibuya - // SubAdminArea=null - // AdminArea=Tokyo - components.add(address.getLocality()); - } else if (address.getSubAdminArea() != null) { - // Sometimes there is only a SubAdminArea: - // LatLong=60.1836354,24.9206748 - // SubLocality=null - // Locality=null - // SubAdminArea=Helsinki - // AdminArea=null - components.add(address.getSubAdminArea()); - } else if (address.getSubLocality() != null) { - // Sometimes there is only a SubLocality: - // LatLong=40.790278,-73.959722 - // SubLocality=Dundas - // Locality=null - // SubAdminArea=null - // AdminArea=Ontario - // Dundas appears to be the smallest unit of geography, - // so we check for it in the third if-block, hoping to find a proper city first. - components.add(address.getSubLocality()); - } - // Sometimes there is too much data, and we want to drop a lot of it: - // LatLong=40.790278,-73.959722 - // SubLocality=Manhattan - // Locality=New York (the city) - // SubAdminArea=New York (the county) - // AdminArea=New York (the state) - // In this case, we just want to grab the Locality (first if-block above) - - // Then grab the States/Province/etc (for those who have it) - if (address.getAdminArea() != null) { - components.add(address.getAdminArea()); - } - // And finally the Country, which should always be there...unless....I'm on a boat! - // So let's be safe and make this optional, in which case we basically take whatever we can get - if (address.getCountryName() != null) { - components.add(address.getCountryName()); - } - return TextUtils.join(", ", components); - } - - private void onAddressFound(Address address) { - if (mAddressListener != null) { - mAddressListener.onAddressFound(mLocation, address); + private void onLocationFound(Location location) { + if (mLocationListener != null) { + mLocationListener.onLocationFound(location); } } @@ -102,11 +40,10 @@ private void onAddressFound(Address address) { // So we can safely use it to initialize variables here, but that's it. // If we do want to store it (like in FetchLocationWithDialog), // then we need to make sure the local reference gets cleaned up appropriately. - public void onStart(Activity activity, AddressListener addressListener) { + public void onStart(Activity activity, LocationListener addressListener) { Log.i(LOG_TAG, "onStart, called from " + activity); - mAddressListener = addressListener; + mLocationListener = addressListener; // Connect the client. - mGeocoder = new Geocoder(activity, Locale.getDefault()); initializeGoogleApiClient(activity); if (mGoogleApiClient != null) { mGoogleApiClient.connect(); @@ -128,7 +65,7 @@ protected void initializeGoogleApiClient(Activity activity) { .build(); } else { Log.e(LOG_TAG, "Unable to connect to Google Play Services"); - onAddressFound(null); + onLocationFound(null); } } @@ -138,10 +75,7 @@ public void onStop() { if (mGoogleApiClient != null) { mGoogleApiClient.disconnect(); } - mAddressListener = null; - if (mReverseGeocodeTask != null) { - mReverseGeocodeTask.cancel(true); - } + mLocationListener = null; } @Override @@ -149,24 +83,9 @@ public void onConnected(Bundle bundle) { Log.i(LOG_TAG, "GoogleApiClient.onConnected: " + bundle); // We reconnect every time the app wakes up, but we only need // to fetch on start if we have no location data (ie, app startup). - mLocation = mLocationProviderApi.getLastLocation(mGoogleApiClient); - Log.i(LOG_TAG, "Reverse geocoding: " + mLocation); - if (mLocation != null) { - if (mAddressListener != null) { - mAddressListener.onLocationFound(mLocation); - } - // It's okay that this has an implicit reference to this parent class. - // This class will be around as long as the underlying geocode task is running, - // and when this class is destroyed via onStop, we cancel this task. - mReverseGeocodeTask = new ReverseGeocodeTask(mGeocoder) { - protected void onPostExecute(Address address) { - onAddressFound(address); - } - }; - mReverseGeocodeTask.execute(mLocation); - } else { - onAddressFound(null); - } + Location location = mLocationProviderApi.getLastLocation(mGoogleApiClient); + Log.i(LOG_TAG, "Reverse geocoding: " + location); + onLocationFound(location); } @Override diff --git a/app/src/main/java/com/dancedeets/android/LoginActivity.java b/app/src/main/java/com/dancedeets/android/LoginActivity.java index 6741ebf..474b3f6 100644 --- a/app/src/main/java/com/dancedeets/android/LoginActivity.java +++ b/app/src/main/java/com/dancedeets/android/LoginActivity.java @@ -57,20 +57,16 @@ public void clickedUseWebsite(View view) { } } - private static class SendAuthRequest implements FetchLocation.AddressListener { + private static class SendAuthRequest implements FetchAddress.AddressListener { private static final String LOG_TAG = "SendAuthRequest"; private final AccessToken mAccessToken; - private final FetchLocation mFetchLocation; + private final FetchAddress mFetchAddress; - SendAuthRequest(AccessToken accessToken, FetchLocation fetchLocation) { - Crashlytics.log(Log.INFO, LOG_TAG, "Received access token " + accessToken + ", with " + fetchLocation); + SendAuthRequest(AccessToken accessToken, FetchAddress fetchAddress) { + Crashlytics.log(Log.INFO, LOG_TAG, "Received access token " + accessToken + ", with " + fetchAddress); mAccessToken = accessToken; - mFetchLocation = fetchLocation; - } - - @Override - public void onLocationFound(Location location) { + mFetchAddress = fetchAddress; } @Override @@ -81,7 +77,7 @@ public void onAddressFound(Location location, Address address) { String addressString = null; if (address != null) { - addressString = FetchLocation.formatAddress(address); + addressString = FetchAddress.formatAddress(address); // Only do this if we have an address, so future events get tagged with the user's location try { @@ -96,7 +92,7 @@ public void onAddressFound(Location location, Address address) { } DanceDeetsApi.sendAuth(mAccessToken, addressString); - mFetchLocation.onStop(); + mFetchAddress.onStop(); } } @@ -134,8 +130,8 @@ public void handleLogin(AccessToken accessToken) { request.setParameters(parameters); request.executeAsync(); - FetchLocation fetchLocation = new FetchLocation(); - fetchLocation.onStart(LoginActivity.this, new SendAuthRequest(accessToken, fetchLocation)); + FetchAddress fetchAddress = new FetchAddress(); + fetchAddress.onStart(LoginActivity.this, new SendAuthRequest(accessToken, fetchAddress)); Intent intent = new Intent(LoginActivity.this, SearchListActivity.class); intent.setAction(Intent.ACTION_DEFAULT); diff --git a/app/src/main/java/com/dancedeets/android/SearchListActivity.java b/app/src/main/java/com/dancedeets/android/SearchListActivity.java index fe5fc0d..d713e97 100644 --- a/app/src/main/java/com/dancedeets/android/SearchListActivity.java +++ b/app/src/main/java/com/dancedeets/android/SearchListActivity.java @@ -30,7 +30,7 @@ import java.util.ArrayList; -public class SearchListActivity extends FacebookActivity implements StateHolder, EventListFragment.Callbacks, SearchDialogFragment.OnSearchListener, FetchLocation.AddressListener, SearchPagerAdapter.SearchOptionsManager { +public class SearchListActivity extends FacebookActivity implements StateHolder, EventListFragment.Callbacks, SearchDialogFragment.OnSearchListener, FetchLocation.LocationListener, FetchAddress.AddressListener, SearchPagerAdapter.SearchOptionsManager { private static final String LOG_TAG = "SearchListActivity"; @@ -43,6 +43,7 @@ public class SearchListActivity extends FacebookActivity implements StateHolder< private ViewPager mViewPager; private FetchLocation mFetchLocation; + private FetchAddress mFetchAddress; // These are exposed as member variables for the sake of testing. SearchDialogFragment mSearchDialog; @@ -147,17 +148,20 @@ protected void onSaveInstanceState(@NonNull Bundle outState) { public void onStart() { super.onStart(); if (mBundled.mSearchOptions.isEmpty()) { - mFetchLocation = new FetchLocation(); - mFetchLocation.onStart(this, this); + mFetchAddress = new FetchAddress(); + mFetchAddress.onStart(this, this); } + mFetchLocation = new FetchLocation(); + mFetchLocation.onStart(this, this); } @Override public void onStop() { super.onStop(); - if (mFetchLocation != null) { - mFetchLocation.onStop(); + if (mFetchAddress != null) { + mFetchAddress.onStop(); } + mFetchLocation.onStop(); } public void startSearchFor(SearchOptions newSearchOptions) { @@ -198,7 +202,7 @@ public void onAddressFound(Location location, Address address) { String optionalSubLocality = (address != null) ? " (with SubLocality " + address.getSubLocality() + ")" : ""; Crashlytics.log(Log.INFO, LOG_TAG, "Address found: " + address + optionalSubLocality); if (address != null) { - String addressString = FetchLocation.formatAddress(address); + String addressString = FetchAddress.formatAddress(address); startSearchFor(new SearchOptions(addressString)); } else { if (location == null) { From eb79969274a9cdeccccf08f639e66f2303c3d617 Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Fri, 9 Oct 2015 00:37:35 -0700 Subject: [PATCH 8/9] Factor out our MD5 function and use it to pass in a hashed UID to DfP for frequency capping purposes. --- .../com/dancedeets/android/AdManager.java | 13 +++++--- .../android/EventInfoPagerAdapter.java | 8 ----- .../java/com/dancedeets/android/Hashing.java | 33 +++++++++++++++++++ .../com/dancedeets/android/HelpSystem.java | 25 +------------- 4 files changed, 43 insertions(+), 36 deletions(-) create mode 100644 app/src/main/java/com/dancedeets/android/Hashing.java diff --git a/app/src/main/java/com/dancedeets/android/AdManager.java b/app/src/main/java/com/dancedeets/android/AdManager.java index dd89e64..c8a724c 100644 --- a/app/src/main/java/com/dancedeets/android/AdManager.java +++ b/app/src/main/java/com/dancedeets/android/AdManager.java @@ -2,6 +2,7 @@ import android.location.Location; +import com.facebook.AccessToken; import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.doubleclick.PublisherAdRequest; @@ -11,11 +12,15 @@ public class AdManager { public static PublisherAdRequest getAdRequest(Location location) { - PublisherAdRequest adRequest = new PublisherAdRequest.Builder() + PublisherAdRequest.Builder adRequestBuilder = new PublisherAdRequest.Builder() .addTestDevice(AdRequest.DEVICE_ID_EMULATOR) .addTestDevice("F92F46CF903B1E0BD86D386FC9813E7F") - .setLocation(location) - .build(); - return adRequest; + .setLocation(location); + AccessToken token = AccessToken.getCurrentAccessToken(); + if (token != null) { + String userID = token.getUserId(); + adRequestBuilder.setPublisherProvidedId(Hashing.md5(userID)); + } + return adRequestBuilder.build(); } } diff --git a/app/src/main/java/com/dancedeets/android/EventInfoPagerAdapter.java b/app/src/main/java/com/dancedeets/android/EventInfoPagerAdapter.java index 0dbc76b..e8b4341 100644 --- a/app/src/main/java/com/dancedeets/android/EventInfoPagerAdapter.java +++ b/app/src/main/java/com/dancedeets/android/EventInfoPagerAdapter.java @@ -53,14 +53,6 @@ public Object instantiateItem(ViewGroup container, int position) { return fragment; } - public EventInfoFragment getExistingItem(int i) { - if (i < mFragments.size()) { - return mFragments.get(i); - } else { - return null; - } - } - @Override public Fragment getItem(int i) { FullEvent event = mEventList.get(i); diff --git a/app/src/main/java/com/dancedeets/android/Hashing.java b/app/src/main/java/com/dancedeets/android/Hashing.java new file mode 100644 index 0000000..78b2a3b --- /dev/null +++ b/app/src/main/java/com/dancedeets/android/Hashing.java @@ -0,0 +1,33 @@ +package com.dancedeets.android; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * Created by lambert on 2015/10/09. + */ +public class Hashing { + public static final String md5(final String s) { + final String MD5 = "MD5"; + try { + // Create MD5 Hash + MessageDigest digest = java.security.MessageDigest.getInstance(MD5); + digest.update(s.getBytes()); + byte messageDigest[] = digest.digest(); + + // Create Hex String + StringBuilder hexString = new StringBuilder(); + for (byte aMessageDigest : messageDigest) { + String h = Integer.toHexString(0xFF & aMessageDigest); + while (h.length() < 2) + h = "0" + h; + hexString.append(h); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return ""; + } + +} diff --git a/app/src/main/java/com/dancedeets/android/HelpSystem.java b/app/src/main/java/com/dancedeets/android/HelpSystem.java index c63ba11..b926bb9 100644 --- a/app/src/main/java/com/dancedeets/android/HelpSystem.java +++ b/app/src/main/java/com/dancedeets/android/HelpSystem.java @@ -26,36 +26,13 @@ public static void openHelp(Activity activity) { } } - public static final String md5(final String s) { - final String MD5 = "MD5"; - try { - // Create MD5 Hash - MessageDigest digest = java.security.MessageDigest.getInstance(MD5); - digest.update(s.getBytes()); - byte messageDigest[] = digest.digest(); - - // Create Hex String - StringBuilder hexString = new StringBuilder(); - for (byte aMessageDigest : messageDigest) { - String h = Integer.toHexString(0xFF & aMessageDigest); - while (h.length() < 2) - h = "0" + h; - hexString.append(h); - } - return hexString.toString(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return ""; - } - public static void openAddEvent(SearchListActivity activity) { AnalyticsUtil.track("Add Event"); String url = "http://www.dancedeets.com/events_add?hl=" + Locale.getDefault().getLanguage(); AccessToken accessToken = AccessToken.getCurrentAccessToken(); if (accessToken != null) { String uid = accessToken.getUserId(); - String accessTokenMD5 = md5(accessToken.getToken()); + String accessTokenMD5 = Hashing.md5(accessToken.getToken()); url += "&uid=" + uid + "&access_token_md5=" + accessTokenMD5; } Crashlytics.log(Log.INFO, LOG_TAG, "Opening URL: " + url); From bc8187dc342d65b77ef6214e25acec5b729e12e6 Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Fri, 9 Oct 2015 02:30:58 -0700 Subject: [PATCH 9/9] Add comment about device name. --- app/src/main/java/com/dancedeets/android/AdManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/dancedeets/android/AdManager.java b/app/src/main/java/com/dancedeets/android/AdManager.java index c8a724c..c73de97 100644 --- a/app/src/main/java/com/dancedeets/android/AdManager.java +++ b/app/src/main/java/com/dancedeets/android/AdManager.java @@ -14,7 +14,7 @@ public class AdManager { public static PublisherAdRequest getAdRequest(Location location) { PublisherAdRequest.Builder adRequestBuilder = new PublisherAdRequest.Builder() .addTestDevice(AdRequest.DEVICE_ID_EMULATOR) - .addTestDevice("F92F46CF903B1E0BD86D386FC9813E7F") + .addTestDevice("F92F46CF903B1E0BD86D386FC9813E7F") // Mike's Nexus 5 .setLocation(location); AccessToken token = AccessToken.getCurrentAccessToken(); if (token != null) {