Skip to content

Commit

Permalink
Add a fallback url for when main urls don't work
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmedre committed Dec 29, 2020
1 parent b28fa79 commit ef8005a
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.quran.data.source.PageProvider
import com.quran.labs.androidquran.presenter.Presenter
import com.quran.labs.androidquran.util.ImageUtil
import com.quran.labs.androidquran.util.QuranFileUtils
import com.quran.labs.androidquran.util.UrlUtil
import dagger.Reusable
import io.reactivex.Scheduler
import io.reactivex.disposables.CompositeDisposable
Expand All @@ -17,6 +18,7 @@ class PageSelectPresenter @Inject
constructor(private val imageUtil: ImageUtil,
private val quranFileUtils: QuranFileUtils,
private val mainThreadScheduler: Scheduler,
private val urlUtil: UrlUtil,
private val pageTypes:
Map<@JvmSuppressWildcards String, @JvmSuppressWildcards PageProvider>) :
Presenter<PageSelectActivity> {
Expand Down Expand Up @@ -44,6 +46,8 @@ class PageSelectPresenter @Inject
val url = "$baseUrl/${it.key}.png"
compositeDisposable.add(
imageUtil.downloadImage(url, previewImage)
.onErrorResumeNext(
imageUtil.downloadImage(urlUtil.fallbackUrl(url), previewImage))
.subscribeOn(Schedulers.io())
.observeOn(mainThreadScheduler)
.subscribe({ generateData() }, { e -> Timber.e(e) })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import android.content.Context;
import android.util.Pair;
import android.util.SparseArray;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.quran.labs.androidquran.common.LocalTranslation;
import com.quran.labs.androidquran.dao.translation.Translation;
import com.quran.labs.androidquran.dao.translation.TranslationItem;
Expand All @@ -15,24 +16,20 @@
import com.quran.labs.androidquran.ui.TranslationManagerActivity;
import com.quran.labs.androidquran.util.QuranFileUtils;
import com.quran.labs.androidquran.util.QuranSettings;
import com.quran.labs.androidquran.util.UrlUtil;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Singleton;

import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
Expand All @@ -51,6 +48,7 @@ public class TranslationManagerPresenter implements Presenter<TranslationManager
private final QuranSettings quranSettings;
private final QuranFileUtils quranFileUtils;
private final TranslationsDBAdapter translationsDBAdapter;
private final UrlUtil urlUtil;

@VisibleForTesting String host;
private TranslationManagerActivity currentActivity;
Expand All @@ -60,13 +58,15 @@ public class TranslationManagerPresenter implements Presenter<TranslationManager
OkHttpClient okHttpClient,
QuranSettings quranSettings,
TranslationsDBAdapter dbAdapter,
QuranFileUtils quranFileUtils) {
QuranFileUtils quranFileUtils,
UrlUtil urlUtil) {
this.host = Constants.HOST;
this.appContext = appContext;
this.okHttpClient = okHttpClient;
this.quranSettings = quranSettings;
this.quranFileUtils = quranFileUtils;
this.translationsDBAdapter = dbAdapter;
this.urlUtil = urlUtil;
}

public void checkForUpdates() {
Expand Down Expand Up @@ -97,7 +97,7 @@ public void getTranslationsList(boolean forceDownload) {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableObserver<List<TranslationItem>>() {
@Override
public void onNext(List<TranslationItem> translationItems) {
public void onNext(@NonNull List<TranslationItem> translationItems) {
if (currentActivity != null) {
currentActivity.onTranslationsUpdated(translationItems);
}
Expand Down Expand Up @@ -152,13 +152,6 @@ public void updateItemOrdering(final List<TranslationItem> items) {
.subscribe();
}

@WorkerThread
public Observable<List<TranslationItem>> syncTranslationsWithCache() {
return getCachedTranslationListObservable()
.filter(translationList -> !translationList.getTranslations().isEmpty())
.map(translationList -> mergeWithServerTranslations(translationList.getTranslations()));
}

Observable<TranslationList> getCachedTranslationListObservable() {
return Observable.defer(() -> {
try {
Expand All @@ -179,9 +172,22 @@ Observable<TranslationList> getCachedTranslationListObservable() {
}

Observable<TranslationList> getRemoteTranslationListObservable() {
final String url = host + WEB_SERVICE_ENDPOINT;
return
downloadTranslationList(url)
.onErrorResumeNext(downloadTranslationList(urlUtil.fallbackUrl(url)))
.doOnNext(translationList -> {
translationList.getTranslations();
if (!translationList.getTranslations().isEmpty()) {
writeTranslationList(translationList);
}
});
}

private Observable<TranslationList> downloadTranslationList(String url) {
return Observable.fromCallable(() -> {
Request request = new Request.Builder()
.url(host + WEB_SERVICE_ENDPOINT)
.url(url)
.build();
Response response = okHttpClient.newCall(request).execute();

Expand All @@ -192,11 +198,6 @@ Observable<TranslationList> getRemoteTranslationListObservable() {
TranslationList result = jsonAdapter.fromJson(responseBody.source());
responseBody.close();
return result;
}).doOnNext(translationList -> {
translationList.getTranslations();
if (!translationList.getTranslations().isEmpty()) {
writeTranslationList(translationList);
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.quran.labs.androidquran.service.util.QuranDownloadNotifier.ProgressIntent;
import com.quran.labs.androidquran.util.QuranSettings;
import com.quran.labs.androidquran.util.QuranUtils;
import com.quran.labs.androidquran.util.UrlUtil;
import com.quran.labs.androidquran.util.ZipUtils;

import java.io.File;
Expand Down Expand Up @@ -98,6 +99,8 @@ public class QuranDownloadService extends Service implements
private ServiceHandler serviceHandler;
private QuranDownloadNotifier notifier;

private static boolean fallbackByDefault = false;

// written from ui thread and read by download thread
private volatile boolean isDownloadCanceled;
private LocalBroadcastManager broadcastManager;
Expand All @@ -109,10 +112,11 @@ public class QuranDownloadService extends Service implements
private Map<String, Intent> recentlyFailedDownloads = null;

// incremented from ui thread and decremented by download thread
private AtomicInteger currentOperations = new AtomicInteger(0);
private final AtomicInteger currentOperations = new AtomicInteger(0);

@Inject QuranInfo quranInfo;
@Inject OkHttpClient okHttpClient;
@Inject UrlUtil urlUtil;

private final class ServiceHandler extends Handler {

Expand Down Expand Up @@ -464,11 +468,8 @@ private boolean downloadFileWrapper(String urlString, String destination,
}

String url = urlString;
if (i > 0) {
// let's try http instead of https?
if (urlString.contains("quran.com") || urlString.contains("quranicaudio.com")) {
url = urlString.replace("https://", "http://");
}
if (fallbackByDefault || i > 0) {
url = urlUtil.fallbackUrl(url);

// want to wait before retrying again
try {
Expand All @@ -486,6 +487,7 @@ private boolean downloadFileWrapper(String urlString, String destination,
}

if (res == DOWNLOAD_SUCCESS) {
fallbackByDefault = (i > 0);
return true;
} else if (res == QuranDownloadNotifier.ERROR_DISK_SPACE ||
res == QuranDownloadNotifier.ERROR_PERMISSIONS) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ import javax.inject.Inject
class QuranFileUtils @Inject constructor(
context: Context,
private val pageProvider: PageProvider,
private val quranScreenInfo: QuranScreenInfo
private val quranScreenInfo: QuranScreenInfo,
private val urlUtil: UrlUtil
) {
// server urls
private val imageBaseUrl: String = pageProvider.getImagesBaseUrl()
Expand Down Expand Up @@ -267,7 +268,8 @@ class QuranFileUtils @Inject constructor(
filename: String,
isRetry: Boolean
): Response {
val urlString = (imageBaseUrl + "width" + widthParam + File.separator + filename)
val base = if (isRetry) urlUtil.fallbackUrl(imageBaseUrl) else imageBaseUrl
val urlString = (base + "width" + widthParam + File.separator + filename)
Timber.d("want to download: %s", urlString)
val request = Builder()
.url(urlString)
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/com/quran/labs/androidquran/util/UrlUtil.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.quran.labs.androidquran.util

import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class UrlUtil @Inject constructor() {

fun fallbackUrl(url: String): String {
return url.replace("android.quran.com", "quran.app")
.replace(".quranicaudio.com", ".quranicaudio.org")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.quran.labs.androidquran.util.QuranFileUtils;
import com.quran.labs.androidquran.util.QuranSettings;

import com.quran.labs.androidquran.util.UrlUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -37,7 +38,7 @@ public void setup() {
mockWebServer = new MockWebServer();
translationManager = new TranslationManagerPresenter(
mockAppContext, mockOkHttp, mockSettings, null,
mock(QuranFileUtils.class)) {
mock(QuranFileUtils.class), new UrlUtil()) {
@Override
void writeTranslationList(TranslationList list) {
// no op
Expand Down

0 comments on commit ef8005a

Please sign in to comment.