Import of Volley from GitHub to AOSP.
Android.bp has been updated to account for the new source directory structure.
- 0dc50bcfd021c204a9e6c9e7e6befbdfa1027247 Refactor Volley into a multi-module project. (#418) by Jeff Davidson <jpd@google.com>
- 763c86b0bc9f66a8bb499f6a8b7fd3bdc87621a8 Remove new constructors from JsonRequests which are break... by Jeff Davidson <jpd@google.com>
- 8d1b1a59e7cd1b1d3c6d8686f8831cea08f80d1f Add @NonNull annotations to Volley (#413) by Kamal Faraj <kfaraj.dev@gmail.com>
- 5ba41f8670413973f587e435598f9f1724fa26e9 Allow sending any JSON with JsonArrayRequest & JsonObject... by Paul Smith <paulsmithkc@gmail.com>
- 784cdd755392a6080e5eb0bf94bd7bf4ea31cf17 Update SNAPSHOT version after 1.2.0 release by Jeff Davidson <jpd@google.com>
- 0d6497bab417a5f78b3c8e03ea157ada0fbfbc5d Add developers stanza to Volley POM. (#400) by Jeff Davidson <jpd@google.com>
- 36274bf515a699ae5a7fe3d321206d1b803226d8 API cleanup for Async Volley stack ahead of 1.2.0 release... by Jeff Davidson <jpd@google.com>
- 03f0144843fcf9ebafe512647c1c588975429452 Update environment variable name for snapshot pushes. (#3... by Jeff Davidson <jpd@google.com>
- 3bd1975652687d2baa1b11a7f02b135edede8523 Publish SNAPSHOT builds to OSSRH instead of OJO. (#397) by Jeff Davidson <jpd@google.com>
- 0e0c3d9cfa694f8f1400a9e9abc4bc11761fdb52 Invoke RetryPolicy#retry in the blocking executor. (#393) by Jeff Davidson <jpd@google.com>
- b51831a48f06ad28f627c3624e5edb41598a2bf8 Use a consistent timebase when evaluating soft/hard TTLs.... by Jeff Davidson <jpd@google.com>
- cd0839113b100f163df1ebd04ce6d5b9e36e9863 Migrate from Travis CI to GitHub Actions. (#381) by Jeff Davidson <jpd@google.com>
- bdc0e393199ebf9e67c4e29e665252818eed4639 Clean up cache initialization in AsyncRequestQueue. (#380) by Jeff Davidson <jpd@google.com>
- 1c0ade36edde15d02844b40351ab6f80c63b71b3 Actually allow applications to provide custom executors. by Jeff Davidson <jpd@google.com>
GitOrigin-RevId: 0dc50bcfd021c204a9e6c9e7e6befbdfa1027247
Change-Id: I4b8e4098ad5c349cb83efc867273fac1d3582a34
diff --git a/.github/workflows/gradle-build.yaml b/.github/workflows/gradle-build.yaml
new file mode 100644
index 0000000..c42648c
--- /dev/null
+++ b/.github/workflows/gradle-build.yaml
@@ -0,0 +1,28 @@
+name: Gradle
+
+on: [push, pull_request]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK 1.8
+ uses: actions/setup-java@v1
+ with:
+ java-version: 1.8
+ - name: Cache Gradle packages
+ uses: actions/cache@v2
+ with:
+ path: ~/.gradle/caches
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
+ restore-keys: ${{ runner.os }}-gradle
+ - name: Build with Gradle
+ run: ./gradlew --continue verifyGoogleJavaFormat build connectedCheck
+ - name: Publish snapshot
+ if: github.event_name == 'push'
+ env:
+ OSSRH_DEPLOY_USERNAME: ${{ secrets.OSSRH_DEPLOY_USERNAME }}
+ OSSRH_DEPLOY_PASSWORD: ${{ secrets.OSSRH_DEPLOY_PASSWORD }}
+ run: ./publish-snapshot-on-commit.sh
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index fb6481a..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-language: android
-android:
- licenses:
- - 'android-sdk-preview-license-.+'
- - 'android-sdk-license-.+'
- - 'google-gdk-license-.+'
-
- components:
- # Workaround to be able to install v28 SDK and build tools.
- # See https://github.com/travis-ci/travis-ci/issues/6040
- - tools # to update the repository XML files
- - tools # to update the SDK tools themselves
-
- - platform-tools
- - build-tools-28.0.3
- - android-28
-
-jdk:
- - oraclejdk8
-
-# Avoid uploading the cache after every build
-# See https://docs.travis-ci.com/user/languages/android/
-before_cache:
- - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
- - rm -fr $HOME/.gradle/caches/*/classAnalysis/
- - rm -fr $HOME/.gradle/caches/*/workerMain/
-cache:
- directories:
- - $HOME/.gradle/caches/
- - $HOME/.gradle/wrapper/
- - $HOME/.android/build-cache
-
-env:
- global:
- - secure: "ObTSgg1H/RoQwhf9735Cr0OEs7r296aQTKiVOmQYSIxZPzc7o2KveSVV8IVeQ+VQtDxPFij6Odk4gaQSKVytliTlgtSsrEaYt67yWWYLWBLWbnzLNYoWMMy+36O5BK78RNtVJ3Xr1mdMcZ2+SRj2TcEvQBqMWlUkJfEcmJttreq0Wd7jiNitv5MbyYRcd2AvKaqNilx5rEm1ihbE0wT3lH20EdAjjjckaBT04r+VXU9e0dg6tmZjqG8dxGzxYHLRTz7nmKXlUnOJ3steNPrmR/AsGqKW6Ppowi31t3iLpL3zdT0+mvzfvnQwBodqHWSU/JhVDGlePv+4a5aU80s+5nN1IKL7tTLGYWoKdoIuQLovRkdcdkuj8UNyftPj6qOO2C9Tk8j64WXwUIDRnmNfjXbFzqN51oiT94G6hPcEDQSxLwuqlmgNm9I9WxZidb5YotIN2BcIKthAvdL4ecxE5INJvss8DVdYUZ53000GqSoMv8WET6jYkSJPKfvmTgpqqYIW0sgMiDfO/ta/MTFG5kSqECL+sAFZNmugwmTc7NIdy29myCyLH/A6oM4n3QeFDDHhOl2cRYlsX3juzw2goRppR9sEosFN0D1T7Fije5RmJsPgVLGwYMxSGukAHufcatKfhccUVl+haSJ3PLQ1z+25Ug2kpJwMAHbUYWCBnew="
- - secure: "Ac95rbJd5dgNdK8ZlaeXpkKYXHGNj8pm4eNv1Oe8YtsByshHtBAK1m55H4Ex55oRXaLXntvQwnnJfqeTDPuqvd7QP1fjvp4Yjdaqa8MkC6qdVtm6LaqsGuE38uSiU6oxJKfnlCywNe2LfFlbzBtPd3ejNI7tfJcO3s1mD2aBT46vmwUy0t5ESxNdP2zUs6DFcbaOUWeJhQn8iNdRm2VbHEMdevzvvXXIUB9YUdBZQIuAZ5E8NRP5/dzPE8P0CY6/yXqQ/6bkXRV3Pf9QsRzJ+oEQVJAIFfC4JAGasgaBIVpaJ2C2At39jrNFpGYUNbHxvkBEal+WiaPk5TfmVbpyWJOTPRaaY3tIRdBbYf6kklnQk2jRJB6GCi4/yvT6oNjTQQEwsuYlaivkibwNehQqtqyjj12CcTI7lwbgNXeLvIWE6LNLIxrY4pnNy3bKjA0oLFoG/FuP3Wi9WldBtVXwvUBVFFXeOgzP6lCDkzGYTwYZi20lRmSgma3Q5e3/BbPtos3BZ9dSY3lUjttGxvHEDCJ48U1aw6usR91ZKD78Thb5OxWLkvs4rjWEDU2I649wiYSyqFldNEnv+2SJSRB+097XEcnCopGXorlMhBMAlhwHyiRY1u0D+9qrpfIl9Z07j0ZiG5uIscDXQZZjMivqe/+u8NJ3kN0zrDO5BQEgNls="
-
-# Publish a SNAPSHOT build for all commits to master.
-script:
- - ./gradlew --continue verifyGoogleJavaFormat build connectedCheck && ./publish-snapshot-on-commit.sh
diff --git a/Android.bp b/Android.bp
index 803b4f2..917048f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -36,11 +36,10 @@
name: "volley",
sdk_version: "28",
min_sdk_version: "8",
- srcs: ["src/main/java/**/*.java"],
+ srcs: ["core/src/main/java/**/*.java"],
// Exclude Cronet support for now. Can be enabled later if/when Cronet is made available as a
// compilation dependency for Volley clients.
- exclude_srcs: ["src/main/java/com/android/volley/cronet/**/*"],
libs: [
// Only needed at compile-time.
diff --git a/bintray.gradle b/bintray.gradle
deleted file mode 100644
index b642b41..0000000
--- a/bintray.gradle
+++ /dev/null
@@ -1,78 +0,0 @@
-buildscript {
- repositories {
- jcenter()
- }
- dependencies {
- classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.8.1"
- }
-}
-
-// apply the plugin with its class name rather than its Id to work around gradle limitation of
-// not being able to find the plugin by Id despite the dependencies being added right above. Gradle
-// is currently not capable of loading plugins by Id if the dependency is anywhere else than
-// in the main project build.gradle. This file is "imported" into the project's build.gradle
-// through a "apply from:".
-apply plugin: org.jfrog.gradle.plugin.artifactory.ArtifactoryPlugin
-apply plugin: 'maven-publish'
-
-task sourcesJar(type: Jar) {
- classifier = 'sources'
- from android.sourceSets.main.java.srcDirs
-}
-
-task javadoc(type: Javadoc) {
- source = android.sourceSets.main.java.srcDirs
- classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
-}
-
-task javadocJar(type: Jar, dependsOn: javadoc) {
- classifier = 'javadoc'
- from javadoc.destinationDir
-}
-
-artifacts {
- archives javadocJar
- archives sourcesJar
-}
-
-publishing {
- publications {
- library(MavenPublication) {
- groupId 'com.android.volley'
- artifactId 'volley'
- version project.version
- pom {
- packaging 'aar'
- licenses {
- license {
- name = "The Apache License, Version 2.0"
- url = "http://www.apache.org/licenses/LICENSE-2.0.txt"
- }
- }
- }
-
- // Release AAR, Sources, and JavaDoc
- artifact "$buildDir/outputs/aar/volley-release.aar"
- artifact sourcesJar
- artifact javadocJar
- }
- }
-}
-
-artifactory {
- contextUrl = "https://oss.jfrog.org"
- publish {
- repository {
- repoKey = 'oss-snapshot-local'
- username = System.env.CI_DEPLOY_USERNAME
- password = System.env.CI_DEPLOY_PASSWORD
- }
- defaults {
- publications('library')
- publishArtifacts = true
- }
- }
- resolve {
- repoKey = 'jcenter'
- }
-}
diff --git a/build.gradle b/build.gradle
index 544771c..b8db952 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,76 +1,72 @@
-// NOTE: The only changes that belong in this file are the definitions
-// of tool versions (gradle plugin, compile SDK, build tools), so that
-// Volley can be built via gradle as a standalone project.
-//
-// Any other changes to the build config belong in rules.gradle, which
-// is used by projects that depend on Volley but define their own
-// tools versions across all dependencies to ensure a consistent build.
-//
-// Most users should just add this line to settings.gradle:
-// include(":volley")
-//
-// If you have a more complicated Gradle setup you can choose to use
-// this instead:
-// include(":volley")
-// project(':volley').buildFileName = 'rules.gradle'
-
-import net.ltgt.gradle.errorprone.CheckSeverity
-
buildscript {
repositories {
+ gradlePluginPortal()
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
+ classpath 'gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.6'
+ // NOTE: 0.7 or newer will require upgrading to a newer Android gradle plugin:
+ // https://github.com/tbroyer/gradle-errorprone-plugin/commit/65b1026ebeae1b7ed8c28578c7f6eea512c16bea
+ classpath 'net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:0.6.1'
}
}
-plugins {
- id "com.github.sherter.google-java-format" version "0.6"
- // NOTE: 0.7 or newer will require upgrading to a newer Android gradle plugin:
- // https://github.com/tbroyer/gradle-errorprone-plugin/commit/65b1026ebeae1b7ed8c28578c7f6eea512c16bea
- id "net.ltgt.errorprone" version "0.6.1"
-}
-
-googleJavaFormat {
- toolVersion = '1.5'
- options style: 'AOSP'
-}
-
-apply plugin: 'com.android.library'
-
-repositories {
- jcenter()
- google()
-}
-
-dependencies {
- // NOTE: Updating ErrorProne introduces new checks that may cause the build to fail. Pin to a
- // specific version to control these updates.
- errorprone("com.google.errorprone:error_prone_core:2.3.2")
- // ErrorProne requires a JDK 9 compiler, so pull one in as a dependency since we use Java 8:
- // https://github.com/tbroyer/gradle-errorprone-plugin#jdk-8-support
- errorproneJavac("com.google.errorprone:javac:9+181-r4173-1")
-}
-
-group = 'com.android.volley'
-version = '1.2.0-SNAPSHOT'
-
-android {
- compileSdkVersion 28
- buildToolsVersion = '28.0.3'
-
- defaultConfig {
- minSdkVersion 8
+allprojects {
+ repositories {
+ jcenter()
+ google()
}
}
-tasks.withType(JavaCompile) {
- options.errorprone {
- check("ParameterComment", CheckSeverity.ERROR)
+subprojects {
+ apply plugin: 'com.github.sherter.google-java-format'
+ apply plugin: 'net.ltgt.errorprone'
+
+ googleJavaFormat {
+ toolVersion = '1.5'
+ options style: 'AOSP'
+ }
+
+ apply plugin: 'com.android.library'
+
+ dependencies {
+ // NOTE: Updating ErrorProne introduces new checks that may cause the build to fail. Pin to a
+ // specific version to control these updates.
+ errorprone("com.google.errorprone:error_prone_core:2.3.2")
+ // ErrorProne requires a JDK 9 compiler, so pull one in as a dependency since we use Java 8:
+ // https://github.com/tbroyer/gradle-errorprone-plugin#jdk-8-support
+ errorproneJavac("com.google.errorprone:javac:9+181-r4173-1")
+ }
+
+ group = 'com.android.volley'
+ version = '1.2.1-SNAPSHOT'
+
+ android {
+ useLibrary 'org.apache.http.legacy'
+
+ compileSdkVersion 28
+ buildToolsVersion = '28.0.3'
+
+ defaultConfig {
+ minSdkVersion 8
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_7
+ targetCompatibility JavaVersion.VERSION_1_7
+ }
+ }
+
+ tasks.withType(JavaCompile) {
+ options.errorprone {
+ check("ParameterComment", net.ltgt.gradle.errorprone.CheckSeverity.ERROR)
+ }
+ options.compilerArgs << "-Xlint:unchecked" << "-Werror"
+ }
+
+ if (it.name != 'testing') {
+ apply from: '../publish.gradle'
}
}
-
-apply from: 'rules.gradle'
-apply from: 'bintray.gradle'
diff --git a/core/build.gradle b/core/build.gradle
new file mode 100644
index 0000000..812968c
--- /dev/null
+++ b/core/build.gradle
@@ -0,0 +1,28 @@
+android {
+ defaultConfig {
+ consumerProguardFiles 'consumer-proguard-rules.pro'
+ }
+}
+
+dependencies {
+ implementation "androidx.annotation:annotation:1.0.1"
+
+ testImplementation project(":testing")
+ testImplementation "junit:junit:4.12"
+ testImplementation "org.hamcrest:hamcrest-library:1.3"
+ testImplementation "org.mockito:mockito-core:2.19.0"
+ testImplementation "org.robolectric:robolectric:3.4.2"
+}
+
+publishing {
+ publications {
+ library(MavenPublication) {
+ artifactId 'volley'
+ pom {
+ name = 'Volley'
+ description = 'An HTTP library that makes networking for Android apps easier and, most importantly, faster.'
+ }
+ artifact "$buildDir/outputs/aar/core-release.aar"
+ }
+ }
+}
diff --git a/consumer-proguard-rules.pro b/core/consumer-proguard-rules.pro
similarity index 100%
rename from consumer-proguard-rules.pro
rename to core/consumer-proguard-rules.pro
diff --git a/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml
similarity index 100%
rename from src/main/AndroidManifest.xml
rename to core/src/main/AndroidManifest.xml
diff --git a/src/main/java/com/android/volley/AsyncCache.java b/core/src/main/java/com/android/volley/AsyncCache.java
similarity index 92%
rename from src/main/java/com/android/volley/AsyncCache.java
rename to core/src/main/java/com/android/volley/AsyncCache.java
index 3cddb4b..8b2dbcc 100644
--- a/src/main/java/com/android/volley/AsyncCache.java
+++ b/core/src/main/java/com/android/volley/AsyncCache.java
@@ -18,7 +18,12 @@
import androidx.annotation.Nullable;
-/** Asynchronous equivalent to the {@link Cache} interface. */
+/**
+ * Asynchronous equivalent to the {@link Cache} interface.
+ *
+ * <p><b>WARNING</b>: This API is experimental and subject to breaking changes. Please see
+ * https://github.com/google/volley/wiki/Asynchronous-Volley for more details.
+ */
public abstract class AsyncCache {
public interface OnGetCompleteCallback {
diff --git a/src/main/java/com/android/volley/AsyncNetwork.java b/core/src/main/java/com/android/volley/AsyncNetwork.java
similarity index 94%
rename from src/main/java/com/android/volley/AsyncNetwork.java
rename to core/src/main/java/com/android/volley/AsyncNetwork.java
index ad19c03..47f35ea 100644
--- a/src/main/java/com/android/volley/AsyncNetwork.java
+++ b/core/src/main/java/com/android/volley/AsyncNetwork.java
@@ -22,7 +22,12 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicReference;
-/** An asynchronous implementation of {@link Network} to perform requests. */
+/**
+ * An asynchronous implementation of {@link Network} to perform requests.
+ *
+ * <p><b>WARNING</b>: This API is experimental and subject to breaking changes. Please see
+ * https://github.com/google/volley/wiki/Asynchronous-Volley for more details.
+ */
public abstract class AsyncNetwork implements Network {
private ExecutorService mBlockingExecutor;
private ExecutorService mNonBlockingExecutor;
diff --git a/src/main/java/com/android/volley/AsyncRequestQueue.java b/core/src/main/java/com/android/volley/AsyncRequestQueue.java
similarity index 84%
rename from src/main/java/com/android/volley/AsyncRequestQueue.java
rename to core/src/main/java/com/android/volley/AsyncRequestQueue.java
index 3754866..7bf8c21 100644
--- a/src/main/java/com/android/volley/AsyncRequestQueue.java
+++ b/core/src/main/java/com/android/volley/AsyncRequestQueue.java
@@ -25,9 +25,10 @@
import com.android.volley.AsyncNetwork.OnRequestComplete;
import com.android.volley.Cache.Entry;
import java.net.HttpURLConnection;
+import java.util.ArrayList;
import java.util.Comparator;
+import java.util.List;
import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.PriorityBlockingQueue;
@@ -41,7 +42,10 @@
* An asynchronous request dispatch queue.
*
* <p>Add requests to the queue with {@link #add(Request)}. Once completed, responses will be
- * delivered on the main thread (unless a custom {@link ResponseDelivery} has been provided)
+ * delivered on the main thread (unless a custom {@link ResponseDelivery} has been provided).
+ *
+ * <p><b>WARNING</b>: This API is experimental and subject to breaking changes. Please see
+ * https://github.com/google/volley/wiki/Asynchronous-Volley for more details.
*/
public class AsyncRequestQueue extends RequestQueue {
/** Default number of blocking threads to start. */
@@ -83,6 +87,17 @@
private final WaitingRequestManager mWaitingRequestManager = new WaitingRequestManager(this);
/**
+ * Requests which have been queued before cache initialization has completed.
+ *
+ * <p>These requests are kicked off once cache initialization finishes. We avoid enqueuing them
+ * sooner as the cache may not yet be ready.
+ */
+ private final List<Request<?>> mRequestsAwaitingCacheInitialization = new ArrayList<>();
+
+ private volatile boolean mIsCacheInitialized = false;
+ private final Object mCacheInitializationLock = new Object[0];
+
+ /**
* Sets all the variables, but processing does not begin until {@link #start()} is called.
*
* @param cache to use for persisting responses to disk. If an AsyncCache was provided, then
@@ -119,34 +134,37 @@
mNetwork.setNonBlockingExecutor(mNonBlockingExecutor);
mNetwork.setNonBlockingScheduledExecutor(mNonBlockingScheduledExecutor);
- mNonBlockingExecutor.execute(
- new Runnable() {
- @Override
- public void run() {
- // This is intentionally blocking, because we don't want to process any
- // requests until the cache is initialized.
- if (mAsyncCache != null) {
- final CountDownLatch latch = new CountDownLatch(1);
+ // Kick off cache initialization, which must complete before any requests can be processed.
+ if (mAsyncCache != null) {
+ mNonBlockingExecutor.execute(
+ new Runnable() {
+ @Override
+ public void run() {
mAsyncCache.initialize(
new AsyncCache.OnWriteCompleteCallback() {
@Override
public void onWriteComplete() {
- latch.countDown();
+ onCacheInitializationComplete();
}
});
- try {
- latch.await();
- } catch (InterruptedException e) {
- VolleyLog.e(
- e, "Thread was interrupted while initializing the cache.");
- Thread.currentThread().interrupt();
- throw new RuntimeException(e);
- }
- } else {
- getCache().initialize();
}
- }
- });
+ });
+ } else {
+ mBlockingExecutor.execute(
+ new Runnable() {
+ @Override
+ public void run() {
+ getCache().initialize();
+ mNonBlockingExecutor.execute(
+ new Runnable() {
+ @Override
+ public void run() {
+ onCacheInitializationComplete();
+ }
+ });
+ }
+ });
+ }
}
/** Shuts down and nullifies both executors */
@@ -169,6 +187,17 @@
/** Begins the request by sending it to the Cache or Network. */
@Override
<T> void beginRequest(Request<T> request) {
+ // If the cache hasn't been initialized yet, add the request to a temporary queue to be
+ // flushed once initialization completes.
+ if (!mIsCacheInitialized) {
+ synchronized (mCacheInitializationLock) {
+ if (!mIsCacheInitialized) {
+ mRequestsAwaitingCacheInitialization.add(request);
+ return;
+ }
+ }
+ }
+
// If the request is uncacheable, send it over the network.
if (request.shouldCache()) {
if (mAsyncCache != null) {
@@ -181,6 +210,20 @@
}
}
+ private void onCacheInitializationComplete() {
+ List<Request<?>> requestsToDispatch;
+ synchronized (mCacheInitializationLock) {
+ requestsToDispatch = new ArrayList<>(mRequestsAwaitingCacheInitialization);
+ mRequestsAwaitingCacheInitialization.clear();
+ mIsCacheInitialized = true;
+ }
+
+ // Kick off any requests that were queued while waiting for cache initialization.
+ for (Request<?> request : requestsToDispatch) {
+ beginRequest(request);
+ }
+ }
+
@Override
<T> void sendRequestOverNetwork(Request<T> request) {
mNonBlockingExecutor.execute(new NetworkTask<>(request));
@@ -230,8 +273,14 @@
return;
}
+ // Use a single instant to evaluate cache expiration. Otherwise, a cache entry with
+ // identical soft and hard TTL times may appear to be valid when checking isExpired but
+ // invalid upon checking refreshNeeded(), triggering a soft TTL refresh which should be
+ // impossible.
+ long currentTimeMillis = System.currentTimeMillis();
+
// If it is completely expired, just send it to the network.
- if (entry.isExpired()) {
+ if (entry.isExpired(currentTimeMillis)) {
mRequest.addMarker("cache-hit-expired");
mRequest.setCacheEntry(entry);
if (!mWaitingRequestManager.maybeAddToWaitingRequests(mRequest)) {
@@ -241,15 +290,17 @@
}
// We have a cache hit; parse its data for delivery back to the request.
- mBlockingExecutor.execute(new CacheParseTask<>(mRequest, entry));
+ mBlockingExecutor.execute(new CacheParseTask<>(mRequest, entry, currentTimeMillis));
}
private class CacheParseTask<T> extends RequestTask<T> {
Cache.Entry entry;
+ long startTimeMillis;
- CacheParseTask(Request<T> request, Cache.Entry entry) {
+ CacheParseTask(Request<T> request, Cache.Entry entry, long startTimeMillis) {
super(request);
this.entry = entry;
+ this.startTimeMillis = startTimeMillis;
}
@Override
@@ -265,7 +316,7 @@
entry.allResponseHeaders));
mRequest.addMarker("cache-hit-parsed");
- if (!entry.refreshNeeded()) {
+ if (!entry.refreshNeeded(startTimeMillis)) {
// Completely unexpired cache hit. Just deliver the response.
getResponseDelivery().postResponse(mRequest, response);
} else {
@@ -436,17 +487,24 @@
}
/**
- * This class may be used by advanced applications to provide custom executors according to
- * their needs. Apps must create ExecutorServices dynamically given a blocking queue rather than
- * providing them directly so that Volley can provide a PriorityQueue which will prioritize
- * requests according to Request#getPriority.
+ * Factory to create/provide the executors which Volley will use.
+ *
+ * <p>This class may be used by advanced applications to provide custom executors according to
+ * their needs.
+ *
+ * <p>For applications which rely on setting request priority via {@link Request#getPriority}, a
+ * task queue is provided which will prioritize requests of higher priority should the thread
+ * pool itself be exhausted. If a shared pool is provided which does not make use of the given
+ * queue, then lower-priority requests may have tasks executed before higher-priority requests
+ * when enough tasks are in flight to fully saturate the shared pool.
*/
public abstract static class ExecutorFactory {
- abstract ExecutorService createNonBlockingExecutor(BlockingQueue<Runnable> taskQueue);
+ public abstract ExecutorService createNonBlockingExecutor(
+ BlockingQueue<Runnable> taskQueue);
- abstract ExecutorService createBlockingExecutor(BlockingQueue<Runnable> taskQueue);
+ public abstract ExecutorService createBlockingExecutor(BlockingQueue<Runnable> taskQueue);
- abstract ScheduledExecutorService createNonBlockingScheduledExecutor();
+ public abstract ScheduledExecutorService createNonBlockingScheduledExecutor();
}
/** Provides a BlockingQueue to be used to create executors. */
diff --git a/src/main/java/com/android/volley/AuthFailureError.java b/core/src/main/java/com/android/volley/AuthFailureError.java
similarity index 100%
rename from src/main/java/com/android/volley/AuthFailureError.java
rename to core/src/main/java/com/android/volley/AuthFailureError.java
diff --git a/src/main/java/com/android/volley/Cache.java b/core/src/main/java/com/android/volley/Cache.java
similarity index 90%
rename from src/main/java/com/android/volley/Cache.java
rename to core/src/main/java/com/android/volley/Cache.java
index b8908ac..7348d0f 100644
--- a/src/main/java/com/android/volley/Cache.java
+++ b/core/src/main/java/com/android/volley/Cache.java
@@ -102,12 +102,20 @@
/** True if the entry is expired. */
public boolean isExpired() {
- return this.ttl < System.currentTimeMillis();
+ return isExpired(System.currentTimeMillis());
+ }
+
+ boolean isExpired(long currentTimeMillis) {
+ return this.ttl < currentTimeMillis;
}
/** True if a refresh is needed from the original data source. */
public boolean refreshNeeded() {
- return this.softTtl < System.currentTimeMillis();
+ return refreshNeeded(System.currentTimeMillis());
+ }
+
+ boolean refreshNeeded(long currentTimeMillis) {
+ return this.softTtl < currentTimeMillis;
}
}
}
diff --git a/src/main/java/com/android/volley/CacheDispatcher.java b/core/src/main/java/com/android/volley/CacheDispatcher.java
similarity index 94%
rename from src/main/java/com/android/volley/CacheDispatcher.java
rename to core/src/main/java/com/android/volley/CacheDispatcher.java
index 1bfc0ea..4443143 100644
--- a/src/main/java/com/android/volley/CacheDispatcher.java
+++ b/core/src/main/java/com/android/volley/CacheDispatcher.java
@@ -138,8 +138,14 @@
return;
}
+ // Use a single instant to evaluate cache expiration. Otherwise, a cache entry with
+ // identical soft and hard TTL times may appear to be valid when checking isExpired but
+ // invalid upon checking refreshNeeded(), triggering a soft TTL refresh which should be
+ // impossible.
+ long currentTimeMillis = System.currentTimeMillis();
+
// If it is completely expired, just send it to the network.
- if (entry.isExpired()) {
+ if (entry.isExpired(currentTimeMillis)) {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
@@ -164,7 +170,7 @@
}
return;
}
- if (!entry.refreshNeeded()) {
+ if (!entry.refreshNeeded(currentTimeMillis)) {
// Completely unexpired cache hit. Just deliver the response.
mDelivery.postResponse(request, response);
} else {
diff --git a/src/main/java/com/android/volley/ClientError.java b/core/src/main/java/com/android/volley/ClientError.java
similarity index 100%
rename from src/main/java/com/android/volley/ClientError.java
rename to core/src/main/java/com/android/volley/ClientError.java
diff --git a/src/main/java/com/android/volley/DefaultRetryPolicy.java b/core/src/main/java/com/android/volley/DefaultRetryPolicy.java
similarity index 100%
rename from src/main/java/com/android/volley/DefaultRetryPolicy.java
rename to core/src/main/java/com/android/volley/DefaultRetryPolicy.java
diff --git a/src/main/java/com/android/volley/ExecutorDelivery.java b/core/src/main/java/com/android/volley/ExecutorDelivery.java
similarity index 100%
rename from src/main/java/com/android/volley/ExecutorDelivery.java
rename to core/src/main/java/com/android/volley/ExecutorDelivery.java
diff --git a/src/main/java/com/android/volley/Header.java b/core/src/main/java/com/android/volley/Header.java
similarity index 100%
rename from src/main/java/com/android/volley/Header.java
rename to core/src/main/java/com/android/volley/Header.java
diff --git a/src/main/java/com/android/volley/Network.java b/core/src/main/java/com/android/volley/Network.java
similarity index 100%
rename from src/main/java/com/android/volley/Network.java
rename to core/src/main/java/com/android/volley/Network.java
diff --git a/src/main/java/com/android/volley/NetworkDispatcher.java b/core/src/main/java/com/android/volley/NetworkDispatcher.java
similarity index 100%
rename from src/main/java/com/android/volley/NetworkDispatcher.java
rename to core/src/main/java/com/android/volley/NetworkDispatcher.java
diff --git a/src/main/java/com/android/volley/NetworkError.java b/core/src/main/java/com/android/volley/NetworkError.java
similarity index 100%
rename from src/main/java/com/android/volley/NetworkError.java
rename to core/src/main/java/com/android/volley/NetworkError.java
diff --git a/src/main/java/com/android/volley/NetworkResponse.java b/core/src/main/java/com/android/volley/NetworkResponse.java
similarity index 100%
rename from src/main/java/com/android/volley/NetworkResponse.java
rename to core/src/main/java/com/android/volley/NetworkResponse.java
diff --git a/src/main/java/com/android/volley/NoConnectionError.java b/core/src/main/java/com/android/volley/NoConnectionError.java
similarity index 100%
rename from src/main/java/com/android/volley/NoConnectionError.java
rename to core/src/main/java/com/android/volley/NoConnectionError.java
diff --git a/src/main/java/com/android/volley/ParseError.java b/core/src/main/java/com/android/volley/ParseError.java
similarity index 100%
rename from src/main/java/com/android/volley/ParseError.java
rename to core/src/main/java/com/android/volley/ParseError.java
diff --git a/src/main/java/com/android/volley/Request.java b/core/src/main/java/com/android/volley/Request.java
similarity index 98%
rename from src/main/java/com/android/volley/Request.java
rename to core/src/main/java/com/android/volley/Request.java
index b60dc74..df0d18f 100644
--- a/src/main/java/com/android/volley/Request.java
+++ b/core/src/main/java/com/android/volley/Request.java
@@ -135,8 +135,8 @@
* @deprecated Use {@link #Request(int, String, com.android.volley.Response.ErrorListener)}.
*/
@Deprecated
- public Request(String url, Response.ErrorListener listener) {
- this(Method.DEPRECATED_GET_OR_POST, url, listener);
+ public Request(String url, Response.ErrorListener errorListener) {
+ this(Method.DEPRECATED_GET_OR_POST, url, errorListener);
}
/**
@@ -144,11 +144,15 @@
* error listener. Note that the normal response listener is not provided here as delivery of
* responses is provided by subclasses, who have a better idea of how to deliver an
* already-parsed response.
+ *
+ * @param method the HTTP method to use
+ * @param url URL to fetch the response from
+ * @param errorListener Error listener, or null to ignore errors.
*/
- public Request(int method, String url, @Nullable Response.ErrorListener listener) {
+ public Request(int method, String url, @Nullable Response.ErrorListener errorListener) {
mMethod = method;
mUrl = url;
- mErrorListener = listener;
+ mErrorListener = errorListener;
setRetryPolicy(new DefaultRetryPolicy());
mDefaultTrafficStatsTag = findDefaultTrafficStatsTag(url);
diff --git a/src/main/java/com/android/volley/RequestQueue.java b/core/src/main/java/com/android/volley/RequestQueue.java
similarity index 100%
rename from src/main/java/com/android/volley/RequestQueue.java
rename to core/src/main/java/com/android/volley/RequestQueue.java
diff --git a/core/src/main/java/com/android/volley/RequestTask.java b/core/src/main/java/com/android/volley/RequestTask.java
new file mode 100644
index 0000000..b429f79
--- /dev/null
+++ b/core/src/main/java/com/android/volley/RequestTask.java
@@ -0,0 +1,20 @@
+package com.android.volley;
+
+/**
+ * Abstract runnable that's a task to be completed by the RequestQueue.
+ *
+ * <p><b>WARNING</b>: This API is experimental and subject to breaking changes. Please see
+ * https://github.com/google/volley/wiki/Asynchronous-Volley for more details.
+ */
+public abstract class RequestTask<T> implements Runnable {
+ final Request<T> mRequest;
+
+ public RequestTask(Request<T> request) {
+ mRequest = request;
+ }
+
+ @SuppressWarnings("unchecked")
+ public int compareTo(RequestTask<?> other) {
+ return mRequest.compareTo((Request<T>) other.mRequest);
+ }
+}
diff --git a/src/main/java/com/android/volley/Response.java b/core/src/main/java/com/android/volley/Response.java
similarity index 100%
rename from src/main/java/com/android/volley/Response.java
rename to core/src/main/java/com/android/volley/Response.java
diff --git a/src/main/java/com/android/volley/ResponseDelivery.java b/core/src/main/java/com/android/volley/ResponseDelivery.java
similarity index 100%
rename from src/main/java/com/android/volley/ResponseDelivery.java
rename to core/src/main/java/com/android/volley/ResponseDelivery.java
diff --git a/src/main/java/com/android/volley/RetryPolicy.java b/core/src/main/java/com/android/volley/RetryPolicy.java
similarity index 100%
rename from src/main/java/com/android/volley/RetryPolicy.java
rename to core/src/main/java/com/android/volley/RetryPolicy.java
diff --git a/src/main/java/com/android/volley/ServerError.java b/core/src/main/java/com/android/volley/ServerError.java
similarity index 100%
rename from src/main/java/com/android/volley/ServerError.java
rename to core/src/main/java/com/android/volley/ServerError.java
diff --git a/src/main/java/com/android/volley/TimeoutError.java b/core/src/main/java/com/android/volley/TimeoutError.java
similarity index 100%
rename from src/main/java/com/android/volley/TimeoutError.java
rename to core/src/main/java/com/android/volley/TimeoutError.java
diff --git a/src/main/java/com/android/volley/VolleyError.java b/core/src/main/java/com/android/volley/VolleyError.java
similarity index 100%
rename from src/main/java/com/android/volley/VolleyError.java
rename to core/src/main/java/com/android/volley/VolleyError.java
diff --git a/src/main/java/com/android/volley/VolleyLog.java b/core/src/main/java/com/android/volley/VolleyLog.java
similarity index 100%
rename from src/main/java/com/android/volley/VolleyLog.java
rename to core/src/main/java/com/android/volley/VolleyLog.java
diff --git a/src/main/java/com/android/volley/WaitingRequestManager.java b/core/src/main/java/com/android/volley/WaitingRequestManager.java
similarity index 100%
rename from src/main/java/com/android/volley/WaitingRequestManager.java
rename to core/src/main/java/com/android/volley/WaitingRequestManager.java
diff --git a/src/main/java/com/android/volley/toolbox/AdaptedHttpStack.java b/core/src/main/java/com/android/volley/toolbox/AdaptedHttpStack.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/AdaptedHttpStack.java
rename to core/src/main/java/com/android/volley/toolbox/AdaptedHttpStack.java
diff --git a/src/main/java/com/android/volley/toolbox/AndroidAuthenticator.java b/core/src/main/java/com/android/volley/toolbox/AndroidAuthenticator.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/AndroidAuthenticator.java
rename to core/src/main/java/com/android/volley/toolbox/AndroidAuthenticator.java
diff --git a/src/main/java/com/android/volley/toolbox/AsyncHttpStack.java b/core/src/main/java/com/android/volley/toolbox/AsyncHttpStack.java
similarity index 96%
rename from src/main/java/com/android/volley/toolbox/AsyncHttpStack.java
rename to core/src/main/java/com/android/volley/toolbox/AsyncHttpStack.java
index bafab8c..4165637 100644
--- a/src/main/java/com/android/volley/toolbox/AsyncHttpStack.java
+++ b/core/src/main/java/com/android/volley/toolbox/AsyncHttpStack.java
@@ -28,7 +28,12 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
-/** Asynchronous extension of the {@link BaseHttpStack} class. */
+/**
+ * Asynchronous extension of the {@link BaseHttpStack} class.
+ *
+ * <p><b>WARNING</b>: This API is experimental and subject to breaking changes. Please see
+ * https://github.com/google/volley/wiki/Asynchronous-Volley for more details.
+ */
public abstract class AsyncHttpStack extends BaseHttpStack {
private ExecutorService mBlockingExecutor;
private ExecutorService mNonBlockingExecutor;
diff --git a/src/main/java/com/android/volley/toolbox/Authenticator.java b/core/src/main/java/com/android/volley/toolbox/Authenticator.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/Authenticator.java
rename to core/src/main/java/com/android/volley/toolbox/Authenticator.java
diff --git a/src/main/java/com/android/volley/toolbox/BaseHttpStack.java b/core/src/main/java/com/android/volley/toolbox/BaseHttpStack.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/BaseHttpStack.java
rename to core/src/main/java/com/android/volley/toolbox/BaseHttpStack.java
diff --git a/src/main/java/com/android/volley/toolbox/BasicAsyncNetwork.java b/core/src/main/java/com/android/volley/toolbox/BasicAsyncNetwork.java
similarity index 86%
rename from src/main/java/com/android/volley/toolbox/BasicAsyncNetwork.java
rename to core/src/main/java/com/android/volley/toolbox/BasicAsyncNetwork.java
index 55892a0..cdedaff 100644
--- a/src/main/java/com/android/volley/toolbox/BasicAsyncNetwork.java
+++ b/core/src/main/java/com/android/volley/toolbox/BasicAsyncNetwork.java
@@ -29,6 +29,7 @@
import com.android.volley.Request;
import com.android.volley.RequestTask;
import com.android.volley.VolleyError;
+import com.android.volley.toolbox.NetworkUtility.RetryInfo;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
@@ -36,7 +37,12 @@
import java.util.Map;
import java.util.concurrent.ExecutorService;
-/** A network performing Volley requests over an {@link HttpStack}. */
+/**
+ * A network performing Volley requests over an {@link HttpStack}.
+ *
+ * <p><b>WARNING</b>: This API is experimental and subject to breaking changes. Please see
+ * https://github.com/google/volley/wiki/Asynchronous-Volley for more details.
+ */
public class BasicAsyncNetwork extends AsyncNetwork {
private final AsyncHttpStack mAsyncStack;
@@ -126,13 +132,39 @@
@Nullable HttpResponse httpResponse,
@Nullable byte[] responseContents) {
try {
- NetworkUtility.handleException(
- request, exception, requestStartMs, httpResponse, responseContents);
+ RetryInfo retryInfo =
+ NetworkUtility.shouldRetryException(
+ request, exception, requestStartMs, httpResponse, responseContents);
+ // RetryPolicy#retry may need a background thread, so invoke in the blocking executor.
+ getBlockingExecutor()
+ .execute(new InvokeRetryPolicyTask<>(request, retryInfo, callback));
} catch (VolleyError volleyError) {
callback.onError(volleyError);
- return;
}
- performRequest(request, callback);
+ }
+
+ private class InvokeRetryPolicyTask<T> extends RequestTask<T> {
+ final Request<T> request;
+ final RetryInfo retryInfo;
+ final OnRequestComplete callback;
+
+ InvokeRetryPolicyTask(Request<T> request, RetryInfo retryInfo, OnRequestComplete callback) {
+ super(request);
+ this.request = request;
+ this.retryInfo = retryInfo;
+ this.callback = callback;
+ }
+
+ @Override
+ public void run() {
+ try {
+ NetworkUtility.attemptRetryOnException(request, retryInfo);
+ // attemptRetryOnException didn't throw, so proceed with the next attempt.
+ performRequest(request, callback);
+ } catch (VolleyError e) {
+ callback.onError(e);
+ }
+ }
}
@Override
diff --git a/src/main/java/com/android/volley/toolbox/BasicNetwork.java b/core/src/main/java/com/android/volley/toolbox/BasicNetwork.java
similarity index 93%
rename from src/main/java/com/android/volley/toolbox/BasicNetwork.java
rename to core/src/main/java/com/android/volley/toolbox/BasicNetwork.java
index 06427fe..552e628 100644
--- a/src/main/java/com/android/volley/toolbox/BasicNetwork.java
+++ b/core/src/main/java/com/android/volley/toolbox/BasicNetwork.java
@@ -22,6 +22,7 @@
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.VolleyError;
+import com.android.volley.toolbox.NetworkUtility.RetryInfo;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
@@ -140,8 +141,11 @@
} catch (IOException e) {
// This will either throw an exception, breaking us from the loop, or will loop
// again and retry the request.
- NetworkUtility.handleException(
- request, e, requestStart, httpResponse, responseContents);
+ RetryInfo retryInfo =
+ NetworkUtility.shouldRetryException(
+ request, e, requestStart, httpResponse, responseContents);
+ // We should already be on a background thread, so we can invoke the retry inline.
+ NetworkUtility.attemptRetryOnException(request, retryInfo);
}
}
}
diff --git a/src/main/java/com/android/volley/toolbox/ByteArrayPool.java b/core/src/main/java/com/android/volley/toolbox/ByteArrayPool.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/ByteArrayPool.java
rename to core/src/main/java/com/android/volley/toolbox/ByteArrayPool.java
diff --git a/src/main/java/com/android/volley/toolbox/ClearCacheRequest.java b/core/src/main/java/com/android/volley/toolbox/ClearCacheRequest.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/ClearCacheRequest.java
rename to core/src/main/java/com/android/volley/toolbox/ClearCacheRequest.java
diff --git a/src/main/java/com/android/volley/toolbox/DiskBasedCache.java b/core/src/main/java/com/android/volley/toolbox/DiskBasedCache.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/DiskBasedCache.java
rename to core/src/main/java/com/android/volley/toolbox/DiskBasedCache.java
diff --git a/src/main/java/com/android/volley/toolbox/FileSupplier.java b/core/src/main/java/com/android/volley/toolbox/FileSupplier.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/FileSupplier.java
rename to core/src/main/java/com/android/volley/toolbox/FileSupplier.java
diff --git a/src/main/java/com/android/volley/toolbox/HttpClientStack.java b/core/src/main/java/com/android/volley/toolbox/HttpClientStack.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/HttpClientStack.java
rename to core/src/main/java/com/android/volley/toolbox/HttpClientStack.java
diff --git a/src/main/java/com/android/volley/toolbox/HttpHeaderParser.java b/core/src/main/java/com/android/volley/toolbox/HttpHeaderParser.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/HttpHeaderParser.java
rename to core/src/main/java/com/android/volley/toolbox/HttpHeaderParser.java
diff --git a/src/main/java/com/android/volley/toolbox/HttpResponse.java b/core/src/main/java/com/android/volley/toolbox/HttpResponse.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/HttpResponse.java
rename to core/src/main/java/com/android/volley/toolbox/HttpResponse.java
diff --git a/src/main/java/com/android/volley/toolbox/HttpStack.java b/core/src/main/java/com/android/volley/toolbox/HttpStack.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/HttpStack.java
rename to core/src/main/java/com/android/volley/toolbox/HttpStack.java
diff --git a/src/main/java/com/android/volley/toolbox/HurlStack.java b/core/src/main/java/com/android/volley/toolbox/HurlStack.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/HurlStack.java
rename to core/src/main/java/com/android/volley/toolbox/HurlStack.java
diff --git a/src/main/java/com/android/volley/toolbox/ImageLoader.java b/core/src/main/java/com/android/volley/toolbox/ImageLoader.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/ImageLoader.java
rename to core/src/main/java/com/android/volley/toolbox/ImageLoader.java
diff --git a/src/main/java/com/android/volley/toolbox/ImageRequest.java b/core/src/main/java/com/android/volley/toolbox/ImageRequest.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/ImageRequest.java
rename to core/src/main/java/com/android/volley/toolbox/ImageRequest.java
diff --git a/src/main/java/com/android/volley/toolbox/JsonArrayRequest.java b/core/src/main/java/com/android/volley/toolbox/JsonArrayRequest.java
similarity index 92%
rename from src/main/java/com/android/volley/toolbox/JsonArrayRequest.java
rename to core/src/main/java/com/android/volley/toolbox/JsonArrayRequest.java
index 86ed9e9..9f56746 100644
--- a/src/main/java/com/android/volley/toolbox/JsonArrayRequest.java
+++ b/core/src/main/java/com/android/volley/toolbox/JsonArrayRequest.java
@@ -26,7 +26,10 @@
import org.json.JSONArray;
import org.json.JSONException;
-/** A request for retrieving a {@link JSONArray} response body at a given URL. */
+/**
+ * A request for retrieving a {@link JSONArray} response body at a given URL, allowing for an
+ * optional {@link JSONArray} to be passed in as part of the request body.
+ */
public class JsonArrayRequest extends JsonRequest<JSONArray> {
/**
@@ -60,7 +63,7 @@
super(
method,
url,
- (jsonRequest == null) ? null : jsonRequest.toString(),
+ jsonRequest != null ? jsonRequest.toString() : null,
listener,
errorListener);
}
diff --git a/src/main/java/com/android/volley/toolbox/JsonObjectRequest.java b/core/src/main/java/com/android/volley/toolbox/JsonObjectRequest.java
similarity index 82%
rename from src/main/java/com/android/volley/toolbox/JsonObjectRequest.java
rename to core/src/main/java/com/android/volley/toolbox/JsonObjectRequest.java
index 8dca0ec..eccb54b 100644
--- a/src/main/java/com/android/volley/toolbox/JsonObjectRequest.java
+++ b/core/src/main/java/com/android/volley/toolbox/JsonObjectRequest.java
@@ -35,6 +35,38 @@
/**
* Creates a new request.
*
+ * @param url URL to fetch the JSON from
+ * @param listener Listener to receive the JSON response
+ * @param errorListener Error listener, or null to ignore errors.
+ */
+ public JsonObjectRequest(
+ String url, Listener<JSONObject> listener, @Nullable ErrorListener errorListener) {
+ super(Method.GET, url, null, listener, errorListener);
+ }
+
+ /**
+ * Constructor which defaults to <code>GET</code> if <code>jsonRequest</code> is <code>null
+ * </code> , <code>POST</code> otherwise.
+ *
+ * @deprecated Use {@link #JsonObjectRequest(int, String, JSONObject, Listener, ErrorListener)}.
+ */
+ @Deprecated
+ public JsonObjectRequest(
+ String url,
+ @Nullable JSONObject jsonRequest,
+ Listener<JSONObject> listener,
+ @Nullable ErrorListener errorListener) {
+ super(
+ jsonRequest == null ? Method.GET : Method.POST,
+ url,
+ jsonRequest != null ? jsonRequest.toString() : null,
+ listener,
+ errorListener);
+ }
+
+ /**
+ * Creates a new request.
+ *
* @param method the HTTP method to use
* @param url URL to fetch the JSON from
* @param jsonRequest A {@link JSONObject} to post with the request. Null indicates no
@@ -51,26 +83,7 @@
super(
method,
url,
- (jsonRequest == null) ? null : jsonRequest.toString(),
- listener,
- errorListener);
- }
-
- /**
- * Constructor which defaults to <code>GET</code> if <code>jsonRequest</code> is <code>null
- * </code> , <code>POST</code> otherwise.
- *
- * @see #JsonObjectRequest(int, String, JSONObject, Listener, ErrorListener)
- */
- public JsonObjectRequest(
- String url,
- @Nullable JSONObject jsonRequest,
- Listener<JSONObject> listener,
- @Nullable ErrorListener errorListener) {
- this(
- jsonRequest == null ? Method.GET : Method.POST,
- url,
- jsonRequest,
+ jsonRequest != null ? jsonRequest.toString() : null,
listener,
errorListener);
}
diff --git a/src/main/java/com/android/volley/toolbox/JsonRequest.java b/core/src/main/java/com/android/volley/toolbox/JsonRequest.java
similarity index 90%
rename from src/main/java/com/android/volley/toolbox/JsonRequest.java
rename to core/src/main/java/com/android/volley/toolbox/JsonRequest.java
index bc035ae..c2d1fad 100644
--- a/src/main/java/com/android/volley/toolbox/JsonRequest.java
+++ b/core/src/main/java/com/android/volley/toolbox/JsonRequest.java
@@ -61,6 +61,16 @@
this(Method.DEPRECATED_GET_OR_POST, url, requestBody, listener, errorListener);
}
+ /**
+ * Creates a new request.
+ *
+ * @param method the HTTP method to use
+ * @param url URL to fetch the JSON from
+ * @param requestBody The content to post as the body of the request. Null indicates no
+ * parameters will be posted along with request.
+ * @param listener Listener to receive the JSON response
+ * @param errorListener Error listener, or null to ignore errors.
+ */
public JsonRequest(
int method,
String url,
diff --git a/src/main/java/com/android/volley/toolbox/NetworkImageView.java b/core/src/main/java/com/android/volley/toolbox/NetworkImageView.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/NetworkImageView.java
rename to core/src/main/java/com/android/volley/toolbox/NetworkImageView.java
diff --git a/src/main/java/com/android/volley/toolbox/NetworkUtility.java b/core/src/main/java/com/android/volley/toolbox/NetworkUtility.java
similarity index 78%
rename from src/main/java/com/android/volley/toolbox/NetworkUtility.java
rename to core/src/main/java/com/android/volley/toolbox/NetworkUtility.java
index 44d5904..58a3bb3 100644
--- a/src/main/java/com/android/volley/toolbox/NetworkUtility.java
+++ b/core/src/main/java/com/android/volley/toolbox/NetworkUtility.java
@@ -42,7 +42,7 @@
* Utility class for methods that are shared between {@link BasicNetwork} and {@link
* BasicAsyncNetwork}
*/
-public final class NetworkUtility {
+final class NetworkUtility {
private static final int SLOW_REQUEST_THRESHOLD_MS = 3000;
private NetworkUtility() {}
@@ -113,30 +113,45 @@
/**
* Attempts to prepare the request for a retry. If there are no more attempts remaining in the
- * request's retry policy, a timeout exception is thrown.
+ * request's retry policy, the provided exception is thrown.
+ *
+ * <p>Must be invoked from a background thread, as client implementations of RetryPolicy#retry
+ * may make blocking calls.
*
* @param request The request to use.
*/
- private static void attemptRetryOnException(
- final String logPrefix, final Request<?> request, final VolleyError exception)
+ static void attemptRetryOnException(final Request<?> request, final RetryInfo retryInfo)
throws VolleyError {
final RetryPolicy retryPolicy = request.getRetryPolicy();
final int oldTimeout = request.getTimeoutMs();
try {
- retryPolicy.retry(exception);
+ retryPolicy.retry(retryInfo.errorToRetry);
} catch (VolleyError e) {
request.addMarker(
- String.format("%s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout));
+ String.format(
+ "%s-timeout-giveup [timeout=%s]", retryInfo.logPrefix, oldTimeout));
throw e;
}
- request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, oldTimeout));
+ request.addMarker(String.format("%s-retry [timeout=%s]", retryInfo.logPrefix, oldTimeout));
+ }
+
+ static class RetryInfo {
+ private final String logPrefix;
+ private final VolleyError errorToRetry;
+
+ private RetryInfo(String logPrefix, VolleyError errorToRetry) {
+ this.logPrefix = logPrefix;
+ this.errorToRetry = errorToRetry;
+ }
}
/**
* Based on the exception thrown, decides whether to attempt to retry, or to throw the error.
- * Also handles logging.
+ *
+ * <p>If this method returns without throwing, {@link #attemptRetryOnException} should be called
+ * with the provided {@link RetryInfo} to consult the client's retry policy.
*/
- static void handleException(
+ static RetryInfo shouldRetryException(
Request<?> request,
IOException exception,
long requestStartMs,
@@ -144,7 +159,7 @@
@Nullable byte[] responseContents)
throws VolleyError {
if (exception instanceof SocketTimeoutException) {
- attemptRetryOnException("socket", request, new TimeoutError());
+ return new RetryInfo("socket", new TimeoutError());
} else if (exception instanceof MalformedURLException) {
throw new RuntimeException("Bad URL " + request.getUrl(), exception);
} else {
@@ -153,11 +168,9 @@
statusCode = httpResponse.getStatusCode();
} else {
if (request.shouldRetryConnectionErrors()) {
- attemptRetryOnException("connection", request, new NoConnectionError());
- return;
- } else {
- throw new NoConnectionError(exception);
+ return new RetryInfo("connection", new NoConnectionError());
}
+ throw new NoConnectionError(exception);
}
VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
NetworkResponse networkResponse;
@@ -173,24 +186,21 @@
responseHeaders);
if (statusCode == HttpURLConnection.HTTP_UNAUTHORIZED
|| statusCode == HttpURLConnection.HTTP_FORBIDDEN) {
- attemptRetryOnException("auth", request, new AuthFailureError(networkResponse));
- } else if (statusCode >= 400 && statusCode <= 499) {
+ return new RetryInfo("auth", new AuthFailureError(networkResponse));
+ }
+ if (statusCode >= 400 && statusCode <= 499) {
// Don't retry other client errors.
throw new ClientError(networkResponse);
- } else if (statusCode >= 500 && statusCode <= 599) {
- if (request.shouldRetryServerErrors()) {
- attemptRetryOnException(
- "server", request, new ServerError(networkResponse));
- } else {
- throw new ServerError(networkResponse);
- }
- } else {
- // 3xx? No reason to retry.
- throw new ServerError(networkResponse);
}
- } else {
- attemptRetryOnException("network", request, new NetworkError());
+ if (statusCode >= 500 && statusCode <= 599) {
+ if (request.shouldRetryServerErrors()) {
+ return new RetryInfo("server", new ServerError(networkResponse));
+ }
+ }
+ // Server error and client has opted out of retries, or 3xx. No reason to retry.
+ throw new ServerError(networkResponse);
}
+ return new RetryInfo("network", new NetworkError());
}
}
}
diff --git a/src/main/java/com/android/volley/toolbox/NoAsyncCache.java b/core/src/main/java/com/android/volley/toolbox/NoAsyncCache.java
similarity index 80%
rename from src/main/java/com/android/volley/toolbox/NoAsyncCache.java
rename to core/src/main/java/com/android/volley/toolbox/NoAsyncCache.java
index aa4aeea..1fda58f 100644
--- a/src/main/java/com/android/volley/toolbox/NoAsyncCache.java
+++ b/core/src/main/java/com/android/volley/toolbox/NoAsyncCache.java
@@ -3,7 +3,12 @@
import com.android.volley.AsyncCache;
import com.android.volley.Cache;
-/** An AsyncCache that doesn't cache anything. */
+/**
+ * An AsyncCache that doesn't cache anything.
+ *
+ * <p><b>WARNING</b>: This API is experimental and subject to breaking changes. Please see
+ * https://github.com/google/volley/wiki/Asynchronous-Volley for more details.
+ */
public class NoAsyncCache extends AsyncCache {
@Override
public void get(String key, OnGetCompleteCallback callback) {
diff --git a/src/main/java/com/android/volley/toolbox/NoCache.java b/core/src/main/java/com/android/volley/toolbox/NoCache.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/NoCache.java
rename to core/src/main/java/com/android/volley/toolbox/NoCache.java
diff --git a/src/main/java/com/android/volley/toolbox/PoolingByteArrayOutputStream.java b/core/src/main/java/com/android/volley/toolbox/PoolingByteArrayOutputStream.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/PoolingByteArrayOutputStream.java
rename to core/src/main/java/com/android/volley/toolbox/PoolingByteArrayOutputStream.java
diff --git a/src/main/java/com/android/volley/toolbox/RequestFuture.java b/core/src/main/java/com/android/volley/toolbox/RequestFuture.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/RequestFuture.java
rename to core/src/main/java/com/android/volley/toolbox/RequestFuture.java
diff --git a/src/main/java/com/android/volley/toolbox/StringRequest.java b/core/src/main/java/com/android/volley/toolbox/StringRequest.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/StringRequest.java
rename to core/src/main/java/com/android/volley/toolbox/StringRequest.java
diff --git a/src/main/java/com/android/volley/toolbox/Threads.java b/core/src/main/java/com/android/volley/toolbox/Threads.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/Threads.java
rename to core/src/main/java/com/android/volley/toolbox/Threads.java
diff --git a/src/main/java/com/android/volley/toolbox/UrlRewriter.java b/core/src/main/java/com/android/volley/toolbox/UrlRewriter.java
similarity index 100%
rename from src/main/java/com/android/volley/toolbox/UrlRewriter.java
rename to core/src/main/java/com/android/volley/toolbox/UrlRewriter.java
diff --git a/src/main/java/com/android/volley/toolbox/Volley.java b/core/src/main/java/com/android/volley/toolbox/Volley.java
similarity index 97%
rename from src/main/java/com/android/volley/toolbox/Volley.java
rename to core/src/main/java/com/android/volley/toolbox/Volley.java
index bc65c9c..6ab34bb 100644
--- a/src/main/java/com/android/volley/toolbox/Volley.java
+++ b/core/src/main/java/com/android/volley/toolbox/Volley.java
@@ -21,6 +21,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.http.AndroidHttpClient;
import android.os.Build;
+import androidx.annotation.NonNull;
import com.android.volley.Network;
import com.android.volley.RequestQueue;
import java.io.File;
@@ -37,6 +38,7 @@
* @param stack A {@link BaseHttpStack} to use for the network, or null for default.
* @return A started {@link RequestQueue} instance.
*/
+ @NonNull
public static RequestQueue newRequestQueue(Context context, BaseHttpStack stack) {
BasicNetwork network;
if (stack == null) {
@@ -78,6 +80,7 @@
*/
@Deprecated
@SuppressWarnings("deprecation")
+ @NonNull
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
if (stack == null) {
return newRequestQueue(context, (BaseHttpStack) null);
@@ -85,6 +88,7 @@
return newRequestQueue(context, new BasicNetwork(stack));
}
+ @NonNull
private static RequestQueue newRequestQueue(Context context, Network network) {
final Context appContext = context.getApplicationContext();
// Use a lazy supplier for the cache directory so that newRequestQueue() can be called on
@@ -112,6 +116,7 @@
* @param context A {@link Context} to use for creating the cache dir.
* @return A started {@link RequestQueue} instance.
*/
+ @NonNull
public static RequestQueue newRequestQueue(Context context) {
return newRequestQueue(context, (BaseHttpStack) null);
}
diff --git a/src/test/java/com/android/volley/AsyncRequestQueueTest.java b/core/src/test/java/com/android/volley/AsyncRequestQueueTest.java
similarity index 64%
rename from src/test/java/com/android/volley/AsyncRequestQueueTest.java
rename to core/src/test/java/com/android/volley/AsyncRequestQueueTest.java
index 54ff0a1..aef4f01 100644
--- a/src/test/java/com/android/volley/AsyncRequestQueueTest.java
+++ b/core/src/test/java/com/android/volley/AsyncRequestQueueTest.java
@@ -16,6 +16,9 @@
package com.android.volley;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -23,6 +26,8 @@
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
+import com.android.volley.AsyncCache.OnGetCompleteCallback;
+import com.android.volley.AsyncCache.OnWriteCompleteCallback;
import com.android.volley.mock.ShadowSystemClock;
import com.android.volley.toolbox.NoAsyncCache;
import com.android.volley.toolbox.StringRequest;
@@ -34,6 +39,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
@@ -45,37 +51,13 @@
@Mock private AsyncNetwork mMockNetwork;
@Mock private ScheduledExecutorService mMockScheduledExecutor;
+ private final ResponseDelivery mDelivery = new ImmediateResponseDelivery();
private AsyncRequestQueue queue;
@Before
public void setUp() throws Exception {
- ResponseDelivery mDelivery = new ImmediateResponseDelivery();
initMocks(this);
- queue =
- new AsyncRequestQueue.Builder(mMockNetwork)
- .setAsyncCache(new NoAsyncCache())
- .setResponseDelivery(mDelivery)
- .setExecutorFactory(
- new AsyncRequestQueue.ExecutorFactory() {
- @Override
- public ExecutorService createNonBlockingExecutor(
- BlockingQueue<Runnable> taskQueue) {
- return MoreExecutors.newDirectExecutorService();
- }
-
- @Override
- public ExecutorService createBlockingExecutor(
- BlockingQueue<Runnable> taskQueue) {
- return MoreExecutors.newDirectExecutorService();
- }
-
- @Override
- public ScheduledExecutorService
- createNonBlockingScheduledExecutor() {
- return mMockScheduledExecutor;
- }
- })
- .build();
+ queue = createRequestQueue(new NoAsyncCache());
}
@Test
@@ -161,4 +143,58 @@
verifyNoMoreInteractions(listener);
queue.stop();
}
+
+ @Test
+ public void requestsQueuedBeforeCacheInitialization_asyncCache() {
+ // Create a new queue with a mock cache in order to verify the initialization.
+ AsyncCache mockAsyncCache = mock(AsyncCache.class);
+ AsyncRequestQueue queue = createRequestQueue(mockAsyncCache);
+ queue.start();
+
+ ArgumentCaptor<OnWriteCompleteCallback> callbackCaptor =
+ ArgumentCaptor.forClass(OnWriteCompleteCallback.class);
+ verify(mockAsyncCache).initialize(callbackCaptor.capture());
+
+ StringRequest req = mock(StringRequest.class);
+ req.setShouldCache(true);
+ when(req.getCacheKey()).thenReturn("cache-key");
+ queue.add(req);
+
+ // Cache should not be read before initialization completes.
+ verify(mockAsyncCache, never()).get(anyString(), any(OnGetCompleteCallback.class));
+
+ callbackCaptor.getValue().onWriteComplete();
+
+ // Once the write completes, the request should be kicked off (in the form of a cache
+ // lookup).
+ verify(mockAsyncCache).get(eq("cache-key"), any(OnGetCompleteCallback.class));
+
+ queue.stop();
+ }
+
+ private AsyncRequestQueue createRequestQueue(AsyncCache asyncCache) {
+ return new AsyncRequestQueue.Builder(mMockNetwork)
+ .setResponseDelivery(mDelivery)
+ .setAsyncCache(asyncCache)
+ .setExecutorFactory(
+ new AsyncRequestQueue.ExecutorFactory() {
+ @Override
+ public ExecutorService createNonBlockingExecutor(
+ BlockingQueue<Runnable> taskQueue) {
+ return MoreExecutors.newDirectExecutorService();
+ }
+
+ @Override
+ public ExecutorService createBlockingExecutor(
+ BlockingQueue<Runnable> taskQueue) {
+ return MoreExecutors.newDirectExecutorService();
+ }
+
+ @Override
+ public ScheduledExecutorService createNonBlockingScheduledExecutor() {
+ return mMockScheduledExecutor;
+ }
+ })
+ .build();
+ }
}
diff --git a/src/test/java/com/android/volley/CacheDispatcherTest.java b/core/src/test/java/com/android/volley/CacheDispatcherTest.java
similarity index 100%
rename from src/test/java/com/android/volley/CacheDispatcherTest.java
rename to core/src/test/java/com/android/volley/CacheDispatcherTest.java
diff --git a/src/test/java/com/android/volley/NetworkDispatcherTest.java b/core/src/test/java/com/android/volley/NetworkDispatcherTest.java
similarity index 100%
rename from src/test/java/com/android/volley/NetworkDispatcherTest.java
rename to core/src/test/java/com/android/volley/NetworkDispatcherTest.java
diff --git a/src/test/java/com/android/volley/NetworkResponseTest.java b/core/src/test/java/com/android/volley/NetworkResponseTest.java
similarity index 100%
rename from src/test/java/com/android/volley/NetworkResponseTest.java
rename to core/src/test/java/com/android/volley/NetworkResponseTest.java
diff --git a/src/test/java/com/android/volley/RequestQueueIntegrationTest.java b/core/src/test/java/com/android/volley/RequestQueueIntegrationTest.java
similarity index 100%
rename from src/test/java/com/android/volley/RequestQueueIntegrationTest.java
rename to core/src/test/java/com/android/volley/RequestQueueIntegrationTest.java
diff --git a/src/test/java/com/android/volley/RequestQueueTest.java b/core/src/test/java/com/android/volley/RequestQueueTest.java
similarity index 100%
rename from src/test/java/com/android/volley/RequestQueueTest.java
rename to core/src/test/java/com/android/volley/RequestQueueTest.java
diff --git a/src/test/java/com/android/volley/RequestTest.java b/core/src/test/java/com/android/volley/RequestTest.java
similarity index 100%
rename from src/test/java/com/android/volley/RequestTest.java
rename to core/src/test/java/com/android/volley/RequestTest.java
diff --git a/src/test/java/com/android/volley/ResponseDeliveryTest.java b/core/src/test/java/com/android/volley/ResponseDeliveryTest.java
similarity index 100%
rename from src/test/java/com/android/volley/ResponseDeliveryTest.java
rename to core/src/test/java/com/android/volley/ResponseDeliveryTest.java
diff --git a/src/test/java/com/android/volley/mock/MockAsyncStack.java b/core/src/test/java/com/android/volley/mock/MockAsyncStack.java
similarity index 100%
rename from src/test/java/com/android/volley/mock/MockAsyncStack.java
rename to core/src/test/java/com/android/volley/mock/MockAsyncStack.java
diff --git a/src/test/java/com/android/volley/mock/MockHttpStack.java b/core/src/test/java/com/android/volley/mock/MockHttpStack.java
similarity index 100%
rename from src/test/java/com/android/volley/mock/MockHttpStack.java
rename to core/src/test/java/com/android/volley/mock/MockHttpStack.java
diff --git a/src/test/java/com/android/volley/mock/MockRequest.java b/core/src/test/java/com/android/volley/mock/MockRequest.java
similarity index 100%
rename from src/test/java/com/android/volley/mock/MockRequest.java
rename to core/src/test/java/com/android/volley/mock/MockRequest.java
diff --git a/src/test/java/com/android/volley/mock/ShadowSystemClock.java b/core/src/test/java/com/android/volley/mock/ShadowSystemClock.java
similarity index 100%
rename from src/test/java/com/android/volley/mock/ShadowSystemClock.java
rename to core/src/test/java/com/android/volley/mock/ShadowSystemClock.java
diff --git a/src/test/java/com/android/volley/toolbox/AdaptedHttpStackTest.java b/core/src/test/java/com/android/volley/toolbox/AdaptedHttpStackTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/AdaptedHttpStackTest.java
rename to core/src/test/java/com/android/volley/toolbox/AdaptedHttpStackTest.java
diff --git a/src/test/java/com/android/volley/toolbox/AndroidAuthenticatorTest.java b/core/src/test/java/com/android/volley/toolbox/AndroidAuthenticatorTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/AndroidAuthenticatorTest.java
rename to core/src/test/java/com/android/volley/toolbox/AndroidAuthenticatorTest.java
diff --git a/src/test/java/com/android/volley/toolbox/BaseHttpStackTest.java b/core/src/test/java/com/android/volley/toolbox/BaseHttpStackTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/BaseHttpStackTest.java
rename to core/src/test/java/com/android/volley/toolbox/BaseHttpStackTest.java
diff --git a/src/test/java/com/android/volley/toolbox/BasicAsyncNetworkTest.java b/core/src/test/java/com/android/volley/toolbox/BasicAsyncNetworkTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/BasicAsyncNetworkTest.java
rename to core/src/test/java/com/android/volley/toolbox/BasicAsyncNetworkTest.java
diff --git a/src/test/java/com/android/volley/toolbox/BasicNetworkTest.java b/core/src/test/java/com/android/volley/toolbox/BasicNetworkTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/BasicNetworkTest.java
rename to core/src/test/java/com/android/volley/toolbox/BasicNetworkTest.java
diff --git a/src/test/java/com/android/volley/toolbox/ByteArrayPoolTest.java b/core/src/test/java/com/android/volley/toolbox/ByteArrayPoolTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/ByteArrayPoolTest.java
rename to core/src/test/java/com/android/volley/toolbox/ByteArrayPoolTest.java
diff --git a/src/test/java/com/android/volley/toolbox/CacheTest.java b/core/src/test/java/com/android/volley/toolbox/CacheTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/CacheTest.java
rename to core/src/test/java/com/android/volley/toolbox/CacheTest.java
diff --git a/src/test/java/com/android/volley/toolbox/DiskBasedCacheTest.java b/core/src/test/java/com/android/volley/toolbox/DiskBasedCacheTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/DiskBasedCacheTest.java
rename to core/src/test/java/com/android/volley/toolbox/DiskBasedCacheTest.java
diff --git a/src/test/java/com/android/volley/toolbox/HttpClientStackTest.java b/core/src/test/java/com/android/volley/toolbox/HttpClientStackTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/HttpClientStackTest.java
rename to core/src/test/java/com/android/volley/toolbox/HttpClientStackTest.java
diff --git a/src/test/java/com/android/volley/toolbox/HttpHeaderParserTest.java b/core/src/test/java/com/android/volley/toolbox/HttpHeaderParserTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/HttpHeaderParserTest.java
rename to core/src/test/java/com/android/volley/toolbox/HttpHeaderParserTest.java
diff --git a/src/test/java/com/android/volley/toolbox/HttpStackConformanceTest.java b/core/src/test/java/com/android/volley/toolbox/HttpStackConformanceTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/HttpStackConformanceTest.java
rename to core/src/test/java/com/android/volley/toolbox/HttpStackConformanceTest.java
diff --git a/src/test/java/com/android/volley/toolbox/HurlStackTest.java b/core/src/test/java/com/android/volley/toolbox/HurlStackTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/HurlStackTest.java
rename to core/src/test/java/com/android/volley/toolbox/HurlStackTest.java
diff --git a/src/test/java/com/android/volley/toolbox/ImageLoaderTest.java b/core/src/test/java/com/android/volley/toolbox/ImageLoaderTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/ImageLoaderTest.java
rename to core/src/test/java/com/android/volley/toolbox/ImageLoaderTest.java
diff --git a/src/test/java/com/android/volley/toolbox/ImageRequestTest.java b/core/src/test/java/com/android/volley/toolbox/ImageRequestTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/ImageRequestTest.java
rename to core/src/test/java/com/android/volley/toolbox/ImageRequestTest.java
diff --git a/src/test/java/com/android/volley/toolbox/JsonRequestCharsetTest.java b/core/src/test/java/com/android/volley/toolbox/JsonRequestCharsetTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/JsonRequestCharsetTest.java
rename to core/src/test/java/com/android/volley/toolbox/JsonRequestCharsetTest.java
diff --git a/src/test/java/com/android/volley/toolbox/JsonRequestTest.java b/core/src/test/java/com/android/volley/toolbox/JsonRequestTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/JsonRequestTest.java
rename to core/src/test/java/com/android/volley/toolbox/JsonRequestTest.java
diff --git a/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java b/core/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java
rename to core/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java
diff --git a/src/test/java/com/android/volley/toolbox/PoolingByteArrayOutputStreamTest.java b/core/src/test/java/com/android/volley/toolbox/PoolingByteArrayOutputStreamTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/PoolingByteArrayOutputStreamTest.java
rename to core/src/test/java/com/android/volley/toolbox/PoolingByteArrayOutputStreamTest.java
diff --git a/src/test/java/com/android/volley/toolbox/RequestFutureTest.java b/core/src/test/java/com/android/volley/toolbox/RequestFutureTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/RequestFutureTest.java
rename to core/src/test/java/com/android/volley/toolbox/RequestFutureTest.java
diff --git a/src/test/java/com/android/volley/toolbox/RequestQueueTest.java b/core/src/test/java/com/android/volley/toolbox/RequestQueueTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/RequestQueueTest.java
rename to core/src/test/java/com/android/volley/toolbox/RequestQueueTest.java
diff --git a/src/test/java/com/android/volley/toolbox/RequestTest.java b/core/src/test/java/com/android/volley/toolbox/RequestTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/RequestTest.java
rename to core/src/test/java/com/android/volley/toolbox/RequestTest.java
diff --git a/src/test/java/com/android/volley/toolbox/ResponseTest.java b/core/src/test/java/com/android/volley/toolbox/ResponseTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/ResponseTest.java
rename to core/src/test/java/com/android/volley/toolbox/ResponseTest.java
diff --git a/src/test/java/com/android/volley/toolbox/StringRequestTest.java b/core/src/test/java/com/android/volley/toolbox/StringRequestTest.java
similarity index 100%
rename from src/test/java/com/android/volley/toolbox/StringRequestTest.java
rename to core/src/test/java/com/android/volley/toolbox/StringRequestTest.java
diff --git a/src/test/java/com/android/volley/utils/CacheTestUtils.java b/core/src/test/java/com/android/volley/utils/CacheTestUtils.java
similarity index 100%
rename from src/test/java/com/android/volley/utils/CacheTestUtils.java
rename to core/src/test/java/com/android/volley/utils/CacheTestUtils.java
diff --git a/src/test/java/com/android/volley/utils/ImmediateResponseDelivery.java b/core/src/test/java/com/android/volley/utils/ImmediateResponseDelivery.java
similarity index 100%
rename from src/test/java/com/android/volley/utils/ImmediateResponseDelivery.java
rename to core/src/test/java/com/android/volley/utils/ImmediateResponseDelivery.java
diff --git a/src/test/resources/org.robolectric.Config.properties b/core/src/test/resources/org.robolectric.Config.properties
similarity index 100%
rename from src/test/resources/org.robolectric.Config.properties
rename to core/src/test/resources/org.robolectric.Config.properties
diff --git a/cronet/build.gradle b/cronet/build.gradle
new file mode 100644
index 0000000..5ee53d6
--- /dev/null
+++ b/cronet/build.gradle
@@ -0,0 +1,24 @@
+dependencies {
+ implementation project(":core")
+ implementation "androidx.annotation:annotation:1.0.1"
+ compileOnly "org.chromium.net:cronet-embedded:76.3809.111"
+
+ testImplementation project(":testing")
+ testImplementation "org.chromium.net:cronet-embedded:76.3809.111"
+ testImplementation "junit:junit:4.12"
+ testImplementation "org.mockito:mockito-core:2.19.0"
+ testImplementation "org.robolectric:robolectric:3.4.2"
+}
+
+publishing {
+ publications {
+ library(MavenPublication) {
+ artifactId 'volley-cronet'
+ pom {
+ name = 'Volley Cronet'
+ description = 'Cronet support for Volley.'
+ }
+ artifact "$buildDir/outputs/aar/cronet-release.aar"
+ }
+ }
+}
diff --git a/cronet/src/main/AndroidManifest.xml b/cronet/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..0dec093
--- /dev/null
+++ b/cronet/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest package="com.android.volley.cronet" />
diff --git a/src/main/java/com/android/volley/cronet/CronetHttpStack.java b/cronet/src/main/java/com/android/volley/cronet/CronetHttpStack.java
similarity index 99%
rename from src/main/java/com/android/volley/cronet/CronetHttpStack.java
rename to cronet/src/main/java/com/android/volley/cronet/CronetHttpStack.java
index f3baace..874029b 100644
--- a/src/main/java/com/android/volley/cronet/CronetHttpStack.java
+++ b/cronet/src/main/java/com/android/volley/cronet/CronetHttpStack.java
@@ -53,6 +53,9 @@
/**
* A {@link AsyncHttpStack} that's based on Cronet's fully asynchronous API for network requests.
+ *
+ * <p><b>WARNING</b>: This API is experimental and subject to breaking changes. Please see
+ * https://github.com/google/volley/wiki/Asynchronous-Volley for more details.
*/
public class CronetHttpStack extends AsyncHttpStack {
diff --git a/src/test/java/com/android/volley/cronet/CronetHttpStackTest.java b/cronet/src/test/java/com/android/volley/cronet/CronetHttpStackTest.java
similarity index 100%
rename from src/test/java/com/android/volley/cronet/CronetHttpStackTest.java
rename to cronet/src/test/java/com/android/volley/cronet/CronetHttpStackTest.java
diff --git a/publish-snapshot-on-commit.sh b/publish-snapshot-on-commit.sh
index 0d0e034..ba02b79 100755
--- a/publish-snapshot-on-commit.sh
+++ b/publish-snapshot-on-commit.sh
@@ -1,13 +1,15 @@
set -eu
-if [ "$TRAVIS_REPO_SLUG" == "google/volley" ] && \
- [ "$TRAVIS_PULL_REQUEST" == "false" ] && \
- [ "$TRAVIS_BRANCH" == "master" ]; then
- echo -e "Publishing snapshot build to OJO...\n"
+GITHUB_BRANCH=${GITHUB_REF#refs/heads/}
- ./gradlew artifactoryPublish
+if [ "$GITHUB_REPOSITORY" == "google/volley" ] && \
+ [ "$GITHUB_EVENT_NAME" == "push" ] && \
+ [ "$GITHUB_BRANCH" == "master" ]; then
+ echo -e "Publishing snapshot build...\n"
- echo -e "Published snapshot build to OJO"
+ ./gradlew publish
+
+ echo -e "Published snapshot build"
else
echo -e "Not publishing snapshot"
-fi
\ No newline at end of file
+fi
diff --git a/publish.gradle b/publish.gradle
new file mode 100644
index 0000000..429df4d
--- /dev/null
+++ b/publish.gradle
@@ -0,0 +1,72 @@
+apply plugin: 'maven-publish'
+
+task sourcesJar(type: Jar) {
+ classifier = 'sources'
+ from android.sourceSets.main.java.srcDirs
+}
+
+task javadoc(type: Javadoc) {
+ source = android.sourceSets.main.java.srcDirs
+ classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
+}
+
+afterEvaluate {
+ javadoc.classpath += files(android.libraryVariants.collect { variant ->
+ variant.getJavaCompile().classpath.files
+ })
+}
+
+task javadocJar(type: Jar, dependsOn: javadoc) {
+ classifier = 'javadoc'
+ from javadoc.destinationDir
+}
+
+artifacts {
+ archives javadocJar
+ archives sourcesJar
+}
+
+publishing {
+ publications {
+ library(MavenPublication) {
+ groupId 'com.android.volley'
+ version project.version
+ pom {
+ name = 'Volley'
+ url = 'https://github.com/google/volley'
+ packaging 'aar'
+ licenses {
+ license {
+ name = "The Apache License, Version 2.0"
+ url = "http://www.apache.org/licenses/LICENSE-2.0.txt"
+ }
+ }
+ scm {
+ connection = 'scm:git:git://github.com/google/volley.git'
+ developerConnection = 'scm:git:ssh://git@github.com/google/volley.git'
+ url = 'https://github.com/google/volley'
+ }
+ developers {
+ developer {
+ name = 'The Volley Team'
+ email = 'noreply+volley@google.com'
+ }
+ }
+ }
+
+ // Release AAR, Sources, and JavaDoc
+ artifact sourcesJar
+ artifact javadocJar
+ }
+ }
+
+ repositories {
+ maven {
+ url = "https://oss.sonatype.org/content/repositories/snapshots/"
+ credentials {
+ username = System.env.OSSRH_DEPLOY_USERNAME
+ password = System.env.OSSRH_DEPLOY_PASSWORD
+ }
+ }
+ }
+}
diff --git a/rules.gradle b/rules.gradle
deleted file mode 100644
index e0aef80..0000000
--- a/rules.gradle
+++ /dev/null
@@ -1,36 +0,0 @@
-// See build.gradle for an explanation of what this file is.
-
-apply plugin: 'com.android.library'
-
-android {
- useLibrary 'org.apache.http.legacy'
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_7
- targetCompatibility JavaVersion.VERSION_1_7
- }
-
- defaultConfig {
- consumerProguardFiles 'consumer-proguard-rules.pro'
- }
-}
-
-tasks.withType(JavaCompile) {
- options.compilerArgs << "-Xlint:unchecked" << "-Werror"
-}
-
-dependencies {
- implementation "androidx.annotation:annotation:1.0.1"
- compileOnly "org.chromium.net:cronet-embedded:76.3809.111"
-}
-
-// Check if the android plugin version supports unit testing.
-if (configurations.findByName("testImplementation")) {
- dependencies {
- testImplementation "org.chromium.net:cronet-embedded:76.3809.111"
- testImplementation "junit:junit:4.12"
- testImplementation "org.hamcrest:hamcrest-library:1.3"
- testImplementation "org.mockito:mockito-core:2.19.0"
- testImplementation "org.robolectric:robolectric:3.4.2"
- }
-}
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..ace4000
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,4 @@
+rootProject.name = 'volley'
+include 'core'
+include 'cronet'
+include 'testing'
diff --git a/src/main/java/com/android/volley/RequestTask.java b/src/main/java/com/android/volley/RequestTask.java
deleted file mode 100644
index 8eeaf2c..0000000
--- a/src/main/java/com/android/volley/RequestTask.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.android.volley;
-
-/** Abstract runnable that's a task to be completed by the RequestQueue. */
-public abstract class RequestTask<T> implements Runnable {
- final Request<T> mRequest;
-
- public RequestTask(Request<T> request) {
- mRequest = request;
- }
-
- @SuppressWarnings("unchecked")
- public int compareTo(RequestTask<?> other) {
- return mRequest.compareTo((Request<T>) other.mRequest);
- }
-}
diff --git a/testing/build.gradle b/testing/build.gradle
new file mode 100644
index 0000000..b374088
--- /dev/null
+++ b/testing/build.gradle
@@ -0,0 +1,4 @@
+dependencies {
+ implementation project(":core")
+}
+
diff --git a/testing/src/main/AndroidManifest.xml b/testing/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..24b1376
--- /dev/null
+++ b/testing/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest package="com.android.volley.testing" />
diff --git a/src/test/java/com/android/volley/mock/TestRequest.java b/testing/src/main/java/com/android/volley/mock/TestRequest.java
similarity index 100%
rename from src/test/java/com/android/volley/mock/TestRequest.java
rename to testing/src/main/java/com/android/volley/mock/TestRequest.java