forked from commons-app/apps-android-commons
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Fixes commons-app#3345 * Trust all hosts for beta * Added a custom NetworkFetcger for Fresco when on beta * removed unused assets * make TestCommonsApplication extend Application instead of Commons Application
- Loading branch information
1 parent
df426f7
commit fa87eb5
Showing
7 changed files
with
231 additions
and
56 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
206 changes: 206 additions & 0 deletions
206
app/src/main/java/fr/free/nrw/commons/CustomNetworkFetcher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
package fr.free.nrw.commons; | ||
|
||
import android.net.Uri; | ||
import android.os.Looper; | ||
import android.os.SystemClock; | ||
import com.facebook.imagepipeline.common.BytesRange; | ||
import com.facebook.imagepipeline.image.EncodedImage; | ||
import com.facebook.imagepipeline.producers.BaseNetworkFetcher; | ||
import com.facebook.imagepipeline.producers.BaseProducerContextCallbacks; | ||
import com.facebook.imagepipeline.producers.Consumer; | ||
import com.facebook.imagepipeline.producers.FetchState; | ||
import com.facebook.imagepipeline.producers.NetworkFetcher; | ||
import com.facebook.imagepipeline.producers.ProducerContext; | ||
import java.io.IOException; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.concurrent.Executor; | ||
import okhttp3.CacheControl; | ||
import okhttp3.Call; | ||
import okhttp3.OkHttpClient; | ||
import okhttp3.Request; | ||
import okhttp3.Response; | ||
import okhttp3.ResponseBody; | ||
|
||
/** Network fetcher that uses OkHttp 3 as a backend. */ | ||
public class CustomNetworkFetcher | ||
extends BaseNetworkFetcher<CustomNetworkFetcher.OkHttpNetworkFetchState> { | ||
|
||
public static class OkHttpNetworkFetchState extends FetchState { | ||
|
||
public long submitTime; | ||
public long responseTime; | ||
public long fetchCompleteTime; | ||
|
||
public OkHttpNetworkFetchState( | ||
Consumer<EncodedImage> consumer, ProducerContext producerContext) { | ||
super(consumer, producerContext); | ||
} | ||
} | ||
|
||
private static final String QUEUE_TIME = "queue_time"; | ||
private static final String FETCH_TIME = "fetch_time"; | ||
private static final String TOTAL_TIME = "total_time"; | ||
private static final String IMAGE_SIZE = "image_size"; | ||
|
||
private final Call.Factory mCallFactory; | ||
private final CacheControl mCacheControl; | ||
|
||
private Executor mCancellationExecutor; | ||
|
||
/** @param okHttpClient client to use */ | ||
public CustomNetworkFetcher(OkHttpClient okHttpClient) { | ||
this(okHttpClient, okHttpClient.dispatcher().executorService()); | ||
} | ||
|
||
/** | ||
* @param callFactory custom {@link Call.Factory} for fetching image from the network | ||
* @param cancellationExecutor executor on which fetching cancellation is performed if | ||
* cancellation is requested from the UI Thread | ||
*/ | ||
public CustomNetworkFetcher(Call.Factory callFactory, Executor cancellationExecutor) { | ||
this(callFactory, cancellationExecutor, true); | ||
} | ||
|
||
/** | ||
* @param callFactory custom {@link Call.Factory} for fetching image from the network | ||
* @param cancellationExecutor executor on which fetching cancellation is performed if | ||
* cancellation is requested from the UI Thread | ||
* @param disableOkHttpCache true if network requests should not be cached by OkHttp | ||
*/ | ||
public CustomNetworkFetcher( | ||
Call.Factory callFactory, Executor cancellationExecutor, boolean disableOkHttpCache) { | ||
mCallFactory = callFactory; | ||
mCancellationExecutor = cancellationExecutor; | ||
mCacheControl = disableOkHttpCache ? new CacheControl.Builder().noStore().build() : null; | ||
} | ||
|
||
@Override | ||
public OkHttpNetworkFetchState createFetchState( | ||
Consumer<EncodedImage> consumer, ProducerContext context) { | ||
return new OkHttpNetworkFetchState(consumer, context); | ||
} | ||
|
||
@Override | ||
public void fetch( | ||
final OkHttpNetworkFetchState fetchState, final NetworkFetcher.Callback callback) { | ||
fetchState.submitTime = SystemClock.elapsedRealtime(); | ||
final Uri uri = fetchState.getUri(); | ||
|
||
try { | ||
final Request.Builder requestBuilder = new Request.Builder().url(uri.toString()).get(); | ||
|
||
if (mCacheControl != null) { | ||
requestBuilder.cacheControl(mCacheControl); | ||
} | ||
|
||
final BytesRange bytesRange = fetchState.getContext().getImageRequest().getBytesRange(); | ||
if (bytesRange != null) { | ||
requestBuilder.addHeader("Range", bytesRange.toHttpRangeHeaderValue()); | ||
} | ||
|
||
fetchWithRequest(fetchState, callback, requestBuilder.build()); | ||
} catch (Exception e) { | ||
// handle error while creating the request | ||
callback.onFailure(e); | ||
} | ||
} | ||
|
||
@Override | ||
public void onFetchCompletion(OkHttpNetworkFetchState fetchState, int byteSize) { | ||
fetchState.fetchCompleteTime = SystemClock.elapsedRealtime(); | ||
} | ||
|
||
@Override | ||
public Map<String, String> getExtraMap(OkHttpNetworkFetchState fetchState, int byteSize) { | ||
Map<String, String> extraMap = new HashMap<>(4); | ||
extraMap.put(QUEUE_TIME, Long.toString(fetchState.responseTime - fetchState.submitTime)); | ||
extraMap.put(FETCH_TIME, Long.toString(fetchState.fetchCompleteTime - fetchState.responseTime)); | ||
extraMap.put(TOTAL_TIME, Long.toString(fetchState.fetchCompleteTime - fetchState.submitTime)); | ||
extraMap.put(IMAGE_SIZE, Integer.toString(byteSize)); | ||
return extraMap; | ||
} | ||
|
||
protected void fetchWithRequest( | ||
final OkHttpNetworkFetchState fetchState, | ||
final NetworkFetcher.Callback callback, | ||
final Request request) { | ||
final Call call = mCallFactory.newCall(request); | ||
|
||
fetchState | ||
.getContext() | ||
.addCallbacks( | ||
new BaseProducerContextCallbacks() { | ||
@Override | ||
public void onCancellationRequested() { | ||
if (Looper.myLooper() != Looper.getMainLooper()) { | ||
call.cancel(); | ||
} else { | ||
mCancellationExecutor.execute( | ||
new Runnable() { | ||
@Override | ||
public void run() { | ||
call.cancel(); | ||
} | ||
}); | ||
} | ||
} | ||
}); | ||
|
||
call.enqueue( | ||
new okhttp3.Callback() { | ||
@Override | ||
public void onResponse(Call call, Response response) throws IOException { | ||
fetchState.responseTime = SystemClock.elapsedRealtime(); | ||
final ResponseBody body = response.body(); | ||
try { | ||
if (!response.isSuccessful()) { | ||
handleException( | ||
call, new IOException("Unexpected HTTP code " + response), callback); | ||
return; | ||
} | ||
|
||
BytesRange responseRange = | ||
BytesRange.fromContentRangeHeader(response.header("Content-Range")); | ||
if (responseRange != null | ||
&& !(responseRange.from == 0 | ||
&& responseRange.to == BytesRange.TO_END_OF_CONTENT)) { | ||
// Only treat as a partial image if the range is not all of the content | ||
fetchState.setResponseBytesRange(responseRange); | ||
fetchState.setOnNewResultStatusFlags(Consumer.IS_PARTIAL_RESULT); | ||
} | ||
|
||
long contentLength = body.contentLength(); | ||
if (contentLength < 0) { | ||
contentLength = 0; | ||
} | ||
callback.onResponse(body.byteStream(), (int) contentLength); | ||
} catch (Exception e) { | ||
handleException(call, e, callback); | ||
} finally { | ||
body.close(); | ||
} | ||
} | ||
|
||
@Override | ||
public void onFailure(Call call, IOException e) { | ||
handleException(call, e, callback); | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Handles exceptions. | ||
* | ||
* <p>OkHttp notifies callers of cancellations via an IOException. If IOException is caught after | ||
* request cancellation, then the exception is interpreted as successful cancellation and | ||
* onCancellation is called. Otherwise onFailure is called. | ||
*/ | ||
private void handleException(final Call call, final Exception e, final Callback callback) { | ||
if (call.isCanceled()) { | ||
callback.onCancellation(); | ||
} else { | ||
callback.onFailure(e); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters