diff --git a/app/src/main/java/org/gdg/frisbee/android/api/PlusApi.java b/app/src/main/java/org/gdg/frisbee/android/api/PlusApi.java new file mode 100644 index 000000000..f987a59fb --- /dev/null +++ b/app/src/main/java/org/gdg/frisbee/android/api/PlusApi.java @@ -0,0 +1,18 @@ +package org.gdg.frisbee.android.api; + +import org.gdg.frisbee.android.BuildConfig; +import org.gdg.frisbee.android.api.model.plus.ImageInfo; +import org.gdg.frisbee.android.api.model.plus.Person; + +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Path; + +public interface PlusApi { + @GET("people/{gplusId}?fields=image&key=" + BuildConfig.IP_SIMPLE_API_ACCESS_KEY) + Call getImageInfo(@Path("gplusId") String gplusId); + + @GET("people/{gplusId}?fields=image,aboutMe,tagline,urls,url,cover,displayName&key=" + + BuildConfig.IP_SIMPLE_API_ACCESS_KEY) + Person getPerson(@Path("gplusId") String gplusId); +} diff --git a/app/src/main/java/org/gdg/frisbee/android/api/PlusApiFactory.java b/app/src/main/java/org/gdg/frisbee/android/api/PlusApiFactory.java new file mode 100644 index 000000000..1a30404a1 --- /dev/null +++ b/app/src/main/java/org/gdg/frisbee/android/api/PlusApiFactory.java @@ -0,0 +1,25 @@ +package org.gdg.frisbee.android.api; + +import org.gdg.frisbee.android.app.App; + +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class PlusApiFactory { + private static final String API_URL = "https://www.googleapis.com/plus/v1/"; + + private PlusApiFactory() { + } + + private static Retrofit provideRestAdapter() { + return new Retrofit.Builder() + .baseUrl(API_URL) + .addConverterFactory(GsonConverterFactory.create()) + .client(OkClientFactory.okHttpClientWithIdlingResources(App.getInstance().getOkHttpClient())) + .build(); + } + + public static PlusApi providePlusApi() { + return provideRestAdapter().create(PlusApi.class); + } +} diff --git a/app/src/main/java/org/gdg/frisbee/android/api/PlusImageResizer.java b/app/src/main/java/org/gdg/frisbee/android/api/PlusImageResizer.java new file mode 100644 index 000000000..4e357e21f --- /dev/null +++ b/app/src/main/java/org/gdg/frisbee/android/api/PlusImageResizer.java @@ -0,0 +1,41 @@ +package org.gdg.frisbee.android.api; + +import org.gdg.frisbee.android.api.model.plus.ImageInfo; +import org.gdg.frisbee.android.app.App; + +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class PlusImageResizer implements Interceptor { + + private static final Pattern mPlusPattern + = Pattern.compile("http[s]?:\\/\\/plus\\..*google\\.com.*(\\+[a-zA-Z] +|[0-9]{21}).*"); + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + Matcher matcher = mPlusPattern.matcher(request.url().toString()); + if (!matcher.matches()) { + return chain.proceed(request); + } + + String gplusId = matcher.group(1); + retrofit2.Response imageInfoResponse + = App.getInstance().getPlusApi().getImageInfo(gplusId).execute(); + if (imageInfoResponse.isSuccessful()) { + ImageInfo imageInfo = imageInfoResponse.body(); + if (imageInfo.getImage() != null && imageInfo.getImage().getUrl() != null) { + String imageUrl = imageInfo.getImage().getUrl().replace("sz=50", "sz=196"); + return chain.proceed(request.newBuilder().url(imageUrl).build()); + } + } + + return null; + } +} diff --git a/app/src/main/java/org/gdg/frisbee/android/api/PlusPersonDownloader.java b/app/src/main/java/org/gdg/frisbee/android/api/PlusPersonDownloader.java deleted file mode 100644 index bb367b3ff..000000000 --- a/app/src/main/java/org/gdg/frisbee/android/api/PlusPersonDownloader.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.gdg.frisbee.android.api; - -import android.support.annotation.Nullable; - -import com.google.api.services.plus.Plus; -import com.google.api.services.plus.model.Person; - -import org.gdg.frisbee.android.Const; -import org.gdg.frisbee.android.app.App; -import org.joda.time.DateTime; - -import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import okhttp3.Interceptor; -import okhttp3.Request; -import okhttp3.Response; -import timber.log.Timber; - -public class PlusPersonDownloader implements Interceptor { - - private static final Pattern mPlusPattern - = Pattern.compile("http[s]?:\\/\\/plus\\..*google\\.com.*(\\+[a-zA-Z] +|[0-9]{21}).*"); - private Plus plusClient; - - public PlusPersonDownloader(Plus plusClient) { - this.plusClient = plusClient; - } - - @Nullable - public static Person getPersonSync(final String gplusId) { - return getPersonSync(App.getInstance().getPlusClient(), gplusId); - } - - @Nullable - public static Person getPersonSync(final Plus plusClient, final String gplusId) { - - final String cacheUrl = Const.CACHE_KEY_PERSON + gplusId; - Object cachedPerson = App.getInstance().getModelCache().get(cacheUrl); - Person person = null; - - if (cachedPerson instanceof Person) { - person = (Person) cachedPerson; - if (person.getImage() != null) { - Timber.d("Cache hit: %s", gplusId); - return person; - } - } - if (cachedPerson != null) { - App.getInstance().getModelCache().remove(cacheUrl); - Timber.d("Cache removal: %s", gplusId); - } - - try { - Plus.People.Get request = plusClient.people().get(gplusId); - request.setFields("id,aboutMe,cover/coverPhoto/url,image/url,displayName,tagline,url,urls"); - person = request.execute(); - App.getInstance().getModelCache().put(cacheUrl, person, DateTime.now().plusDays(2)); - - Timber.d("Request: %s", gplusId); - } catch (IOException e) { - Timber.e(e, "Error while getting profile URL."); - } - - return person; - } - - @Override - public Response intercept(Chain chain) throws IOException { - Request request = chain.request(); - - Matcher matcher = mPlusPattern.matcher(request.url().toString()); - if (!matcher.matches()) { - return chain.proceed(request); - } - - String gplusId = matcher.group(1); - Person person = getPersonSync(plusClient, gplusId); - if (person != null && person.getImage() != null && person.getImage().getUrl() != null) { - String imageUrl = person.getImage().getUrl().replace("sz=50", "sz=196"); - return chain.proceed(request.newBuilder().url(imageUrl).build()); - } - - return null; - } -} diff --git a/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Cover.java b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Cover.java new file mode 100644 index 000000000..d8ae2866e --- /dev/null +++ b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Cover.java @@ -0,0 +1,9 @@ +package org.gdg.frisbee.android.api.model.plus; + +public class Cover { + CoverPhoto coverPhoto; + + public CoverPhoto getCoverPhoto() { + return coverPhoto; + } +} diff --git a/app/src/main/java/org/gdg/frisbee/android/api/model/plus/CoverPhoto.java b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/CoverPhoto.java new file mode 100644 index 000000000..db3512deb --- /dev/null +++ b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/CoverPhoto.java @@ -0,0 +1,9 @@ +package org.gdg.frisbee.android.api.model.plus; + +public class CoverPhoto { + String url; + + public String getUrl() { + return url; + } +} diff --git a/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Image.java b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Image.java new file mode 100644 index 000000000..a41c61c9f --- /dev/null +++ b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Image.java @@ -0,0 +1,14 @@ +package org.gdg.frisbee.android.api.model.plus; + +public class Image { + private String url; + private boolean isDefault; + + public String getUrl() { + return url; + } + + public boolean isDefault() { + return isDefault; + } +} diff --git a/app/src/main/java/org/gdg/frisbee/android/api/model/plus/ImageInfo.java b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/ImageInfo.java new file mode 100644 index 000000000..e37dd1775 --- /dev/null +++ b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/ImageInfo.java @@ -0,0 +1,13 @@ +package org.gdg.frisbee.android.api.model.plus; + +public class ImageInfo { + private Image image; + + public Image getImage() { + return image; + } + + public String getUrl() { + return image.getUrl(); + } +} diff --git a/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Person.java b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Person.java new file mode 100644 index 000000000..abfee5fb2 --- /dev/null +++ b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Person.java @@ -0,0 +1,41 @@ +package org.gdg.frisbee.android.api.model.plus; + +import java.util.List; + +public class Person { + private String url; + private String tagline; + private String aboutMe; + private ImageInfo image; + private Cover cover; + private List urls; + private String displayName; + + public String getUrl() { + return url; + } + + public String getTagline() { + return tagline; + } + + public String getAboutMe() { + return aboutMe; + } + + public ImageInfo getImage() { + return image; + } + + public Cover getCover() { + return cover; + } + + public List getUrls() { + return urls; + } + + public String getDisplayName() { + return displayName; + } +} diff --git a/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Urls.java b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Urls.java new file mode 100644 index 000000000..aa0768782 --- /dev/null +++ b/app/src/main/java/org/gdg/frisbee/android/api/model/plus/Urls.java @@ -0,0 +1,19 @@ +package org.gdg.frisbee.android.api.model.plus; + +public class Urls { + String label; + String type; + String value; + + public String getLabel() { + return label; + } + + public String getType() { + return type; + } + + public String getValue() { + return value; + } +} diff --git a/app/src/main/java/org/gdg/frisbee/android/app/App.java b/app/src/main/java/org/gdg/frisbee/android/app/App.java index 27704d79c..be6fea8b6 100644 --- a/app/src/main/java/org/gdg/frisbee/android/app/App.java +++ b/app/src/main/java/org/gdg/frisbee/android/app/App.java @@ -52,7 +52,9 @@ import org.gdg.frisbee.android.api.GroupDirectory; import org.gdg.frisbee.android.api.GroupDirectoryFactory; import org.gdg.frisbee.android.api.OkClientFactory; -import org.gdg.frisbee.android.api.PlusPersonDownloader; +import org.gdg.frisbee.android.api.PlusApi; +import org.gdg.frisbee.android.api.PlusApiFactory; +import org.gdg.frisbee.android.api.PlusImageResizer; import org.gdg.frisbee.android.cache.ModelCache; import org.gdg.frisbee.android.eventseries.TaggedEventSeries; import org.gdg.frisbee.android.utils.CrashlyticsTree; @@ -85,6 +87,7 @@ public class App extends BaseApp implements LocationListener { private ArrayList mTaggedEventSeriesList; private RefWatcher refWatcher; private Plus plusClient; + private PlusApi plusApiInstance; public static App getInstance() { return mInstance; @@ -140,7 +143,7 @@ public void onCreate() { // Only the interceptors will be different. // We shouldn't have the below interceptor in other instances. OkHttpClient.Builder picassoClient = mOkHttpClient.newBuilder(); - picassoClient.addInterceptor(new PlusPersonDownloader(plusClient)); + picassoClient.addInterceptor(new PlusImageResizer()); mPicasso = new Picasso.Builder(this) .downloader(new OkHttp3Downloader(picassoClient.build())) @@ -342,6 +345,13 @@ public GitHub getGithub() { return gitHubInstance; } + public PlusApi getPlusApi() { + if (plusApiInstance == null) { + plusApiInstance = PlusApiFactory.providePlusApi(); + } + return plusApiInstance; + } + public OkHttpClient getOkHttpClient() { return mOkHttpClient; } diff --git a/app/src/main/java/org/gdg/frisbee/android/chapter/InfoFragment.java b/app/src/main/java/org/gdg/frisbee/android/chapter/InfoFragment.java index 1239a4e16..6aafa1a04 100644 --- a/app/src/main/java/org/gdg/frisbee/android/chapter/InfoFragment.java +++ b/app/src/main/java/org/gdg/frisbee/android/chapter/InfoFragment.java @@ -32,12 +32,12 @@ import android.widget.ScrollView; import android.widget.TextView; -import com.google.api.services.plus.model.Person; import com.tasomaniac.android.widget.DelayedProgressBar; import org.gdg.frisbee.android.Const; import org.gdg.frisbee.android.R; -import org.gdg.frisbee.android.api.PlusPersonDownloader; +import org.gdg.frisbee.android.api.model.plus.Person; +import org.gdg.frisbee.android.api.model.plus.Urls; import org.gdg.frisbee.android.app.App; import org.gdg.frisbee.android.cache.ModelCache; import org.gdg.frisbee.android.common.BaseFragment; @@ -90,7 +90,7 @@ public Person[] doInBackground(String... params) { for (int i = 0; i < params.length; i++) { Timber.d("Get Organizer " + params[i]); if (isAdded()) { - people[i] = PlusPersonDownloader.getPersonSync(params[i]); + people[i] = App.getInstance().getPlusApi().getPerson(params[i]); } else { // fragment is not used anymore people[i] = null; @@ -129,7 +129,7 @@ public void onActivityCreated(Bundle savedInstanceState) { @Override public Person doInBackground(String... params) { if (isAdded()) { - return PlusPersonDownloader.getPersonSync(chapterPlusId); + return App.getInstance().getPlusApi().getPerson(chapterPlusId); } else { // fragment is not used anymore return null; @@ -153,11 +153,11 @@ public void onPostExecute(String[] params, Person person) { new ModelCache.CacheListener() { @Override public void onGet(Object item) { - final Person chachedChapter = (Person) item; - updateChapterUIFrom(chachedChapter); + final Person cachedChapter = (Person) item; + updateChapterUIFrom(cachedChapter); - for (int chapterIndex = 0; chapterIndex < chachedChapter.getUrls().size(); chapterIndex++) { - Person.Urls url = chachedChapter.getUrls().get(chapterIndex); + for (int chapterIndex = 0; chapterIndex < cachedChapter.getUrls().size(); chapterIndex++) { + Urls url = cachedChapter.getUrls().get(chapterIndex); if (url.getValue().contains("plus.google.com/") && !url.getValue().contains("communities")) { @@ -172,7 +172,7 @@ public void onGet(Object item) { @Override public void onGet(Object item) { addOrganizerToUI((Person) item); - if (indexAsFinal == chachedChapter.getUrls().size()) { + if (indexAsFinal == cachedChapter.getUrls().size()) { setIsLoading(false); } } @@ -180,7 +180,7 @@ public void onGet(Object item) { @Override public void onNotFound(String key) { addUnknowOrganizerToUI(); - if (indexAsFinal == chachedChapter.getUrls().size()) { + if (indexAsFinal == cachedChapter.getUrls().size()) { setIsLoading(false); } } @@ -265,7 +265,7 @@ private Spanned getAboutText(Person person) { private void updateOrganizersOnline(final Person person) { if (person.getUrls() != null) { - for (Person.Urls url : person.getUrls()) { + for (Urls url : person.getUrls()) { if (url.getValue().contains("plus.google.com/")) { if (url.getValue().contains("communities")) { // TODO @@ -285,7 +285,7 @@ private void updateOrganizersOnline(final Person person) { } else { TextView tv = (TextView) mInflater .inflate(R.layout.list_resource_item, (ViewGroup) getView(), false); - tv.setText(Html.fromHtml("" + url.get("label") + "")); + tv.setText(Html.fromHtml("" + url.getLabel() + "")); mResourcesBox.addView(tv); } @@ -294,7 +294,7 @@ private void updateOrganizersOnline(final Person person) { } } - private String getGPlusIdFromPersonUrl(Person.Urls personUrl) { + private String getGPlusIdFromPersonUrl(Urls personUrl) { final String plusId = getArguments().getString(Const.EXTRA_PLUS_ID, ""); if (personUrl.getValue().contains("+")) { try { diff --git a/app/src/main/java/org/gdg/frisbee/android/common/GdgNavDrawerActivity.java b/app/src/main/java/org/gdg/frisbee/android/common/GdgNavDrawerActivity.java index 58a355cd9..c3c9ba0eb 100644 --- a/app/src/main/java/org/gdg/frisbee/android/common/GdgNavDrawerActivity.java +++ b/app/src/main/java/org/gdg/frisbee/android/common/GdgNavDrawerActivity.java @@ -35,13 +35,12 @@ import android.widget.ImageView; import com.google.android.gms.games.Games; -import com.google.api.services.plus.model.Person; import org.gdg.frisbee.android.Const; import org.gdg.frisbee.android.R; import org.gdg.frisbee.android.about.AboutActivity; import org.gdg.frisbee.android.activity.SettingsActivity; -import org.gdg.frisbee.android.api.PlusPersonDownloader; +import org.gdg.frisbee.android.api.model.plus.Person; import org.gdg.frisbee.android.app.App; import org.gdg.frisbee.android.arrow.ArrowActivity; import org.gdg.frisbee.android.chapter.MainActivity; @@ -401,7 +400,7 @@ private void maybeUpdateChapterImage() { @Override public Person doInBackground(String... params) { - return PlusPersonDownloader.getPersonSync(params[0]); + return App.getInstance().getPlusApi().getPerson(params[0]); } }) .setOnPostExecuteListener(new CommonAsyncTask.OnPostExecuteListener() { diff --git a/app/src/main/java/org/gdg/frisbee/android/event/EventOverviewFragment.java b/app/src/main/java/org/gdg/frisbee/android/event/EventOverviewFragment.java index b4aa00fd2..9e0d8b1d5 100644 --- a/app/src/main/java/org/gdg/frisbee/android/event/EventOverviewFragment.java +++ b/app/src/main/java/org/gdg/frisbee/android/event/EventOverviewFragment.java @@ -36,11 +36,6 @@ import android.widget.ImageView; import android.widget.TextView; -import com.google.android.gms.common.api.CommonStatusCodes; -import com.google.android.gms.common.api.ResultCallback; -import com.google.android.gms.plus.People; -import com.google.android.gms.plus.Plus; -import com.google.android.gms.plus.model.people.Person; import com.squareup.picasso.Picasso; import com.squareup.picasso.Target; import com.tasomaniac.android.widget.DelayedProgressBar; @@ -51,6 +46,7 @@ import org.gdg.frisbee.android.api.model.Chapter; import org.gdg.frisbee.android.api.model.Directory; import org.gdg.frisbee.android.api.model.EventFullDetails; +import org.gdg.frisbee.android.api.model.plus.ImageInfo; import org.gdg.frisbee.android.app.App; import org.gdg.frisbee.android.cache.ModelCache; import org.gdg.frisbee.android.common.BaseFragment; @@ -61,6 +57,8 @@ import butterknife.Bind; import butterknife.ButterKnife; +import retrofit2.Call; +import retrofit2.Response; public class EventOverviewFragment extends BaseFragment { @@ -220,39 +218,47 @@ private void updateGroupDetails(Chapter group) { return; } - Plus.PeopleApi.load(((GdgActivity) getActivity()).getGoogleApiClient(), group.getGplusId()) - .setResultCallback(new ResultCallback() { - @Override - public void onResult(People.LoadPeopleResult loadPeopleResult) { - if (loadPeopleResult.getStatus().getStatusCode() == CommonStatusCodes.SUCCESS) { - Person gplusChapter = loadPeopleResult.getPersonBuffer().get(0); - if (gplusChapter.getImage().hasUrl()) { - Picasso.with(getActivity()).load(gplusChapter.getImage().getUrl()).into(new Target() { - @Override - public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) { - if (!isAdded()) { - return; - } - BitmapDrawable logo = new BitmapDrawable(getResources(), bitmap); - mGroupLogo.setVisibility(View.VISIBLE); - mGroupLogo.setImageDrawable(logo); - } - - @Override - public void onBitmapFailed(Drawable drawable) { - mGroupLogo.setVisibility(View.INVISIBLE); - } - - @Override - public void onPrepareLoad(Drawable drawable) { - - } - }); + loadChapterImageInto(group.getGplusId(), mGroupLogo); + + ((GdgActivity) getActivity()).setToolbarTitle(group.getShortName()); + } + + private void loadChapterImageInto(String gplusId, ImageView groupLogo) { + App.getInstance().getPlusApi().getImageInfo(gplusId).enqueue(new retrofit2.Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + App.getInstance().getPicasso().load(response.body().getImage().getUrl()).into(new Target() { + @Override + public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) { + if (!isAdded()) { + return; + } + BitmapDrawable logo = new BitmapDrawable(getResources(), bitmap); + mGroupLogo.setVisibility(View.VISIBLE); + mGroupLogo.setImageDrawable(logo); } - } + + @Override + public void onBitmapFailed(Drawable drawable) { + mGroupLogo.setVisibility(View.INVISIBLE); + } + + @Override + public void onPrepareLoad(Drawable drawable) { + + } + }); + } else { + mGroupLogo.setVisibility(View.INVISIBLE); } - }); - ((GdgActivity) getActivity()).setToolbarTitle(group.getShortName()); + } + + @Override + public void onFailure(Call call, Throwable t) { + mGroupLogo.setVisibility(View.INVISIBLE); + } + }); } private void setIsLoading(boolean isLoading) {