├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── styles.xml │ │ │ │ └── dimens.xml │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ └── layout │ │ │ │ └── log_item.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── app │ │ │ │ └── core │ │ │ │ └── example │ │ │ │ ├── App.java │ │ │ │ └── bean │ │ │ │ ├── BeautyBean.java │ │ │ │ └── CityRootBean.java │ │ ├── aidl │ │ │ └── com │ │ │ │ └── app │ │ │ │ └── core │ │ │ │ └── example │ │ │ │ ├── ILogProcessor.aidl │ │ │ │ ├── LogFormattedString.java │ │ │ │ └── LogProcessor.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── app │ │ │ └── core │ │ │ └── http │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── app │ │ └── core │ │ └── http │ │ └── ApplicationTest.java ├── proguard-rules.pro └── build.gradle ├── lib.http ├── .gitignore ├── gradle.properties ├── src │ ├── main │ │ ├── java │ │ │ └── net │ │ │ │ └── robinx │ │ │ │ └── lib │ │ │ │ └── http │ │ │ │ ├── base │ │ │ │ ├── Builder.java │ │ │ │ ├── IResponseDelivery.java │ │ │ │ └── IRequest.java │ │ │ │ ├── config │ │ │ │ ├── DataType.java │ │ │ │ ├── Priority.java │ │ │ │ ├── HttpMethod.java │ │ │ │ └── TimeController.java │ │ │ │ ├── callback │ │ │ │ ├── OnCacheDataListener.java │ │ │ │ ├── BytesWriteListener.java │ │ │ │ ├── OnRequestListenerAdapter.java │ │ │ │ └── OnRequestListener.java │ │ │ │ ├── converter │ │ │ │ ├── Converter.java │ │ │ │ └── GsonConverter.java │ │ │ │ ├── cache │ │ │ │ ├── Cache.java │ │ │ │ ├── CacheConfig.java │ │ │ │ ├── BitmapCache.java │ │ │ │ ├── Entry.java │ │ │ │ ├── memory │ │ │ │ │ └── MemoryCache.java │ │ │ │ ├── disk │ │ │ │ │ ├── Util.java │ │ │ │ │ └── StrictLineReader.java │ │ │ │ └── CacheData.java │ │ │ │ ├── network │ │ │ │ ├── ex │ │ │ │ │ ├── Body.java │ │ │ │ │ ├── HttpRequest.java │ │ │ │ │ ├── StringRequest.java │ │ │ │ │ ├── SyncRequest.java │ │ │ │ │ ├── hurl │ │ │ │ │ │ ├── RequestBodyConstants.java │ │ │ │ │ │ ├── HurlStack.java │ │ │ │ │ │ └── HurlRequestBody.java │ │ │ │ │ ├── RequestParams.java │ │ │ │ │ └── DownloadRequest.java │ │ │ │ ├── HttpError.java │ │ │ │ ├── HttpStack.java │ │ │ │ ├── HttpResponse.java │ │ │ │ ├── HttpStatus.java │ │ │ │ ├── PoolingByteArrayOutputStream.java │ │ │ │ ├── HTTPSTrustManager.java │ │ │ │ ├── HttpException.java │ │ │ │ ├── ByteArrayPool.java │ │ │ │ └── Network.java │ │ │ │ ├── utils │ │ │ │ ├── NetworkUtils.java │ │ │ │ ├── AppUtils.java │ │ │ │ └── GenericsUtils.java │ │ │ │ ├── retry │ │ │ │ ├── RetryPolicy.java │ │ │ │ └── DefaultRetryPolicyImpl.java │ │ │ │ ├── RequestContext.java │ │ │ │ ├── response │ │ │ │ ├── NetworkResponse.java │ │ │ │ └── Response.java │ │ │ │ ├── delivered │ │ │ │ └── IDelivery.java │ │ │ │ ├── XRequest.java │ │ │ │ └── dispatcher │ │ │ │ ├── NetworkDispatcher.java │ │ │ │ └── CacheDispatcher.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── app │ │ │ └── core │ │ │ └── http │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── app │ │ └── core │ │ └── http │ │ └── ApplicationTest.java ├── proguard-rules.pro └── build.gradle ├── lib.http.converters ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ └── values │ │ │ │ └── strings.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── net │ │ │ └── robinx │ │ │ └── lib │ │ │ └── http │ │ │ └── converters │ │ │ ├── FastjsonConverter.java │ │ │ └── JackSonConverter.java │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── app │ │ │ └── core │ │ │ └── http │ │ │ └── converters │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── app │ │ └── core │ │ └── http │ │ └── converters │ │ └── ApplicationTest.java ├── gradle.properties ├── proguard-rules.pro └── build.gradle ├── lib.http.okhttpsupport ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ └── values │ │ │ │ └── strings.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── net │ │ │ └── robinx │ │ │ └── lib │ │ │ └── http │ │ │ └── okhttp │ │ │ ├── RequestBodyProxy.java │ │ │ ├── OkRequestBody.java │ │ │ └── OkHttpStack.java │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── app │ │ │ └── core │ │ │ └── okhttp │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── app │ │ └── core │ │ └── okhttp │ │ └── ApplicationTest.java ├── gradle.properties ├── proguard-rules.pro └── build.gradle ├── 1.png ├── 2.png ├── gradle.properties ├── settings.gradle ├── XDroidRequestExample.apk ├── .idea ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── vcs.xml ├── runConfigurations.xml ├── compiler.xml ├── modules.xml ├── gradle.xml └── misc.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── script ├── make-jar.gradle └── gradle-jcenter-push.gradle ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /lib.http/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /lib.http.converters/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /lib.http.okhttpsupport/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinxdroid/HttpRequest/HEAD/1.png -------------------------------------------------------------------------------- /2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinxdroid/HttpRequest/HEAD/2.png -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinxdroid/HttpRequest/HEAD/gradle.properties -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':lib.http', ':lib.http.okhttpsupport', ':lib.http.converters' 2 | -------------------------------------------------------------------------------- /XDroidRequestExample.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinxdroid/HttpRequest/HEAD/XDroidRequestExample.apk -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | HttpRequest 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinxdroid/HttpRequest/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /lib.http/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_BINTRAY_NAME=HttpLibrary 2 | POM_DESCRIPTION=Android http library. 3 | POM_ARTIFACT_ID=lib.http -------------------------------------------------------------------------------- /lib.http.converters/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Converters 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /lib.http.okhttpsupport/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | OkHttpSupport 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinxdroid/HttpRequest/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinxdroid/HttpRequest/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinxdroid/HttpRequest/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinxdroid/HttpRequest/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #E86767 4 | 5 | -------------------------------------------------------------------------------- /lib.http.converters/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_BINTRAY_NAME=HttpConvertersLibrary 2 | POM_DESCRIPTION=Android http converters library. 3 | POM_ARTIFACT_ID=lib.http.converters -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinxdroid/HttpRequest/HEAD/app/src/main/res/mipmap-xhdpi/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib.http.okhttpsupport/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_BINTRAY_NAME=HttpOkHttpSupportLibrary 2 | POM_DESCRIPTION=Android okhttp support library. 3 | POM_ARTIFACT_ID=lib.http.okhttpsupport -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/base/Builder.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.base; 2 | 3 | /** 4 | * Created by Robin on 2016/5/5. 5 | */ 6 | public interface Builder { 7 | T build(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/config/DataType.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.config; 2 | 3 | /** 4 | * The types of data delivery 5 | * @author Robin 6 | * @since 2015-05-08 16:18:07 7 | */ 8 | public enum DataType { 9 | 10 | CACHE_DATA,NETWORK_DATA; 11 | } 12 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Nov 18 17:44:07 GMT+08:00 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /lib.http/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/callback/OnCacheDataListener.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.callback; 2 | 3 | /** 4 | * the operation with cache callback 5 | * @author Robin 6 | * @since 2015-05-08 00:26:40 7 | */ 8 | public interface OnCacheDataListener { 9 | 10 | public void onFinish(ReturnDataType data); 11 | } 12 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/converter/Converter.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.converter; 2 | 3 | import java.lang.reflect.Type; 4 | 5 | /** 6 | * Created by Robin on 2016/5/11 16:03. 7 | */ 8 | public interface Converter { 9 | T fromJSONObject(String json, Type cls); 10 | T fromJSONArray(String json, Type cls); 11 | } 12 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/callback/BytesWriteListener.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.callback; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * Created by Robin on 2016/4/30. 7 | */ 8 | public interface BytesWriteListener{ 9 | public void onWrite(long transferredBytesSize, long totalSize, int currentFileIndex, File currentFile); 10 | } -------------------------------------------------------------------------------- /lib.http.converters/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lib.http.okhttpsupport/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/config/Priority.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.config; 2 | 3 | /** 4 | * Priority values. Requests will be processed from higher priorities to lower priorities, in FIFO order. 5 | * @author Robin 6 | * @since 2015-05-10 00:58:01 7 | */ 8 | public enum Priority { 9 | LOW, 10 | NORMAL, 11 | HIGH, 12 | IMMEDIATE 13 | } -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/cache/Cache.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.cache; 2 | 3 | /** 4 | * Created by Robin on 2016/5/7. 5 | */ 6 | public interface Cache { 7 | void put(String key, V value); 8 | 9 | V get(String key); 10 | 11 | void delete(String key); 12 | 13 | void update(String key, V value); 14 | 15 | void clear(); 16 | } 17 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/ex/Body.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network.ex; 2 | 3 | import net.robinx.lib.http.callback.BytesWriteListener; 4 | 5 | /** 6 | * Created by Robin on 2016/5/4. 7 | */ 8 | public interface Body { 9 | T buildBody(RequestParams params,Object... args); 10 | 11 | void setBytesWriteListener(BytesWriteListener listener); 12 | } 13 | -------------------------------------------------------------------------------- /script/make-jar.gradle: -------------------------------------------------------------------------------- 1 | task clearJar(type: Delete) { 2 | delete 'release/' + POM_ARTIFACT_ID + '_' + VERSION_NAME + '.jar' 3 | } 4 | 5 | task makeJar(type: Copy) { 6 | from('build/intermediates/bundles/release/') 7 | into('release/') 8 | include('classes.jar') 9 | rename('classes.jar', POM_ARTIFACT_ID + '_' + VERSION_NAME + '.jar') 10 | } 11 | makeJar.dependsOn(clearJar, build) -------------------------------------------------------------------------------- /app/src/test/java/com/app/core/http/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.app.core.http; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /lib.http/src/test/java/com/app/core/http/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.app.core.http; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /lib.http.okhttpsupport/src/test/java/com/app/core/okhttp/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.app.core.okhttp; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/app/core/http/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.app.core.http; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /lib.http.converters/src/test/java/com/app/core/http/converters/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.app.core.http.converters; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /lib.http/src/androidTest/java/com/app/core/http/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.app.core.http; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /lib.http.okhttpsupport/src/androidTest/java/com/app/core/okhttp/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.app.core.okhttp; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /lib.http.converters/src/androidTest/java/com/app/core/http/converters/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.app.core.http.converters; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/cache/CacheConfig.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.cache; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * Disk cache configuration 7 | * @author Robin 8 | * @since 2015-12-28 16:18:00 9 | * 10 | */ 11 | public class CacheConfig { 12 | 13 | public static long DEFAULT_MAX_SIZE=10*1024*1024; 14 | 15 | public static long DISK_CACHE_MAX_SIZE; 16 | public static File DISK_CACHE_DIRECTORY; 17 | public static int DISK_CACHE_APP_VERSION; 18 | 19 | public static int MEMORY_CACHE_MAX_SIZE; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/config/HttpMethod.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.config; 2 | 3 | /** 4 | * For the default request body definition request method 5 | * 6 | * @author Robin 7 | * @since 2015-05-13 19:31:46 8 | */ 9 | public class HttpMethod { 10 | private HttpMethod() { 11 | } 12 | 13 | public static final int GET = 0, 14 | POST = 1, 15 | PUT = 2, 16 | DELETE = 3, 17 | HEAD = 4, 18 | OPTIONS = 5, 19 | TRACE = 6, 20 | PATCH = 7; 21 | } -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/HttpError.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network; 2 | 3 | /** 4 | * Request error code 5 | * @author Robin 6 | * @since 2015-12-29 14:52:10 7 | */ 8 | public class HttpError { 9 | private HttpError(){}; 10 | 11 | public static final int ERROR_UNKNOWN = 0x01, 12 | ERROR_NOT_NETWORK = 0x02, 13 | ERROR_SERVER = 0x03, 14 | ERROR_SOCKET_TIMEOUT = 0x04, 15 | ERROR_UNAUTHORIZED = 0x05, 16 | ERROR_REDIRECT = 0x06, 17 | ERROR_RESPONSE_NULL = 0x07, 18 | ERROR_PARSE = 0x08, 19 | ERROR_NO_CONNECTION = 0x09; 20 | } 21 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/base/IResponseDelivery.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.base; 2 | 3 | import java.util.Map; 4 | 5 | import net.robinx.lib.http.config.DataType; 6 | 7 | /** 8 | * Used to cache thread or request thread after the completion of the delivery data 9 | * @author Robin 10 | * @since 2015-05-08 18:04:42 11 | * @param 12 | */ 13 | public interface IResponseDelivery { 14 | /** 15 | * Parses a response from the network or cache and delivers it. 16 | */ 17 | public void deliveryResponse(Request request, Map headers, T result, DataType dataType); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/utils/NetworkUtils.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.utils; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | 7 | /** 8 | * Provide some help about the network function 9 | * @author Robin 10 | * @since 2015/5/28 11:23. 11 | */ 12 | public class NetworkUtils { 13 | 14 | public static boolean checkNet(Context context) { 15 | ConnectivityManager cm = (ConnectivityManager) context 16 | .getSystemService(Context.CONNECTIVITY_SERVICE); 17 | NetworkInfo info = cm.getActiveNetworkInfo(); 18 | return info != null; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/cache/BitmapCache.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.cache; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Used to cache bitmap 7 | * @author Robin 8 | * @since 2016-01-19 15:12:40 9 | * 10 | */ 11 | public class BitmapCache implements Serializable { 12 | private static final long serialVersionUID = 1L; 13 | 14 | private byte[] bitmapBytes = null; 15 | private String name = null; 16 | 17 | public BitmapCache(byte[] bitmapBytes, String name) { 18 | this.bitmapBytes = bitmapBytes; 19 | this.name = name; 20 | } 21 | 22 | public byte[] getBitmapBytes() { 23 | return this.bitmapBytes; 24 | } 25 | 26 | public String getName() { 27 | return this.name; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\Administrator\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /lib.http/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\Administrator\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /lib.http.converters/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\Administrator\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/HttpStack.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network; 2 | 3 | import java.io.IOException; 4 | import java.util.Map; 5 | 6 | import net.robinx.lib.http.base.Request; 7 | 8 | /** 9 | * Http request terminal, known to achieve class: 10 | * @author Robin 11 | * @since 2015-07-02 16:13:43 12 | * 13 | */ 14 | public interface HttpStack { 15 | /** 16 | * Let the Http request for a Request 17 | * 18 | * @param request 19 | * @param additionalHeaders Attached Http request header 20 | * @return A Http response 21 | */ 22 | public HttpResponse performRequest(Request request, 23 | Map additionalHeaders) throws IOException; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /lib.http.okhttpsupport/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\Administrator\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/retry/RetryPolicy.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.retry; 2 | 3 | import net.robinx.lib.http.network.HttpException; 4 | 5 | /** 6 | * Retry policy for a request. 7 | * @author Robin 8 | * @since 2015-08-19 10:00:59 9 | */ 10 | public interface RetryPolicy { 11 | 12 | /** 13 | * Returns the current timeout 14 | */ 15 | public int getCurrentTimeout(); 16 | 17 | /** 18 | * Currently retry count 19 | * @return 20 | */ 21 | public int getCurrentRetryCount(); 22 | 23 | /** 24 | * Prepares for the next retry by applying a backoff to the timeout. 25 | * @param error The error code of the last attempt. 26 | * @throws HttpException In the event that the retry could not be performed 27 | */ 28 | public void retry(HttpException error) throws HttpException; 29 | } 30 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/config/TimeController.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.config; 2 | 3 | /** 4 | * control the expiration time and timeout 5 | * 6 | * @author Robin 7 | * @since 2015-05-07 20:17:47 8 | */ 9 | public class TimeController { 10 | 11 | private long expirationTime; 12 | 13 | private long timeout; 14 | 15 | public long getExpirationTime() { 16 | return expirationTime; 17 | } 18 | 19 | public TimeController setExpirationTime(long expirationTime) { 20 | this.expirationTime = expirationTime; 21 | return this; 22 | } 23 | 24 | public long getTimeout() { 25 | return timeout; 26 | } 27 | 28 | public TimeController setTimeout(long timeout) { 29 | this.timeout = timeout; 30 | return this; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "TimeController [expirationTime=" + expirationTime + ", timeout=" + timeout + "]"; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/app/core/example/App.java: -------------------------------------------------------------------------------- 1 | package com.app.core.example; 2 | 3 | import java.io.File; 4 | 5 | import android.annotation.SuppressLint; 6 | import android.app.Application; 7 | 8 | import net.robinx.lib.http.XRequest; 9 | import net.robinx.lib.http.cache.CacheConfig; 10 | 11 | public class App extends Application { 12 | 13 | @Override 14 | public void onCreate() { 15 | super.onCreate(); 16 | 17 | configXRequestCache(); 18 | 19 | } 20 | 21 | @SuppressLint("SdCardPath") 22 | private void configXRequestCache() { 23 | //磁盘缓存路径 24 | File DISK_CACHE_DIR_PATH = new File("/sdcard/xrequest/diskcache"); 25 | //磁盘缓存最大值 26 | int DISK_CACHE_MAX_SIZE = 30*1024*1024; 27 | 28 | XRequest.initXRequest(getApplicationContext()); 29 | //XRequest.INSTANCE.setStack(new OkHttpStack()); 30 | CacheConfig.DISK_CACHE_MAX_SIZE = DISK_CACHE_MAX_SIZE; 31 | CacheConfig.DISK_CACHE_DIRECTORY = DISK_CACHE_DIR_PATH; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/RequestContext.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http; 2 | 3 | import net.robinx.lib.http.utils.AppUtils; 4 | 5 | import android.content.Context; 6 | import android.content.ContextWrapper; 7 | 8 | /** 9 | * Request context 10 | * 11 | * @author Robin 12 | * @since 2015-12-31 10:59:05 13 | * 14 | */ 15 | public class RequestContext extends ContextWrapper { 16 | 17 | private static RequestContext sContext; 18 | 19 | public RequestContext(Context base) { 20 | super(base); 21 | } 22 | 23 | public static void init(Context context) { 24 | String processName = AppUtils.getCurProcessName(context); 25 | String mainProcessName = context.getPackageName(); 26 | 27 | if (!mainProcessName.equals(processName)) { 28 | return; 29 | } 30 | if (sContext == null) { 31 | sContext = new RequestContext(context); 32 | } 33 | } 34 | 35 | public static RequestContext getInstance() { 36 | return sContext; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/aidl/com/app/core/example/ILogProcessor.aidl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 Michael Novak 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | package com.app.core.example; 19 | 20 | interface ILogProcessor { 21 | 22 | void reset(String buffer); 23 | void run(int type); 24 | void restart(int type); 25 | void stop(); 26 | void write(String file, String tag); 27 | } 28 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/cache/Entry.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.cache; 2 | 3 | import java.io.Serializable; 4 | import java.util.Collections; 5 | import java.util.Map; 6 | 7 | /** 8 | * The cached data entity, including the request header and the request content 9 | * @author Robin 10 | * @since 2015-06-24 11:21:41 11 | */ 12 | @SuppressWarnings("serial") 13 | public class Entry implements Serializable{ 14 | 15 | /** Request's content for cache*/ 16 | public T result; 17 | /** Request's headers for cache */ 18 | public Map responseHeaders = Collections.emptyMap(); 19 | 20 | public Entry(T result, Map responseHeaders) { 21 | super(); 22 | this.result = result; 23 | this.responseHeaders = responseHeaders; 24 | } 25 | 26 | public T getResult() { 27 | return result; 28 | } 29 | 30 | public void setResult(T result) { 31 | this.result = result; 32 | } 33 | 34 | public Map getResponseHeaders() { 35 | return responseHeaders; 36 | } 37 | 38 | public void setResponseHeaders(Map responseHeaders) { 39 | this.responseHeaders = responseHeaders; 40 | } 41 | 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /lib.http.converters/src/main/java/net/robinx/lib/http/converters/FastjsonConverter.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.converters; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.TypeReference; 5 | import net.robinx.lib.http.converter.Converter; 6 | import net.robinx.lib.http.utils.CLog; 7 | 8 | import java.lang.reflect.Type; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by Robin on 2016/5/11 19:55. 14 | */ 15 | public class FastjsonConverter implements Converter { 16 | 17 | 18 | public FastjsonConverter() { 19 | CLog.w("Create Fastjson"); 20 | } 21 | 22 | @Override 23 | public T fromJSONObject(String json, Type cls) { 24 | CLog.w("From JSON Object"); 25 | return fromObject(json, cls); 26 | } 27 | 28 | @Override 29 | public T fromJSONArray(String json, Type cls) { 30 | CLog.w("From JSON Array"); 31 | return (T) fromList(json, cls); 32 | } 33 | 34 | public T fromObject(String json, Type cls) { 35 | T bean = JSON.parseObject(json,cls); 36 | return bean; 37 | } 38 | 39 | public ArrayList fromList(String json, Type cls) { 40 | ArrayList list= (ArrayList) JSON.parseObject(json, new TypeReference>(){}); 41 | return list; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/res/layout/log_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 26 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/response/NetworkResponse.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.response; 2 | 3 | import java.util.Collections; 4 | import java.util.Map; 5 | 6 | import net.robinx.lib.http.network.HttpStatus; 7 | 8 | /** 9 | * The Http response returned from the NetWork, 10 | * contains the response that is successful or failed, the request header, the response content, the HTTP status code 11 | * @author Robin 12 | * @since 2015-07-02 15:05:31 13 | */ 14 | public class NetworkResponse { 15 | 16 | public NetworkResponse(int statusCode, byte[] data, 17 | Map headers, boolean notModified) { 18 | this.statusCode = statusCode; 19 | this.data = data; 20 | this.headers = headers; 21 | this.notModified = notModified; 22 | } 23 | 24 | public NetworkResponse(byte[] data) { 25 | this(HttpStatus.SC_OK, data, Collections. emptyMap(), 26 | false); 27 | } 28 | 29 | public NetworkResponse(byte[] data, Map headers) { 30 | this(HttpStatus.SC_OK, data, headers, false); 31 | } 32 | 33 | public final int statusCode; 34 | 35 | public final byte[] data; 36 | 37 | public final Map headers; 38 | 39 | public final boolean notModified; // If the server returns 304 ( Not Modified ), the true 40 | } -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/converter/GsonConverter.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.converter; 2 | 3 | import net.robinx.lib.http.utils.CLog; 4 | import com.google.gson.Gson; 5 | 6 | import java.lang.reflect.Type; 7 | import java.util.ArrayList; 8 | 9 | /** 10 | * Created by Robin on 2016/5/11 16:07. 11 | */ 12 | public class GsonConverter implements Converter { 13 | 14 | private Gson gson; 15 | 16 | public GsonConverter() { 17 | if (gson == null) { 18 | gson = new Gson(); 19 | CLog.w("Create GSON"); 20 | } 21 | } 22 | 23 | public T fromJSONObject(String json, Type cls) { 24 | CLog.w("From JSON Object"); 25 | return fromObject(json, cls); 26 | } 27 | 28 | @Override 29 | public T fromJSONArray(String json, Type cls) { 30 | CLog.w("From JSON Array"); 31 | return (T) fromList(json, cls); 32 | } 33 | 34 | public X fromObject(String json, Type cls) { 35 | X bean = gson.fromJson(json, cls); 36 | return bean; 37 | } 38 | 39 | public ArrayList fromList(String json, Type cls) { 40 | ArrayList list; 41 | try { 42 | list = gson.fromJson(json, cls); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | return null; 46 | } 47 | return list; 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/response/Response.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.response; 2 | 3 | import java.util.Map; 4 | 5 | import net.robinx.lib.http.network.HttpException; 6 | 7 | /** 8 | * Http request response package type, containing the request header, request 9 | * content, error content of the request response 10 | * 11 | * @author Robin 12 | * @since 2015-07-02 15:07:13 13 | */ 14 | public class Response { 15 | /** 16 | * Http type of response 17 | */ 18 | public final T result; 19 | 20 | public final HttpException error; 21 | 22 | public final Map headers; 23 | 24 | public boolean isSuccess() { 25 | return error == null; 26 | } 27 | 28 | private Response(T result, Map headers) { 29 | this.result = result; 30 | this.headers = headers; 31 | this.error = null; 32 | } 33 | 34 | private Response(HttpException error) { 35 | this.result = null; 36 | this.headers = null; 37 | this.error = error; 38 | } 39 | 40 | /** 41 | * To return a successful HttpRespond 42 | * 43 | * @param result 44 | * Http type of response 45 | * @param headers 46 | * Request header information 47 | */ 48 | public static Response success(T result, Map headers) { 49 | return new Response(result, headers); 50 | } 51 | 52 | /** 53 | * To return a failed HttpRespond 54 | * 55 | * @param error 56 | */ 57 | public static Response error(HttpException error) { 58 | return new Response(error); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.app.core.http" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | 21 | lintOptions { 22 | abortOnError false 23 | } 24 | 25 | //解决jackson运行报错问题 26 | packagingOptions { 27 | exclude 'META-INF/LICENSE' 28 | exclude 'META-INF/NOTICE' 29 | } 30 | 31 | //------------aidl start--------------------------------- 32 | sourceSets { 33 | main { 34 | manifest.srcFile 'src/main/AndroidManifest.xml' 35 | java.srcDirs = ['src/main/java', 'src/main/aidl'] 36 | resources.srcDirs = ['src/main/java', 'src/main/aidl'] 37 | aidl.srcDirs = ['src/main/aidl'] 38 | res.srcDirs = ['src/main/res'] 39 | assets.srcDirs = ['src/main/assets'] 40 | } 41 | } 42 | //------------aidl end--------------------------------- 43 | } 44 | 45 | dependencies { 46 | compile fileTree(dir: 'libs', include: ['*.jar']) 47 | testCompile 'junit:junit:4.12' 48 | compile project(':lib.http') 49 | compile project(':lib.http.okhttpsupport') 50 | compile project(':lib.http.converters') 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/app/core/example/bean/BeautyBean.java: -------------------------------------------------------------------------------- 1 | package com.app.core.example.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by Robin on 2016/5/12 10:08. 7 | */ 8 | public class BeautyBean implements Serializable{ 9 | 10 | 11 | /** 12 | * title : 台大女神各种校花自拍照片合集 13 | * description : 台大女神各种校花自拍照片合集 14 | * picUrl : http://img9.tu11.com:8080/uploads/allimg/150418/1_041Q024134405.jpg 15 | * url : http://www.yixiuba.com/shenghuomeinvzipai/2015/6371.html 16 | */ 17 | private String title; 18 | private String description; 19 | private String picUrl; 20 | private String url; 21 | 22 | public BeautyBean() { 23 | super(); 24 | } 25 | 26 | public String getTitle() { 27 | return title; 28 | } 29 | 30 | public void setTitle(String title) { 31 | this.title = title; 32 | } 33 | 34 | public String getDescription() { 35 | return description; 36 | } 37 | 38 | public void setDescription(String description) { 39 | this.description = description; 40 | } 41 | 42 | public String getPicUrl() { 43 | return picUrl; 44 | } 45 | 46 | public void setPicUrl(String picUrl) { 47 | this.picUrl = picUrl; 48 | } 49 | 50 | public String getUrl() { 51 | return url; 52 | } 53 | 54 | public void setUrl(String url) { 55 | this.url = url; 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | return "BeautyBean{" + 61 | "title='" + title + '\'' + 62 | ", description='" + description + '\'' + 63 | ", picUrl='" + picUrl + '\'' + 64 | ", url='" + url + '\'' + 65 | '}'; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/cache/memory/MemoryCache.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.cache.memory; 2 | 3 | import net.robinx.lib.http.cache.Cache; 4 | import net.robinx.lib.http.cache.CacheConfig; 5 | import net.robinx.lib.http.cache.CacheData; 6 | import net.robinx.lib.http.cache.Entry; 7 | 8 | /** 9 | * Created by Robin on 2016/5/7. 10 | */ 11 | public enum MemoryCache implements Cache>{ 12 | 13 | INSTANCE; 14 | 15 | private LruCache> mMemoryCache; 16 | 17 | private MemoryCache(){ 18 | if (mMemoryCache==null) { 19 | if (CacheConfig.MEMORY_CACHE_MAX_SIZE <= 0) { 20 | throw new RuntimeException("Maybe you forgot to initialize,like \"XRequest.init(context)\""); 21 | } 22 | mMemoryCache=new LruCache>(CacheConfig.MEMORY_CACHE_MAX_SIZE){ 23 | @Override 24 | protected int sizeOf(String key, CacheData value) { 25 | return super.sizeOf(key, value); 26 | } 27 | }; 28 | } 29 | } 30 | 31 | 32 | @Override 33 | public void put(String key, CacheData value) { 34 | if (get(key)==null) { 35 | mMemoryCache.put(key, value); 36 | } 37 | } 38 | 39 | @Override 40 | public CacheData get(String key) { 41 | return mMemoryCache.get(key); 42 | } 43 | 44 | @Override 45 | public void delete(String key) { 46 | mMemoryCache.remove(key); 47 | } 48 | 49 | @Override 50 | public void update(String key, CacheData value) { 51 | mMemoryCache.put(key, value); 52 | } 53 | 54 | @Override 55 | public void clear() { 56 | mMemoryCache.evictAll(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/callback/OnRequestListenerAdapter.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.callback; 2 | 3 | import java.io.File; 4 | import java.util.Map; 5 | 6 | import net.robinx.lib.http.base.Request; 7 | import net.robinx.lib.http.config.DataType; 8 | import net.robinx.lib.http.network.HttpException; 9 | import net.robinx.lib.http.response.NetworkResponse; 10 | 11 | /** 12 | * implements "OnRequestListener" interface, if you need to rewrite a callback function, can realize this 13 | * @author Robin 14 | * @since 2015/5/27 18:55. 15 | */ 16 | public abstract class OnRequestListenerAdapter implements OnRequestListener { 17 | 18 | @Override 19 | public void onRequestPrepare(Request request) { 20 | } 21 | 22 | @Override 23 | public void onRequestFailed(Request request, HttpException httpException) { 24 | } 25 | 26 | @Override 27 | public void onRequestRetry(Request request, int currentRetryCount, HttpException previousError) { 28 | } 29 | 30 | @Override 31 | public void onRequestDownloadProgress(Request request, long transferredBytesSize, long totalSize) { 32 | } 33 | 34 | @Override 35 | public void onRequestUploadProgress(Request request, long transferredBytesSize, long totalSize, int currentFileIndex,File currentFile) { 36 | } 37 | 38 | @Override 39 | public void onRequestFinish(Request request, Map headers, T result) { 40 | } 41 | 42 | @Override 43 | public void onCacheDataLoadFinish(Request request, Map headers, T result) { 44 | } 45 | 46 | @Override 47 | public boolean onParseNetworkResponse(Request request, NetworkResponse networkResponse, T result) { 48 | return true; 49 | } 50 | 51 | @Override 52 | public void onDone(Request request, Map headers, T result, DataType dataType) { 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/base/IRequest.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.base; 2 | 3 | import java.io.File; 4 | import java.util.Map; 5 | 6 | import net.robinx.lib.http.cache.CacheData; 7 | import net.robinx.lib.http.cache.Entry; 8 | import net.robinx.lib.http.network.HttpException; 9 | import net.robinx.lib.http.response.NetworkResponse; 10 | 11 | /** 12 | * {@link net.robinx.lib.http.base.Request} 13 | * @author Robin 14 | * @since 2015-05-07 14:06:41 15 | */ 16 | public interface IRequest{ 17 | 18 | /** Do something before the request */ 19 | public void requestPrepare(); 20 | 21 | /** When request finished */ 22 | public void onRequestFinish(Map headers, T data); 23 | 24 | /** When request failed */ 25 | public void onRequestFailed(HttpException httpException); 26 | 27 | /** When request retry */ 28 | public void onRequestRetry(int currentRetryCount, HttpException previousError); 29 | 30 | /** Call this method to delivered current progress for request */ 31 | public void onRequestDownloadProgress(long transferredBytesSize, long totalSize); 32 | 33 | /** Call this method to delivered upload progress for request */ 34 | public void onRequestUploadProgress(long transferredBytesSize, long totalSize, int currentFileIndex, File currentFile); 35 | 36 | /** When cache data load finished */ 37 | public void onCacheDataLoadFinish(CacheData> cacheData); 38 | 39 | /** Get the current request's cache data */ 40 | public CacheData> getCache(String key); 41 | 42 | /** Parse the network response to an object */ 43 | public void onParseNetworkResponse(NetworkResponse networkResponse, T result); 44 | 45 | /** Manual call this method when the request finished , to release the same request in the "mWaitingRequests" map */ 46 | public void finish() ; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/aidl/com/app/core/example/LogFormattedString.java: -------------------------------------------------------------------------------- 1 | package com.app.core.example; 2 | 3 | import java.util.HashMap; 4 | 5 | import android.graphics.Typeface; 6 | import android.text.SpannableString; 7 | import android.text.style.ForegroundColorSpan; 8 | import android.text.style.StyleSpan; 9 | 10 | public class LogFormattedString extends SpannableString { 11 | public static final HashMap LABEL_COLOR_MAP; 12 | 13 | public LogFormattedString(String line) { 14 | super(line); 15 | 16 | try { 17 | if (line.length() < 4) { 18 | throw new RuntimeException(); 19 | } 20 | 21 | if (line.charAt(1) != '/') { 22 | throw new RuntimeException(); 23 | } 24 | 25 | Integer labelColor = LABEL_COLOR_MAP.get(line.charAt(0)); 26 | 27 | if (labelColor == null) { 28 | labelColor = LABEL_COLOR_MAP.get('E'); 29 | } 30 | 31 | setSpan(new ForegroundColorSpan(labelColor), 0, 1, 0); 32 | setSpan(new StyleSpan(Typeface.BOLD), 0, 1, 0); 33 | 34 | int leftIdx; 35 | 36 | if ((leftIdx = line.indexOf(':', 2)) >= 0) { 37 | setSpan(new ForegroundColorSpan(labelColor), 2, leftIdx, 0); 38 | setSpan(new StyleSpan(Typeface.ITALIC), 2, leftIdx, 0); 39 | } 40 | } catch (Exception e) { 41 | setSpan(new ForegroundColorSpan(0xffddaacc), 0, length(), 0); 42 | } 43 | } 44 | 45 | static { 46 | LABEL_COLOR_MAP = new HashMap(); 47 | LABEL_COLOR_MAP.put('D', 0xff9999ff); 48 | LABEL_COLOR_MAP.put('V', 0xffcccccc); 49 | LABEL_COLOR_MAP.put('I', 0xffeeeeee); 50 | LABEL_COLOR_MAP.put('E', 0xffff9999); 51 | LABEL_COLOR_MAP.put('W', 0xffffff99); 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/app/core/example/bean/CityRootBean.java: -------------------------------------------------------------------------------- 1 | package com.app.core.example.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 测试用 城市实体类 7 | * @author Robin 8 | * @since 2015-11-11 14:26:36 9 | * 10 | */ 11 | public class CityRootBean implements Serializable{ 12 | private static final long serialVersionUID = 1L; 13 | 14 | private String errNum; 15 | private String retMsg; 16 | private T retData; 17 | 18 | public CityRootBean() { 19 | super(); 20 | } 21 | 22 | public CityRootBean(String errNum, T retData, String retMsg) { 23 | this.errNum = errNum; 24 | this.retData = retData; 25 | this.retMsg = retMsg; 26 | } 27 | 28 | public static class CityBean implements Serializable{ 29 | private static final long serialVersionUID = 1L; 30 | private String citylist; 31 | 32 | public CityBean() { 33 | super(); 34 | } 35 | 36 | public CityBean(String citylist) { 37 | this.citylist = citylist; 38 | } 39 | 40 | public String getCitylist() { 41 | return citylist; 42 | } 43 | 44 | public void setCitylist(String citylist) { 45 | this.citylist = citylist; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | return "CityBean [citylist=" + citylist + "]"; 51 | } 52 | 53 | } 54 | 55 | public String getErrNum() { 56 | return errNum; 57 | } 58 | 59 | public void setErrNum(String errNum) { 60 | this.errNum = errNum; 61 | } 62 | 63 | public String getRetMsg() { 64 | return retMsg; 65 | } 66 | 67 | public void setRetMsg(String retMsg) { 68 | this.retMsg = retMsg; 69 | } 70 | 71 | public T getRetData() { 72 | return retData; 73 | } 74 | 75 | public void setRetData(T retData) { 76 | this.retData = retData; 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | return "CityRootBean [errNum=" + errNum + ", retMsg=" + retMsg + ", retData=" + retData + "]"; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/callback/OnRequestListener.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.callback; 2 | 3 | import java.io.File; 4 | import java.util.Map; 5 | 6 | import net.robinx.lib.http.base.Request; 7 | import net.robinx.lib.http.config.DataType; 8 | import net.robinx.lib.http.network.HttpException; 9 | import net.robinx.lib.http.response.NetworkResponse; 10 | 11 | /** 12 | * when data processed finish 13 | * 14 | * @author Robin 15 | * @since 2015-05-07 21:27:07 16 | */ 17 | public interface OnRequestListener { 18 | 19 | /** The preparation for the request */ 20 | public void onRequestPrepare(Request request); 21 | 22 | /** Call this method when request failed */ 23 | public void onRequestFailed(Request request, HttpException httpException); 24 | 25 | /** Call this method when request retry */ 26 | public void onRequestRetry(Request request, int currentRetryCount, HttpException previousError); 27 | 28 | /** Call this method to delivered current progress for request */ 29 | public void onRequestDownloadProgress(Request request, long transferredBytesSize, long totalSize); 30 | 31 | /** Call this method to delivered upload progress for request */ 32 | public void onRequestUploadProgress(Request request, long transferredBytesSize, long totalSize, int currentFileIndex, File currentFile); 33 | 34 | /** Call this method when request finished */ 35 | public void onRequestFinish(Request request, Map headers, T result); 36 | 37 | /** Call this method when cache data load finished */ 38 | public void onCacheDataLoadFinish(Request request, Map headers, T result); 39 | 40 | /** Parse the network response to an object */ 41 | public boolean onParseNetworkResponse(Request request, NetworkResponse networkResponse, T result); 42 | 43 | /** 44 | * When the request is completed or the cache data loaded ,call this method 45 | * , called only once, the final data delivery function 46 | */ 47 | public void onDone(Request request, Map headers, T result, DataType dataType); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /lib.http.converters/src/main/java/net/robinx/lib/http/converters/JackSonConverter.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.converters; 2 | 3 | import net.robinx.lib.http.converter.Converter; 4 | import net.robinx.lib.http.utils.CLog; 5 | import com.fasterxml.jackson.core.type.TypeReference; 6 | import com.fasterxml.jackson.databind.JavaType; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | 9 | import java.io.IOException; 10 | import java.lang.reflect.Type; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * Created by Robin on 2016/5/11 19:55. 16 | */ 17 | public class JackSonConverter implements Converter { 18 | 19 | private ObjectMapper mapper; 20 | 21 | public JackSonConverter() { 22 | if (mapper == null) { 23 | mapper = new ObjectMapper(); 24 | CLog.w("Create JackSon"); 25 | } 26 | } 27 | 28 | @Override 29 | public T fromJSONObject(String json, Type cls) { 30 | CLog.w("From JSON Object"); 31 | return fromObject(json, cls); 32 | } 33 | 34 | @Override 35 | public T fromJSONArray(String json, Type cls) { 36 | CLog.w("From JSON Array"); 37 | return (T) fromList(json, cls); 38 | } 39 | 40 | public T fromObject(String json, Type cls) { 41 | try { 42 | JavaType javaType = mapper.getTypeFactory().constructType(cls); 43 | T bean = mapper.readValue(json, javaType); 44 | return bean; 45 | } catch (IOException e) { 46 | e.printStackTrace(); 47 | CLog.e("JackSonConverter:%s", e.getMessage()); 48 | return null; 49 | } 50 | 51 | } 52 | 53 | public ArrayList fromList(String json, Type cls) { 54 | try { 55 | ArrayList list = mapper.readValue(json, new TypeReference>() { 56 | }); 57 | return list; 58 | } catch (IOException e) { 59 | e.printStackTrace(); 60 | CLog.e("JackSonConverter:%s", e.getMessage()); 61 | return null; 62 | } 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/ex/HttpRequest.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network.ex; 2 | 3 | import net.robinx.lib.http.XRequest; 4 | import net.robinx.lib.http.base.Request; 5 | import net.robinx.lib.http.callback.BytesWriteListener; 6 | import net.robinx.lib.http.network.ex.hurl.HurlRequestBody; 7 | 8 | import java.io.File; 9 | import java.util.Map; 10 | 11 | /** 12 | * Created by Robin on 2016/4/30. 13 | */ 14 | public abstract class HttpRequest extends Request { 15 | protected RequestParams mRequestParams = new RequestParams(); 16 | 17 | protected Body mBody; 18 | 19 | public HttpRequest() { 20 | super(); 21 | 22 | mBody = new HurlRequestBody(); 23 | mBody.setBytesWriteListener(getBytesWriteListener()); 24 | } 25 | 26 | protected BytesWriteListener getBytesWriteListener() { 27 | return new BytesWriteListener() { 28 | @Override 29 | public void onWrite(long transferredBytesSize, long totalSize, int currentFileIndex, File currentFile) { 30 | //super.getRequestQueue().getDelivery().postRequestUploadProgress(this, transferredBytesSize,totalSize); //UI Thread 31 | onRequestUploadProgress(transferredBytesSize, totalSize, currentFileIndex, currentFile); //Thread 32 | } 33 | }; 34 | } 35 | 36 | @Override 37 | public Map getHeaders() { 38 | return mRequestParams.buildHeaders(); 39 | } 40 | 41 | @Override 42 | public String getParams() { 43 | return mRequestParams.toString(); 44 | } 45 | 46 | @Override 47 | public R buildBody(Object... args) { 48 | return mBody.buildBody(mRequestParams, args); 49 | } 50 | 51 | public void setRequestParams(RequestParams requestParams) { 52 | this.mRequestParams = requestParams; 53 | } 54 | 55 | public RequestParams getRequestParams() { 56 | return mRequestParams; 57 | } 58 | 59 | public HttpRequest execute(){ 60 | XRequest.INSTANCE.addToRequestQueue(this); 61 | return this; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/utils/AppUtils.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.utils; 2 | 3 | import java.io.File; 4 | 5 | import android.app.ActivityManager; 6 | import android.content.Context; 7 | import android.content.pm.PackageInfo; 8 | import android.content.pm.PackageManager.NameNotFoundException; 9 | import android.os.Environment; 10 | import android.os.Process;; 11 | /** 12 | * APP helper 13 | * 14 | * @author Robin 15 | * @since 2015-12-31 10:03:05 16 | * 17 | */ 18 | public class AppUtils { 19 | 20 | public static int getAppVersion(Context context) { 21 | try { 22 | PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); 23 | return info.versionCode; 24 | } catch (NameNotFoundException e) { 25 | e.printStackTrace(); 26 | } 27 | return 1; 28 | } 29 | /** 30 | * According to the incoming a unique name for the path of the hard disk cache address. 31 | */ 32 | public static File getDiskCacheDir(Context context, String uniqueName) { 33 | String cachePath; 34 | if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) 35 | || !Environment.isExternalStorageRemovable()) { 36 | File cacheDir=context.getExternalCacheDir(); 37 | if (cacheDir!=null) { 38 | cachePath = cacheDir .getPath(); // /sdcard/Android/data//cache 39 | }else { 40 | cachePath = context.getCacheDir().getPath(); // /data/data//cache 41 | } 42 | 43 | } else { 44 | cachePath = context.getCacheDir().getPath(); // /data/data//cache 45 | } 46 | return new File(cachePath + File.separator + uniqueName); 47 | } 48 | 49 | public static String getCurProcessName(Context context) { 50 | int pid = Process.myPid(); 51 | ActivityManager mActivityManager = (ActivityManager) context.getSystemService("activity"); 52 | 53 | for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager.getRunningAppProcesses()) { 54 | if (appProcess.pid == pid) { 55 | return appProcess.processName; 56 | } 57 | } 58 | return null; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/HttpResponse.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network; 2 | 3 | import java.io.InputStream; 4 | import java.io.Serializable; 5 | import java.util.Map; 6 | 7 | /** 8 | * Compatible with 6.0, is used to replace "org.apache.http.HttpResponse" 9 | * @author Robin 10 | * @since 2016-1-14 18:55:51 11 | * 12 | */ 13 | public class HttpResponse implements Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | private Map headers; 18 | 19 | private int responseCode; 20 | 21 | private String responseMessage; 22 | 23 | private InputStream contentStream; 24 | 25 | private String contentEncoding; 26 | 27 | private String contentType; 28 | 29 | private long contentLength; 30 | 31 | public Map getHeaders() { 32 | return headers; 33 | } 34 | 35 | public void setHeaders(Map headers) { 36 | this.headers = headers; 37 | } 38 | 39 | public int getResponseCode() { 40 | return responseCode; 41 | } 42 | 43 | public void setResponseCode(int responseCode) { 44 | this.responseCode = responseCode; 45 | } 46 | 47 | public String getResponseMessage() { 48 | return responseMessage; 49 | } 50 | 51 | public void setResponseMessage(String responseMessage) { 52 | this.responseMessage = responseMessage; 53 | } 54 | 55 | public InputStream getContentStream() { 56 | return contentStream; 57 | } 58 | 59 | public void setContentStream(InputStream contentStream) { 60 | this.contentStream = contentStream; 61 | } 62 | 63 | public String getContentEncoding() { 64 | return contentEncoding; 65 | } 66 | 67 | public void setContentEncoding(String contentEncoding) { 68 | this.contentEncoding = contentEncoding; 69 | } 70 | 71 | public String getContentType() { 72 | return contentType; 73 | } 74 | 75 | public void setContentType(String contentType) { 76 | this.contentType = contentType; 77 | } 78 | 79 | public long getContentLength() { 80 | return contentLength; 81 | } 82 | 83 | public void setContentLength(long contentLength) { 84 | this.contentLength = contentLength; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/delivered/IDelivery.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.delivered; 2 | 3 | import java.io.File; 4 | 5 | import net.robinx.lib.http.base.Request; 6 | import net.robinx.lib.http.network.HttpException; 7 | import net.robinx.lib.http.response.Response; 8 | 9 | /** 10 | * The distributor, the result of the asynchronous thread to the UI thread 11 | * 12 | * @author Robin 13 | * @since 2015-07-02 14:49:51 14 | * 15 | */ 16 | public interface IDelivery { 17 | /** 18 | * Distribution request response result 19 | * 20 | * @param request 21 | * @param response 22 | */ 23 | public void postRequestResponse(Request request, Response response); 24 | 25 | /** 26 | * Distribute Failure events 27 | * 28 | * @param request 29 | * @param error 30 | */ 31 | public void postError(Request request, HttpException error); 32 | 33 | /** 34 | * Distribution to read the cached results response 35 | * @param request 36 | * @param cacheData 37 | */ 38 | public void postCacheResponse(Request request, T cacheData); 39 | 40 | /** 41 | * Prepare events at the start of the request 42 | * @param request 43 | */ 44 | public void postRequestPrepare(Request request); 45 | 46 | /** 47 | * Distribution to retry event 48 | * @param request 49 | * @param previousError An exception before 50 | */ 51 | public void postRequestRetry(Request request, int currentRetryCount, HttpException previousError); 52 | 53 | /** 54 | * Delivered current progress for request 55 | * @param request 56 | * @param transferredBytesSize 57 | * @param totalSize 58 | */ 59 | public void postRequestDownloadProgress(Request request, long transferredBytesSize, long totalSize); 60 | 61 | /** 62 | * Delivered upload progress for request 63 | * @param request 64 | * @param transferredBytesSize 65 | * @param totalSize 66 | * @param currentFileIndex The subscript is currently being uploaded file 67 | * @param currentFile Is currently being uploaded files 68 | */ 69 | public void postRequestUploadProgress(Request request, long transferredBytesSize, long totalSize, int currentFileIndex, File currentFile); 70 | 71 | } 72 | -------------------------------------------------------------------------------- /lib.http.okhttpsupport/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion ANDROID_BUILD_SDK_VERSION as int 5 | buildToolsVersion ANDROID_BUILD_TOOLS_VERSION 6 | 7 | defaultConfig { 8 | minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION as int 9 | targetSdkVersion ANDROID_BUILD_TARGET_SDK_VERSION as int 10 | versionCode VERSION_CODE as int 11 | versionName VERSION_NAME 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | 20 | lintOptions { 21 | abortOnError false 22 | } 23 | } 24 | 25 | dependencies { 26 | compile fileTree(dir: 'libs', include: ['*.jar']) 27 | testCompile 'junit:junit:4.12' 28 | compile project(':lib.http') 29 | compile 'com.squareup.okhttp3:okhttp:3.2.0' 30 | } 31 | 32 | //apply from: '../script/gradle-jcenter-push.gradle' 33 | 34 | /*//-----------------javadoc编码------------------------ 35 | allprojects { 36 | tasks.withType(Javadoc) { 37 | options{ 38 | encoding "UTF-8" 39 | charSet 'UTF-8' 40 | links "http://docs.oracle.com/javase/7/docs/api" 41 | } 42 | } 43 | } 44 | //-----------------jCenter 配置 begin------------------------ 45 | ext { 46 | bintrayRepo = 'RobinMaven' 47 | bintrayName = 'HttpOkHttpSupportLibrary' 48 | 49 | publishedGroupId = 'net.robinx' 50 | libraryName = 'lib.http.okhttpsupport' 51 | artifact = 'lib.http.okhttpsupport' 52 | 53 | libraryDescription = 'Android okhttp support library' 54 | 55 | siteUrl = 'http://git.oschina.net/robinxdroid/HttpRequest' 56 | gitUrl = 'https://git.oschina.net/robinxdroid/HttpRequest.git' 57 | 58 | libraryVersion = '1.0.0' 59 | 60 | developerId = 'robinx' 61 | developerName = 'robin' 62 | developerEmail = 'robinxdroid@gmail.com' 63 | 64 | licenseName = 'The Apache Software License, Version 2.0' 65 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' 66 | allLicenses = ["Apache-2.0"] 67 | 68 | } 69 | 70 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' 71 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle'*/ 72 | -------------------------------------------------------------------------------- /lib.http.okhttpsupport/src/main/java/net/robinx/lib/http/okhttp/RequestBodyProxy.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.okhttp; 2 | 3 | import net.robinx.lib.http.callback.BytesWriteListener; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | 8 | import okhttp3.MediaType; 9 | import okhttp3.RequestBody; 10 | import okio.Buffer; 11 | import okio.BufferedSink; 12 | import okio.ForwardingSink; 13 | import okio.Okio; 14 | import okio.Sink; 15 | 16 | /** 17 | * Created by Robin on 2016/4/26. 18 | */ 19 | public class RequestBodyProxy extends RequestBody { 20 | 21 | private BytesWriteListener mBytesWriteListener; 22 | 23 | private RequestBody mRequestBody; 24 | 25 | private BufferedSink mBufferedSink; 26 | 27 | private int mCurrentFileIndex; 28 | 29 | private File mCurrentFile; 30 | 31 | public RequestBodyProxy(RequestBody requestBody, int currentFileIndex, File currentFile, BytesWriteListener listener) { 32 | super(); 33 | this.mRequestBody = requestBody; 34 | this.mCurrentFileIndex = currentFileIndex; 35 | this.mCurrentFile = currentFile; 36 | this.mBytesWriteListener = listener; 37 | } 38 | 39 | @Override 40 | public long contentLength() throws IOException { 41 | return mRequestBody.contentLength(); 42 | } 43 | 44 | @Override 45 | public MediaType contentType() { 46 | return mRequestBody.contentType(); 47 | } 48 | 49 | @Override 50 | public void writeTo(BufferedSink sink) throws IOException { 51 | if (mBufferedSink == null) { 52 | mBufferedSink = Okio.buffer(sink(sink)); 53 | } 54 | mRequestBody.writeTo(mBufferedSink); 55 | mBufferedSink.flush(); 56 | } 57 | 58 | private Sink sink(Sink sink) { 59 | return new ForwardingSink(sink) { 60 | long bytesWritten = 0L; 61 | long contentLength = 0L; 62 | 63 | @Override 64 | public void write(Buffer source, long byteCount) throws IOException { 65 | super.write(source, byteCount); 66 | if (contentLength == 0) { 67 | contentLength = contentLength(); 68 | } 69 | bytesWritten += byteCount; 70 | mBytesWriteListener.onWrite(bytesWritten,contentLength,mCurrentFileIndex,mCurrentFile); 71 | } 72 | }; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /lib.http/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion ANDROID_BUILD_SDK_VERSION as int 5 | buildToolsVersion ANDROID_BUILD_TOOLS_VERSION 6 | 7 | defaultConfig { 8 | minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION as int 9 | targetSdkVersion ANDROID_BUILD_TARGET_SDK_VERSION as int 10 | versionCode VERSION_CODE as int 11 | versionName VERSION_NAME 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | 20 | lintOptions { 21 | abortOnError false 22 | } 23 | } 24 | 25 | dependencies { 26 | compile fileTree(dir: 'libs', include: ['*.jar']) 27 | testCompile 'junit:junit:4.12' 28 | compile 'com.google.code.gson:gson:2.6.2' 29 | } 30 | 31 | apply from: '../script/gradle-jcenter-push.gradle' 32 | 33 | /*//-----------------javadoc编码------------------------ 34 | allprojects { 35 | tasks.withType(Javadoc) { 36 | options{ 37 | encoding "UTF-8" 38 | charSet 'UTF-8' 39 | links "http://docs.oracle.com/javase/7/docs/api" 40 | } 41 | } 42 | } 43 | //-----------------Javadoc generation failed------------------------ 44 | allprojects { 45 | tasks.withType(Javadoc) { 46 | options.addStringOption('Xdoclint:none', '-quiet') 47 | options.addStringOption('encoding', 'UTF-8') 48 | } 49 | } 50 | //-----------------jCenter 配置 begin------------------------ 51 | ext { 52 | bintrayRepo = 'RobinMaven' 53 | bintrayName = 'HttpLibrary' 54 | 55 | publishedGroupId = 'net.robinx' 56 | libraryName = 'lib.http' 57 | artifact = 'lib.http' 58 | 59 | libraryDescription = 'Android http library' 60 | 61 | siteUrl = 'http://git.oschina.net/robinxdroid/HttpRequest' 62 | gitUrl = 'https://git.oschina.net/robinxdroid/HttpRequest.git' 63 | 64 | libraryVersion = '1.0.1' 65 | 66 | developerId = 'robinx' 67 | developerName = 'robin' 68 | developerEmail = 'robinxdroid@gmail.com' 69 | 70 | licenseName = 'The Apache Software License, Version 2.0' 71 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' 72 | allLicenses = ["Apache-2.0"] 73 | 74 | } 75 | 76 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' 77 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle'*/ 78 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/cache/disk/Util.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.robinx.lib.http.cache.disk; 18 | 19 | import java.io.Closeable; 20 | import java.io.File; 21 | import java.io.IOException; 22 | import java.io.Reader; 23 | import java.io.StringWriter; 24 | import java.nio.charset.Charset; 25 | 26 | /** Junk drawer of utility methods. */ 27 | final class Util { 28 | static final Charset US_ASCII = Charset.forName("US-ASCII"); 29 | static final Charset UTF_8 = Charset.forName("UTF-8"); 30 | 31 | private Util() { 32 | } 33 | 34 | static String readFully(Reader reader) throws IOException { 35 | try { 36 | StringWriter writer = new StringWriter(); 37 | char[] buffer = new char[1024]; 38 | int count; 39 | while ((count = reader.read(buffer)) != -1) { 40 | writer.write(buffer, 0, count); 41 | } 42 | return writer.toString(); 43 | } finally { 44 | reader.close(); 45 | } 46 | } 47 | 48 | /** 49 | * Deletes the contents of {@code dir}. Throws an IOException if any file 50 | * could not be deleted, or if {@code dir} is not a readable directory. 51 | */ 52 | static void deleteContents(File dir) throws IOException { 53 | File[] files = dir.listFiles(); 54 | if (files == null) { 55 | throw new IOException("not a readable directory: " + dir); 56 | } 57 | for (File file : files) { 58 | if (file.isDirectory()) { 59 | deleteContents(file); 60 | } 61 | if (!file.delete()) { 62 | throw new IOException("failed to delete file: " + file); 63 | } 64 | } 65 | } 66 | 67 | static void closeQuietly(/*Auto*/Closeable closeable) { 68 | if (closeable != null) { 69 | try { 70 | closeable.close(); 71 | } catch (RuntimeException rethrown) { 72 | throw rethrown; 73 | } catch (Exception ignored) { 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib.http.converters/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion ANDROID_BUILD_SDK_VERSION as int 5 | buildToolsVersion ANDROID_BUILD_TOOLS_VERSION 6 | 7 | //如果运行jackson报错,在运行module的build.gradle文件中加入下面代码 8 | /*packagingOptions { 9 | exclude 'META-INF/LICENSE' 10 | exclude 'META-INF/NOTICE' 11 | }*/ 12 | 13 | defaultConfig { 14 | minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION as int 15 | targetSdkVersion ANDROID_BUILD_TARGET_SDK_VERSION as int 16 | versionCode VERSION_CODE as int 17 | versionName VERSION_NAME 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | lintOptions { 27 | abortOnError false 28 | } 29 | 30 | } 31 | 32 | dependencies { 33 | compile fileTree(dir: 'libs', include: ['*.jar']) 34 | testCompile 'junit:junit:4.12' 35 | compile project(':lib.http') 36 | compile 'com.fasterxml.jackson.core:jackson-databind:2.7.4' 37 | compile 'com.alibaba:fastjson:1.2.11' 38 | } 39 | 40 | //apply from: '../script/gradle-jcenter-push.gradle' 41 | 42 | /*//-----------------javadoc编码------------------------ 43 | allprojects { 44 | tasks.withType(Javadoc) { 45 | options{ 46 | encoding "UTF-8" 47 | charSet 'UTF-8' 48 | links "http://docs.oracle.com/javase/7/docs/api" 49 | } 50 | } 51 | } 52 | //-----------------jCenter 配置 begin------------------------ 53 | ext { 54 | bintrayRepo = 'RobinMaven' 55 | bintrayName = 'HttpConvertersLibrary' 56 | 57 | publishedGroupId = 'net.robinx' 58 | libraryName = 'lib.http.converters' 59 | artifact = 'lib.http.converters' 60 | 61 | libraryDescription = 'Android http converters library' 62 | 63 | siteUrl = 'http://git.oschina.net/robinxdroid/HttpRequest' 64 | gitUrl = 'https://git.oschina.net/robinxdroid/HttpRequest.git' 65 | 66 | libraryVersion = '1.0.0' 67 | 68 | developerId = 'robinx' 69 | developerName = 'robin' 70 | developerEmail = 'robinxdroid@gmail.com' 71 | 72 | licenseName = 'The Apache Software License, Version 2.0' 73 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' 74 | allLicenses = ["Apache-2.0"] 75 | 76 | } 77 | 78 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' 79 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle'*/ 80 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/HttpStatus.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network; 2 | 3 | /** 4 | * HTTP Status 5 | * 6 | * @author Robin 7 | * @since 2015-11-07 18:34:57 8 | * 9 | */ 10 | public class HttpStatus { 11 | private HttpStatus(){} 12 | public static int SC_ACCEPTED = 202; 13 | public static int SC_BAD_GATEWAY = 502; 14 | public static int SC_BAD_REQUEST = 400; 15 | public static int SC_CONFLICT = 409; 16 | public static int SC_CONTINUE = 100; 17 | public static int SC_CREATED = 201; 18 | public static int SC_EXPECTATION_FAILED = 417; 19 | public static int SC_FAILED_DEPENDENCY = 424; 20 | public static int SC_FORBIDDEN = 403; 21 | public static int SC_GATEWAY_TIMEOUT = 504; 22 | public static int SC_GONE = 410; 23 | public static int SC_HTTP_VERSION_NOT_SUPPORTED = 505; 24 | public static int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419; 25 | public static int SC_INSUFFICIENT_STORAGE = 507; 26 | public static int SC_INTERNAL_SERVER_ERROR = 500; 27 | public static int SC_LENGTH_REQUIRED = 411; 28 | public static int SC_LOCKED = 423; 29 | public static int SC_METHOD_FAILURE = 420; 30 | public static int SC_METHOD_NOT_ALLOWED = 405; 31 | public static int SC_MOVED_PERMANENTLY = 301; 32 | public static int SC_MOVED_TEMPORARILY = 302; 33 | public static int SC_MULTIPLE_CHOICES = 300; 34 | public static int SC_MULTI_STATUS = 207; 35 | public static int SC_NON_AUTHORITATIVE_INFORMATION = 203; 36 | public static int SC_NOT_ACCEPTABLE = 406; 37 | public static int SC_NOT_FOUND = 404; 38 | public static int SC_NOT_IMPLEMENTED = 501; 39 | public static int SC_NOT_MODIFIED = 304; 40 | public static int SC_NO_CONTENT = 204; 41 | public static int SC_OK = 200; 42 | public static int SC_PARTIAL_CONTENT = 206; 43 | public static int SC_PAYMENT_REQUIRED = 402; 44 | public static int SC_PRECONDITION_FAILED = 412; 45 | public static int SC_PROCESSING = 102; 46 | public static int SC_PROXY_AUTHENTICATION_REQUIRED = 407; 47 | public static int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; 48 | public static int SC_REQUEST_TIMEOUT = 408; 49 | public static int SC_REQUEST_TOO_LONG = 413; 50 | public static int SC_REQUEST_URI_TOO_LONG = 414; 51 | public static int SC_RESET_CONTENT = 205; 52 | public static int SC_SEE_OTHER = 303; 53 | public static int SC_SERVICE_UNAVAILABLE = 503; 54 | public static int SC_SWITCHING_PROTOCOLS = 101; 55 | public static int SC_TEMPORARY_REDIRECT = 307; 56 | public static int SC_UNAUTHORIZED = 401; 57 | public static int SC_UNPROCESSABLE_ENTITY = 422; 58 | public static int SC_UNSUPPORTED_MEDIA_TYPE = 415; 59 | public static int SC_USE_PROXY = 305; 60 | } 61 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/PoolingByteArrayOutputStream.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | 6 | /** 7 | * Cache write stream 8 | */ 9 | public class PoolingByteArrayOutputStream extends ByteArrayOutputStream { 10 | /** 11 | * If the {@link #PoolingByteArrayOutputStream(ByteArrayPool)} constructor 12 | * is called, this is the default size to which the underlying byte array is 13 | * initialized. 14 | */ 15 | private static final int DEFAULT_SIZE = 256; 16 | 17 | private final ByteArrayPool mPool; 18 | 19 | /** 20 | * Constructs a new PoolingByteArrayOutputStream with a default size. If 21 | * more bytes are written to this instance, the underlying byte array will 22 | * expand. 23 | */ 24 | public PoolingByteArrayOutputStream(ByteArrayPool pool) { 25 | this(pool, DEFAULT_SIZE); 26 | } 27 | 28 | /** 29 | * Constructs a new {@code ByteArrayOutputStream} with a default size of 30 | * {@code size} bytes. If more than {@code size} bytes are written to this 31 | * instance, the underlying byte array will expand. 32 | * 33 | * @param size 34 | * initial size for the underlying byte array. The value will be 35 | * pinned to a default minimum size. 36 | */ 37 | public PoolingByteArrayOutputStream(ByteArrayPool pool, int size) { 38 | mPool = pool; 39 | buf = mPool.getBuf(Math.max(size, DEFAULT_SIZE)); 40 | } 41 | 42 | @Override 43 | public void close() throws IOException { 44 | mPool.returnBuf(buf); 45 | buf = null; 46 | super.close(); 47 | } 48 | 49 | @Override 50 | public void finalize() { 51 | mPool.returnBuf(buf); 52 | } 53 | 54 | /** 55 | * Ensures there is enough space in the buffer for the given number of 56 | * additional bytes. 57 | */ 58 | private void expand(int i) { 59 | /* Can the buffer handle @i more bytes, if not expand it */ 60 | if (count + i <= buf.length) { 61 | return; 62 | } 63 | byte[] newbuf = mPool.getBuf((count + i) * 2); 64 | System.arraycopy(buf, 0, newbuf, 0, count); 65 | mPool.returnBuf(buf); 66 | buf = newbuf; 67 | } 68 | 69 | @Override 70 | public synchronized void write(byte[] buffer, int offset, int len) { 71 | expand(len); 72 | super.write(buffer, offset, len); 73 | } 74 | 75 | @Override 76 | public synchronized void write(int oneByte) { 77 | expand(1); 78 | super.write(oneByte); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/HTTPSTrustManager.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network; 2 | 3 | import java.security.KeyManagementException; 4 | import java.security.NoSuchAlgorithmException; 5 | import java.security.SecureRandom; 6 | import java.security.cert.X509Certificate; 7 | 8 | import javax.net.ssl.HostnameVerifier; 9 | import javax.net.ssl.HttpsURLConnection; 10 | import javax.net.ssl.SSLContext; 11 | import javax.net.ssl.SSLSession; 12 | import javax.net.ssl.TrustManager; 13 | import javax.net.ssl.X509TrustManager; 14 | 15 | /** 16 | * HTTPS Kit 17 | */ 18 | public class HTTPSTrustManager implements X509TrustManager { 19 | 20 | private static TrustManager[] trustManagers; 21 | private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{}; 22 | 23 | @Override 24 | public void checkClientTrusted( 25 | X509Certificate[] x509Certificates, String s) 26 | throws java.security.cert.CertificateException { 27 | // To change body of implemented methods use File | Settings | File 28 | // Templates. 29 | } 30 | 31 | @Override 32 | public void checkServerTrusted( 33 | X509Certificate[] x509Certificates, String s) 34 | throws java.security.cert.CertificateException { 35 | // To change body of implemented methods use File | Settings | File 36 | // Templates. 37 | } 38 | 39 | public boolean isClientTrusted(X509Certificate[] chain) { 40 | return true; 41 | } 42 | 43 | public boolean isServerTrusted(X509Certificate[] chain) { 44 | return true; 45 | } 46 | 47 | @Override 48 | public X509Certificate[] getAcceptedIssuers() { 49 | return _AcceptedIssuers; 50 | } 51 | 52 | public static void allowAllSSL() { 53 | HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { 54 | @Override 55 | public boolean verify(String arg0, SSLSession arg1) { 56 | return true; 57 | } 58 | }); 59 | 60 | SSLContext context = null; 61 | if (trustManagers == null) { 62 | trustManagers = new TrustManager[]{new HTTPSTrustManager()}; 63 | } 64 | 65 | try { 66 | context = SSLContext.getInstance("TLS"); 67 | context.init(null, trustManagers, new SecureRandom()); 68 | } catch (NoSuchAlgorithmException e) { 69 | e.printStackTrace(); 70 | } catch (KeyManagementException e) { 71 | e.printStackTrace(); 72 | } 73 | HttpsURLConnection.setDefaultSSLSocketFactory(context 74 | .getSocketFactory()); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/retry/DefaultRetryPolicyImpl.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.retry; 2 | 3 | import net.robinx.lib.http.network.HttpException; 4 | import net.robinx.lib.http.utils.CLog; 5 | 6 | /** 7 | * Default retry policy for request. 8 | * @author Robin 9 | * @since 2015-08-19 10:08:59 10 | * 11 | */ 12 | public class DefaultRetryPolicyImpl implements RetryPolicy { 13 | private int mCurrentTimeoutMs; 14 | 15 | private int mCurrentRetryCount; 16 | 17 | private final int mMaxNumRetries; 18 | 19 | private final float mBackoffMultiplier; 20 | 21 | public static final int DEFAULT_TIMEOUT_MS = 2500; 22 | 23 | public static final int DEFAULT_MAX_RETRIES = 2; 24 | 25 | public static final float DEFAULT_BACKOFF_MULT = 1f; 26 | 27 | /*================================================================== 28 | * Constructor 29 | *================================================================== 30 | */ 31 | 32 | public DefaultRetryPolicyImpl() { 33 | this(DEFAULT_TIMEOUT_MS, DEFAULT_MAX_RETRIES, DEFAULT_BACKOFF_MULT); 34 | } 35 | 36 | public DefaultRetryPolicyImpl(int initialTimeoutMs, int maxNumRetries, float backoffMultiplier) { 37 | mCurrentTimeoutMs = initialTimeoutMs; 38 | mMaxNumRetries = maxNumRetries; 39 | mBackoffMultiplier = backoffMultiplier; 40 | } 41 | 42 | /*================================================================== 43 | * Override RetryPolicy 44 | *================================================================== 45 | */ 46 | 47 | @Override 48 | public void retry(HttpException error) throws HttpException { 49 | mCurrentRetryCount++; 50 | mCurrentTimeoutMs += (mCurrentTimeoutMs * mBackoffMultiplier); 51 | if (!canContinueToTry()) { 52 | throw error; 53 | } 54 | 55 | CLog.w("request failed , is to try the request again,current retry count = %s , current timeout = %s", mCurrentRetryCount,mCurrentTimeoutMs ); 56 | 57 | } 58 | 59 | protected boolean canContinueToTry () { 60 | return mCurrentRetryCount <= mMaxNumRetries; 61 | } 62 | 63 | 64 | public float getBackoffMultiplier() { 65 | return mBackoffMultiplier; 66 | } 67 | 68 | /*================================================================== 69 | * Getter and Setter 70 | *================================================================== 71 | */ 72 | 73 | @Override 74 | public int getCurrentTimeout() { 75 | return mCurrentTimeoutMs; 76 | } 77 | 78 | @Override 79 | public int getCurrentRetryCount() { 80 | return mCurrentRetryCount; 81 | } 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/HttpException.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network; 2 | 3 | /** 4 | * HTTP request exception 5 | * 6 | * @author Robin 7 | * @since 2015-07-02 15:10:49 8 | */ 9 | @SuppressWarnings("serial") 10 | public class HttpException extends Exception { 11 | 12 | /** Http request error code */ 13 | private int mHttpErrorCode = HttpError.ERROR_UNKNOWN; 14 | 15 | /** Http request error text */ 16 | private String mHttpErrorText; 17 | 18 | public HttpException() { 19 | } 20 | 21 | public HttpException(String exceptionMessage,int httpErrorCode) { 22 | super(exceptionMessage); 23 | this.mHttpErrorCode = httpErrorCode; 24 | this.mHttpErrorText = exceptionMessage; 25 | } 26 | 27 | public HttpException(String exceptionMessage, Throwable reason) { 28 | super(exceptionMessage, reason); 29 | this.mHttpErrorText = exceptionMessage; 30 | } 31 | 32 | public HttpException(String exceptionMessage) { 33 | super(exceptionMessage); 34 | this.mHttpErrorText = exceptionMessage; 35 | } 36 | 37 | /*public HttpException(Throwable cause) { 38 | super(cause); 39 | }*/ 40 | 41 | public int getHttpErrorCode() { 42 | return mHttpErrorCode; 43 | } 44 | 45 | public void setHttpErrorCode(int httpErrorCode) { 46 | this.mHttpErrorCode = httpErrorCode; 47 | } 48 | 49 | 50 | public String getHttpErrorText() { 51 | return mHttpErrorText; 52 | } 53 | 54 | public void setHttpErrorText(String httpErrorText) { 55 | this.mHttpErrorText = httpErrorText; 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | String errorCodeText = ""; 61 | switch (mHttpErrorCode) { 62 | case HttpError.ERROR_NOT_NETWORK: 63 | errorCodeText = "ERROR_NOT_NETWORK"; 64 | break; 65 | case HttpError.ERROR_REDIRECT: 66 | errorCodeText = "ERROR_REDIRECT"; 67 | break; 68 | case HttpError.ERROR_RESPONSE_NULL: 69 | errorCodeText = "ERROR_RESPONSE_NULL"; 70 | break; 71 | case HttpError.ERROR_SERVER: 72 | errorCodeText = "ERROR_SERVER"; 73 | break; 74 | case HttpError.ERROR_SOCKET_TIMEOUT: 75 | errorCodeText = "ERROR_SOCKET_TIMEOUT"; 76 | break; 77 | case HttpError.ERROR_UNAUTHORIZED: 78 | errorCodeText = "ERROR_UNAUTHORIZED"; 79 | break; 80 | case HttpError.ERROR_UNKNOWN: 81 | errorCodeText = "ERROR_UNKNOWN"; 82 | break; 83 | case HttpError.ERROR_NO_CONNECTION: 84 | errorCodeText = "ERROR_NO_CONNECTION"; 85 | break; 86 | case HttpError.ERROR_PARSE: 87 | errorCodeText = "ERROR_PARSE"; 88 | break; 89 | default: 90 | errorCodeText = "ERROR_UNKNOWN"; 91 | break; 92 | } 93 | return "HttpException [HttpErrorCode = " + mHttpErrorCode +", HttpErrorCodeText = "+errorCodeText+ ", HttpErrorText = "+getHttpErrorText()+"]"; 94 | } 95 | 96 | 97 | 98 | } 99 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/cache/CacheData.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.cache; 2 | 3 | import java.io.Serializable; 4 | import java.text.SimpleDateFormat; 5 | 6 | import net.robinx.lib.http.utils.CLog; 7 | 8 | import android.annotation.SuppressLint; 9 | 10 | /** 11 | * define the cache data entity 12 | * 13 | * @author Robin 14 | * @since 2015-05-08 10:06:46 15 | */ 16 | @SuppressWarnings("serial") 17 | public class CacheData implements Serializable { 18 | 19 | /** 20 | * will storage's data 21 | */ 22 | private E entry; 23 | 24 | /** 25 | * the data expired time 26 | */ 27 | private long expirationTime; 28 | 29 | /** 30 | * the data write to cache time 31 | */ 32 | private long writeTime; 33 | 34 | /** 35 | * Whether never expired 36 | */ 37 | private boolean isNeverExpiry; 38 | 39 | public CacheData(E entry, long expirationTime, long writeTime) { 40 | super(); 41 | this.entry = entry; 42 | this.expirationTime = expirationTime; 43 | this.writeTime = writeTime; 44 | } 45 | 46 | public CacheData(E data, long expirationTime, long writeTime, boolean isNeverExpiry) { 47 | super(); 48 | this.entry = data; 49 | this.expirationTime = expirationTime; 50 | this.writeTime = writeTime; 51 | this.isNeverExpiry = isNeverExpiry; 52 | } 53 | 54 | public E getEntry() { 55 | return entry; 56 | } 57 | 58 | public void setEntry(E data) { 59 | this.entry = data; 60 | } 61 | 62 | public long getExpirationTime() { 63 | return expirationTime; 64 | } 65 | 66 | public void setExpirationTime(long expirationTime) { 67 | this.expirationTime = expirationTime; 68 | } 69 | 70 | public long getWriteTime() { 71 | return writeTime; 72 | } 73 | 74 | public void setWriteTime(long writeTime) { 75 | this.writeTime = writeTime; 76 | } 77 | 78 | public boolean isNeverExpiry() { 79 | return isNeverExpiry; 80 | } 81 | 82 | public void setNeverExpiry(boolean isNeverExpiry) { 83 | this.isNeverExpiry = isNeverExpiry; 84 | } 85 | 86 | /** 87 | * check out the data is or not expired 88 | * 89 | * @return 90 | */ 91 | public Boolean isExpired() { 92 | if (isNeverExpiry) { 93 | return false; 94 | } 95 | 96 | if (writeTime <= 0) { 97 | return true; 98 | } 99 | if (expirationTime <= 0) { 100 | return true; 101 | } 102 | long intervalTime = System.currentTimeMillis() - writeTime; 103 | String format = "yyyy-MM-dd HH:mm"; 104 | String currentTimeStr = getStringByFormat(System.currentTimeMillis(), format); 105 | String writeTimeStr = getStringByFormat(writeTime, format); 106 | CLog.d("currentTime:%s,writeTime:%s,interval:%s s", (Object)currentTimeStr, writeTimeStr , intervalTime/1000); 107 | 108 | if (intervalTime < expirationTime) { 109 | return false; 110 | } else { 111 | // expired 112 | return true; 113 | } 114 | } 115 | 116 | @SuppressLint("SimpleDateFormat") 117 | private static String getStringByFormat(long milliseconds,String format) { 118 | String thisDateTime = null; 119 | try { 120 | SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); 121 | thisDateTime = mSimpleDateFormat.format(milliseconds); 122 | } catch (Exception e) { 123 | e.printStackTrace(); 124 | } 125 | return thisDateTime; 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/XRequest.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http; 2 | 3 | import net.robinx.lib.http.base.Request; 4 | import net.robinx.lib.http.cache.CacheConfig; 5 | import net.robinx.lib.http.config.RequestCacheOptions; 6 | import net.robinx.lib.http.network.HttpStack; 7 | import net.robinx.lib.http.queue.RequestQueue; 8 | import net.robinx.lib.http.utils.AppUtils; 9 | 10 | import android.content.Context; 11 | 12 | /** 13 | * Encapsulates the request,for the convenience of call 14 | * 15 | * @author Robin 16 | * @since 2015-08-12 17:43:03 17 | */ 18 | public enum XRequest { 19 | INSTANCE; 20 | private XRequest(){ 21 | 22 | } 23 | 24 | public static void initXRequest(Context context) { 25 | RequestContext.init(context); 26 | CacheConfig.DISK_CACHE_MAX_SIZE = CacheConfig.DEFAULT_MAX_SIZE; 27 | CacheConfig.DISK_CACHE_DIRECTORY = AppUtils.getDiskCacheDir(context, "xrequest"); 28 | CacheConfig.DISK_CACHE_APP_VERSION = AppUtils.getAppVersion(context); 29 | CacheConfig.MEMORY_CACHE_MAX_SIZE = (int) Runtime.getRuntime().maxMemory() / 8; 30 | } 31 | 32 | private RequestQueue queue; 33 | 34 | /** 35 | * Best during application initialization calls only once 36 | * 37 | * @param threadPoolSize 38 | */ 39 | public void setRequestThreadPoolSize(int threadPoolSize) { 40 | if (queue != null) { 41 | queue.stop(); 42 | queue = null; 43 | } 44 | queue = new RequestQueue(threadPoolSize); 45 | queue.start(); 46 | } 47 | 48 | 49 | /** 50 | * Add a request to queue to execute 51 | * 52 | * @param request Target request 53 | */ 54 | public void addToRequestQueue(Request request) { 55 | if (queue == null) { 56 | queue = new RequestQueue(); 57 | queue.start(); 58 | } 59 | queue.add(request); 60 | } 61 | 62 | public void setStack(HttpStack stack){ 63 | //Need to initialize the queue 64 | shutdown(); 65 | if (queue != null) { 66 | queue.stop(); 67 | queue = null; 68 | } 69 | queue = new RequestQueue(stack); 70 | queue.start(); 71 | } 72 | 73 | /** 74 | * Create a default cache configuration 75 | * 76 | * @return 77 | */ 78 | public RequestCacheOptions getDefaultRequestCacheOptions() { 79 | return RequestCacheOptions.buildDefaultCacheOptions(); 80 | } 81 | 82 | /** 83 | * To cancel a request that is requesting 84 | * 85 | * @param request 86 | */ 87 | public void cancelRequest(Request request) { 88 | if (null != request) { 89 | request.cancel(); 90 | } 91 | } 92 | 93 | /** 94 | * Cancel all of this request in the request queue , not including is 95 | * requested 96 | * 97 | * @param tag If there is no special Settings, then introduction the 98 | * instance of activity 99 | */ 100 | public void cancelAllRequestInQueueByTag(Object tag) { 101 | if (queue != null) { 102 | queue.cancelAll(tag); 103 | } 104 | } 105 | 106 | /** 107 | * Start the request,start the thread pool 108 | */ 109 | public void start() { 110 | if (queue != null) { 111 | queue.start(); 112 | } 113 | } 114 | 115 | /** 116 | * Close the request, quit all threads, release the request queue 117 | */ 118 | public void shutdown() { 119 | if (queue != null) { 120 | queue.stop(); 121 | queue = null; 122 | } 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/utils/GenericsUtils.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.utils; 2 | 3 | import java.lang.reflect.Method; 4 | import java.lang.reflect.ParameterizedType; 5 | import java.lang.reflect.Type; 6 | 7 | /** 8 | * Parse helper 9 | * @author Robin 10 | * @since 2015-11-10 14:50:21 11 | * 12 | */ 13 | public class GenericsUtils { 14 | 15 | public static Type[] getGenericOuterTypeByMethod(Class cls,String methodName,Class parameterTypes){ 16 | try { 17 | Method method = cls.getMethod(methodName, parameterTypes) ; 18 | Type[] pType = method.getParameterTypes(); 19 | return pType; 20 | } catch (Exception e) { 21 | e.printStackTrace(); 22 | return null; 23 | } 24 | } 25 | 26 | public static Type[] getGenericInnerTypeByMethod(Class cls,String methodName,Class parameterTypes){ 27 | try { 28 | Method method = cls.getMethod(methodName, parameterTypes) ; 29 | Type[] innerType = method.getGenericParameterTypes(); 30 | return innerType; 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | return null; 34 | } 35 | } 36 | 37 | 38 | public static Type getBeanClassType(T listener) { 39 | Type type; 40 | try { 41 | Type[] typs = GenericsUtils.getGenericInterfaces(listener.getClass()); 42 | if (typs != null) { 43 | type = typs[0]; 44 | } else { 45 | type = GenericsUtils.getGenericSuperclass(listener.getClass())[0]; 46 | } 47 | } catch (Exception e) { 48 | throw new RuntimeException("unknow type"); 49 | } 50 | return type; 51 | } 52 | 53 | /** 54 | * Take the parent class generic 55 | * @param clazz 56 | * @return 57 | */ 58 | public static Type[] getGenericSuperclass(Class clazz) { 59 | try { 60 | Type typeGeneric = clazz.getGenericSuperclass(); 61 | if (typeGeneric != null) { 62 | if (typeGeneric instanceof ParameterizedType) { 63 | return getGeneric((ParameterizedType) typeGeneric); 64 | } 65 | } 66 | } catch (Exception e) { 67 | e.printStackTrace(); 68 | } 69 | return null; 70 | } 71 | /** 72 | * Take the parent interface generic 73 | * @param clazz 74 | * @return 75 | */ 76 | public static Type[] getGenericInterfaces(Class clazz) { 77 | try { 78 | Type typeGeneric = clazz.getGenericInterfaces()[0]; 79 | if (typeGeneric != null) { 80 | if (typeGeneric instanceof ParameterizedType) { 81 | return getGeneric((ParameterizedType) typeGeneric); 82 | } 83 | } 84 | } catch (Exception e) { 85 | e.printStackTrace(); 86 | } 87 | return null; 88 | } 89 | /** 90 | * Take a generic 91 | * @param type 92 | * @return 93 | */ 94 | public static Type[] getGeneric(ParameterizedType type) { 95 | try { 96 | if (type != null) { 97 | Type[] typeArgs = type.getActualTypeArguments(); 98 | if (typeArgs != null && typeArgs.length > 0) { 99 | return typeArgs; 100 | } else { 101 | return null; 102 | } 103 | } else { 104 | return null; 105 | } 106 | } catch (Exception e) { 107 | e.printStackTrace(); 108 | return null; 109 | } 110 | 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /script/gradle-jcenter-push.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Robin <735506404@robinx.net> 3 | * WebSite http://www.robinx.net 4 | * Created 1/11/2016 5 | * Changed 1/11/2016 6 | * Version 1.0.0 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | /* 22 | *Use "gradle clean build bintrayUpload" to upload 23 | */ 24 | 25 | apply plugin: 'com.jfrog.bintray' 26 | apply plugin: 'com.github.dcendents.android-maven' 27 | 28 | group = POM_GROUP_ID 29 | version = VERSION_NAME 30 | 31 | afterEvaluate { project -> 32 | install { 33 | repositories.mavenInstaller { 34 | configurePOM(pom); 35 | } 36 | } 37 | 38 | task sourcesJar(type: Jar) { 39 | classifier = 'sources' 40 | from android.sourceSets.main.java.srcDirs 41 | } 42 | 43 | task javadoc(type: Javadoc) { 44 | failOnError false 45 | source = android.sourceSets.main.java.srcDirs 46 | options { 47 | links "http://docs.oracle.com/javase/7/docs/api/" 48 | linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference" 49 | } 50 | classpath += project.android.libraryVariants.toList().first().javaCompile.classpath 51 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 52 | } 53 | 54 | task javadocJar(type: Jar, dependsOn: javadoc) { 55 | classifier = 'javadoc' 56 | from javadoc.destinationDir 57 | } 58 | 59 | artifacts { 60 | archives javadocJar 61 | archives sourcesJar 62 | } 63 | } 64 | 65 | private configurePOM(def pom) { 66 | pom.project { 67 | packaging POM_PACKAGING 68 | groupId POM_GROUP_ID 69 | artifactId POM_ARTIFACT_ID 70 | 71 | name POM_NAME 72 | description POM_DESCRIPTION 73 | url POM_URL 74 | 75 | version VERSION_NAME 76 | inceptionYear POM_INCEPTION_YEAR 77 | 78 | licenses { 79 | license { 80 | name POM_LICENCE_NAME 81 | url POM_LICENCE_URL 82 | distribution POM_LICENCE_DIST 83 | comments POM_LICENCE_COMMENTS 84 | } 85 | } 86 | 87 | developers { 88 | developer { 89 | id POM_DEVELOPER_ID 90 | name POM_DEVELOPER_NAME 91 | email POM_DEVELOPER_EMAIL 92 | url POM_DEVELOPER_URL 93 | } 94 | } 95 | 96 | scm { 97 | url POM_SCM_URL 98 | connection POM_SCM_CONNECTION 99 | developerConnection POM_SCM_DEV_CONNECTION 100 | } 101 | 102 | issueManagement { 103 | system POM_ISSUE_MANAGEMENT_SYSTEM 104 | url POM_ISSUE_MANAGEMENT_URL 105 | } 106 | } 107 | } 108 | 109 | // Default Bintray 110 | def getRepositoryUser() { 111 | return hasProperty('BINTRAY_USER') ? BINTRAY_USER : "" 112 | } 113 | 114 | def getRepositoryKey() { 115 | return hasProperty('BINTRAY_KEY') ? BINTRAY_KEY : "" 116 | } 117 | 118 | def getRepositoryGPGPassword() { 119 | return hasProperty('BINTRAY_GPG_PASSWORD') ? BINTRAY_GPG_PASSWORD : "" 120 | } 121 | 122 | bintray { 123 | user = getRepositoryUser(); 124 | key = getRepositoryKey(); 125 | 126 | group = POM_GROUP_ID 127 | version = VERSION_NAME 128 | 129 | configurations = ['archives'] 130 | 131 | pkg { 132 | repo = POM_BINTRAY_PRPO 133 | name = POM_BINTRAY_NAME 134 | desc = POM_DESCRIPTION 135 | websiteUrl = POM_URL 136 | vcsUrl = POM_GIT_URL 137 | licenses = POM_LICENCE_ALL 138 | publish = true 139 | publicDownloadNumbers = true 140 | version { 141 | desc = POM_DESCRIPTION 142 | gpg { 143 | sign = true //Determines whether to GPG sign the files. The default is false 144 | passphrase = getRepositoryGPGPassword(); 145 | //Optional. The passphrase for GPG signing' 146 | } 147 | } 148 | } 149 | } 150 | 151 | -------------------------------------------------------------------------------- /lib.http.okhttpsupport/src/main/java/net/robinx/lib/http/okhttp/OkRequestBody.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.okhttp; 2 | 3 | import net.robinx.lib.http.callback.BytesWriteListener; 4 | import net.robinx.lib.http.network.ex.Body; 5 | import net.robinx.lib.http.network.ex.RequestParams; 6 | 7 | import java.io.File; 8 | import java.util.Map; 9 | 10 | import okhttp3.FormBody; 11 | import okhttp3.MediaType; 12 | import okhttp3.MultipartBody; 13 | import okhttp3.RequestBody; 14 | 15 | /** 16 | * Can submit key/value pair, files, key/value pair and files, JSON, 17 | * If the request parameter contains a JSON parameters, send JSON parameters, 18 | * this time even contain key/value pair or file parameter will not be sent 19 | * @author Robin 20 | * @since 2016-01-07 18:53:19 21 | * 22 | */ 23 | public class OkRequestBody implements Body{ 24 | 25 | private BytesWriteListener mBytesWriteListener; 26 | 27 | /*====================================================== 28 | * Override Super 29 | *====================================================== 30 | */ 31 | 32 | 33 | @Override 34 | public RequestBody buildBody(RequestParams params,Object...args) { 35 | if (params == null) { 36 | return RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"), "".getBytes()); 37 | } 38 | if (params.hasJsonInParams()) { 39 | // has json 40 | return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), params.buildJsonParams()); 41 | 42 | } else if (params.isEmpty()) { 43 | return RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"), "".getBytes()); 44 | } else if (params.hasFileInParams()) { 45 | // has file 46 | return createMultipartBody(params); 47 | } else { 48 | // key/value 49 | return createFormBody(params); 50 | 51 | } 52 | } 53 | 54 | private RequestBody createFormBody(RequestParams params) { 55 | FormBody.Builder formBodyBuilder = new FormBody.Builder(); 56 | for (Map.Entry entry : params.entrySet()) { 57 | Object value = entry.getValue(); 58 | if (value == null) { 59 | continue; 60 | } 61 | 62 | formBodyBuilder.add(entry.getKey(),String.valueOf(value)); 63 | 64 | } 65 | 66 | RequestBody formBody = formBodyBuilder.build(); 67 | return formBody; 68 | } 69 | 70 | private RequestBody createMultipartBody(RequestParams params) { 71 | MultipartBody.Builder builder = new MultipartBody.Builder(); 72 | builder.setType(MultipartBody.FORM); 73 | 74 | int fileIndex = 1; 75 | if(params != null && !params.isEmpty()) { 76 | for (Map.Entry entry : params.entrySet()) { 77 | Object value = entry.getValue(); 78 | if (value == null) { 79 | continue; 80 | } 81 | 82 | if (value instanceof File) { //add file 83 | final File file = (File) value; 84 | String fileName = file.getName(); 85 | 86 | 87 | RequestBody fileBody = RequestBody.create(getMediaType(fileName),file); 88 | builder.addFormDataPart(entry.getKey(), fileName, new RequestBodyProxy(fileBody,fileIndex,file, new BytesWriteListener() { 89 | @Override 90 | public void onWrite(long transferredBytesSize, long totalSize, int currentFileIndex, File currentFile) { 91 | if (mBytesWriteListener != null) { 92 | mBytesWriteListener.onWrite(transferredBytesSize,totalSize,currentFileIndex,currentFile); 93 | } 94 | 95 | } 96 | 97 | })); 98 | //builder.addFormDataPart(entry.getKey(),fileName,fileBody); 99 | fileIndex++; 100 | 101 | } else { //add field 102 | builder.addFormDataPart(entry.getKey(),String.valueOf(value)); 103 | } 104 | 105 | } 106 | } 107 | 108 | return builder.build(); 109 | 110 | } 111 | 112 | 113 | /** 114 | * get ContentType by file name 115 | * @param fileName 116 | * @return 117 | */ 118 | private MediaType getMediaType(String fileName) { 119 | boolean isPng = fileName.lastIndexOf("png") > 0 || fileName.lastIndexOf("PNG") > 0; 120 | if (isPng) { 121 | return MediaType.parse("image/png; charset=UTF-8"); 122 | } 123 | 124 | boolean isJpg = fileName.lastIndexOf("jpg") > 0 || fileName.lastIndexOf("JPG") > 0 125 | ||fileName.lastIndexOf("jpeg") > 0 || fileName.lastIndexOf("JPEG") > 0; 126 | if (isJpg) { 127 | return MediaType.parse("image/jpeg; charset=UTF-8"); 128 | } 129 | return null; 130 | } 131 | 132 | @Override 133 | public void setBytesWriteListener(BytesWriteListener listener) { 134 | this.mBytesWriteListener = listener; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/ex/StringRequest.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network.ex; 2 | 3 | import net.robinx.lib.http.callback.OnRequestListener; 4 | import net.robinx.lib.http.config.HttpMethod; 5 | import net.robinx.lib.http.config.Priority; 6 | import net.robinx.lib.http.config.RequestCacheOptions; 7 | import net.robinx.lib.http.response.NetworkResponse; 8 | import net.robinx.lib.http.response.Response; 9 | import net.robinx.lib.http.retry.DefaultRetryPolicyImpl; 10 | import net.robinx.lib.http.retry.RetryPolicy; 11 | 12 | /** 13 | * Get char sequence from network 14 | * 15 | * @author Robin 16 | * @since 2016-01-05 19:15:06 17 | */ 18 | public class StringRequest extends HttpRequest { 19 | 20 | private StringRequest(Builder builder) { 21 | super(); 22 | 23 | super.mRequestCacheOptions = builder.requestCacheOptions; 24 | super.retryPolicy = builder.retryPolicy; 25 | super.onRequestListener = builder.onRequestListener; 26 | super.mPriority = builder.priority; 27 | super.httpMethod = builder.httpMethod; 28 | super.cacheKey = builder.cacheKey; 29 | super.mTag = builder.tag; 30 | super.mUrl = builder.url; 31 | 32 | if (builder.requestParams != null) { 33 | super.mRequestParams = builder.requestParams; 34 | } 35 | if (builder.body != null) { 36 | super.mBody = builder.body; 37 | super.mBody.setBytesWriteListener(super.getBytesWriteListener()); 38 | } 39 | 40 | //handler default 41 | if (super.cacheKey == null) { 42 | super.cacheKey = builder.url; 43 | } 44 | 45 | if (super.mPriority == null) { 46 | setPriority(Priority.NORMAL); 47 | } 48 | 49 | if (super.retryPolicy == null) { 50 | setRetryPolicy(new DefaultRetryPolicyImpl(DefaultRetryPolicyImpl.DEFAULT_TIMEOUT_MS, DefaultRetryPolicyImpl.DEFAULT_MAX_RETRIES, DefaultRetryPolicyImpl.DEFAULT_BACKOFF_MULT)); 51 | } 52 | 53 | if (super.mRequestCacheOptions == null) { 54 | setRequestCacheOptions(RequestCacheOptions.buildDefaultCacheOptions()); 55 | } 56 | 57 | if (super.httpMethod == HttpMethod.GET) { 58 | super.mUrl = builder.url+super.mRequestParams.buildQueryParameters(); 59 | } else { 60 | super.mUrl = builder.url; 61 | } 62 | 63 | } 64 | 65 | @Override 66 | public Response parseNetworkResponse(NetworkResponse response) { 67 | return Response.success(new String(response.data), response.headers); 68 | } 69 | 70 | 71 | /* 72 | * ========================================================================= 73 | * Inner class 74 | * ========================================================================= 75 | */ 76 | public static class Builder implements net.robinx.lib.http.base.Builder> { 77 | 78 | //HttpRequest property 79 | private RequestParams requestParams; 80 | private Body body; 81 | 82 | //Request property 83 | private RequestCacheOptions requestCacheOptions; 84 | private RetryPolicy retryPolicy; 85 | private String url; 86 | private String cacheKey; 87 | private Object tag; 88 | private Priority priority; 89 | private OnRequestListener onRequestListener; 90 | private int httpMethod; 91 | 92 | public Builder() { 93 | } 94 | 95 | public Builder requestParams(RequestParams requestParams) { 96 | this.requestParams = requestParams; 97 | return this; 98 | } 99 | 100 | public Builder body(Body body) { 101 | this.body = body; 102 | return this; 103 | } 104 | 105 | public Builder requestCacheOptions(RequestCacheOptions requestCacheOptions) { 106 | this.requestCacheOptions = requestCacheOptions; 107 | return this; 108 | } 109 | 110 | public Builder retryPolicy(RetryPolicy retryPolicy) { 111 | this.retryPolicy = retryPolicy; 112 | return this; 113 | } 114 | 115 | public Builder url(String url) { 116 | this.url = url; 117 | return this; 118 | } 119 | 120 | public Builder cacheKey(String cacheKey) { 121 | this.cacheKey = cacheKey; 122 | return this; 123 | } 124 | 125 | public Builder tag(Object tag) { 126 | this.tag = tag; 127 | return this; 128 | } 129 | 130 | public Builder priority(Priority priority) { 131 | this.priority = priority; 132 | return this; 133 | } 134 | 135 | public Builder onRequestListener(OnRequestListener onRequestListener) { 136 | this.onRequestListener = onRequestListener; 137 | return this; 138 | } 139 | 140 | public Builder httpMethod(int httpMethod) { 141 | this.httpMethod = httpMethod; 142 | return this; 143 | } 144 | 145 | @Override 146 | public HttpRequest build() { 147 | return new StringRequest(this); 148 | } 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /lib.http.okhttpsupport/src/main/java/net/robinx/lib/http/okhttp/OkHttpStack.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.okhttp; 2 | 3 | import net.robinx.lib.http.base.Request; 4 | import net.robinx.lib.http.config.HttpMethod; 5 | import net.robinx.lib.http.network.HttpResponse; 6 | import net.robinx.lib.http.network.HttpStack; 7 | import net.robinx.lib.http.utils.CLog; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | import okhttp3.OkHttpClient; 16 | 17 | 18 | import okhttp3.Call; 19 | import okhttp3.Headers; 20 | import okhttp3.RequestBody; 21 | import okhttp3.Response; 22 | import okhttp3.ResponseBody; 23 | 24 | /** 25 | * Created by Robin on 2016/4/23. 26 | * 27 | * OkHttpClient okClient = new OkHttpClient.Builder().build(); 28 | * RequestQueue queue = Volley.newRequestQueue(context, new OkHttpStack(okClient)); 29 | */ 30 | public class OkHttpStack implements HttpStack { 31 | 32 | 33 | public OkHttpStack() { 34 | } 35 | 36 | @Override 37 | public HttpResponse performRequest(Request request, Map additionalHeaders) throws IOException { 38 | CLog.w("Current Stack:%s","OK_HTTP"); 39 | 40 | int timeoutMs = request.getRetryPolicy().getCurrentTimeout(); 41 | OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); 42 | builder.connectTimeout(timeoutMs, TimeUnit.MILLISECONDS) 43 | .readTimeout(timeoutMs, TimeUnit.MILLISECONDS) 44 | .writeTimeout(timeoutMs, TimeUnit.MILLISECONDS); 45 | OkHttpClient client = builder.build(); 46 | 47 | okhttp3.Request.Builder okHttpRequestBuilder = new okhttp3.Request.Builder(); 48 | okHttpRequestBuilder.url(request.getUrl()); 49 | 50 | Map headers = request.getHeaders(); 51 | for (final String name : headers.keySet()) { 52 | okHttpRequestBuilder.addHeader(name, headers.get(name)); 53 | } 54 | for (final String name : additionalHeaders.keySet()) { 55 | // 这里用header方法,如果有重复的name,会覆盖,否则某些请求会被判定为非法 56 | okHttpRequestBuilder.header(name, additionalHeaders.get(name)); 57 | } 58 | 59 | setConnectionParametersForRequest(okHttpRequestBuilder, request); 60 | 61 | okhttp3.Request okHttpRequest = okHttpRequestBuilder.build(); 62 | Call okHttpCall = client.newCall(okHttpRequest); 63 | Response okHttpResponse = okHttpCall.execute(); 64 | 65 | HttpResponse response = responseFromConnection(okHttpResponse); 66 | 67 | return response; 68 | } 69 | 70 | /** 71 | * Create HttpResponse from OkHttp 72 | */ 73 | private HttpResponse responseFromConnection(Response okHttpResponse) throws IOException { 74 | HttpResponse response = new HttpResponse(); 75 | int responseCode = okHttpResponse.code(); 76 | if (responseCode == -1) { 77 | throw new IOException("Could not retrieve response code from OkHttp."); 78 | } 79 | response.setResponseCode(responseCode); 80 | response.setResponseMessage(okHttpResponse.message()); 81 | // contentStream 82 | ResponseBody body = okHttpResponse.body(); 83 | 84 | InputStream inputStream = body.byteStream(); 85 | response.setContentStream(inputStream); 86 | response.setContentLength(body.contentLength()); 87 | response.setContentEncoding(okHttpResponse.header("Content-Encoding")); 88 | response.setContentType(body.contentType().type()); 89 | // header 90 | Map headerMap = new HashMap(); 91 | 92 | Headers responseHeaders = okHttpResponse.headers(); 93 | for (int i = 0, len = responseHeaders.size(); i < len; i++) { 94 | final String name = responseHeaders.name(i), value = responseHeaders.value(i); 95 | if (name != null) { 96 | headerMap.put(name, value); 97 | response.setHeaders(headerMap); 98 | } 99 | } 100 | 101 | return response; 102 | } 103 | 104 | private static void setConnectionParametersForRequest( 105 | okhttp3.Request.Builder builder, Request request) throws IOException{ 106 | switch (request.getHttpMethod()) { 107 | case HttpMethod.GET: 108 | builder.get(); 109 | break; 110 | case HttpMethod.DELETE: 111 | builder.delete(); 112 | break; 113 | case HttpMethod.POST: 114 | builder.post(addBodyIfExists(request)); 115 | break; 116 | case HttpMethod.PUT: 117 | builder.put(addBodyIfExists(request)); 118 | break; 119 | case HttpMethod.HEAD: 120 | builder.head(); 121 | break; 122 | case HttpMethod.OPTIONS: 123 | builder.method("OPTIONS", null); 124 | break; 125 | case HttpMethod.TRACE: 126 | builder.method("TRACE", null); 127 | break; 128 | case HttpMethod.PATCH: 129 | builder.patch(addBodyIfExists(request)); 130 | break; 131 | default: 132 | throw new IllegalStateException("Unknown method type."); 133 | } 134 | } 135 | 136 | private static RequestBody addBodyIfExists(Request request) { 137 | return request.buildBody(); 138 | } 139 | } -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/ex/SyncRequest.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network.ex; 2 | 3 | import net.robinx.lib.http.base.Request; 4 | import net.robinx.lib.http.callback.OnRequestListener; 5 | import net.robinx.lib.http.config.DataType; 6 | import net.robinx.lib.http.network.HttpException; 7 | import net.robinx.lib.http.response.NetworkResponse; 8 | import net.robinx.lib.http.utils.CLog; 9 | 10 | import java.io.File; 11 | import java.util.Map; 12 | import java.util.concurrent.ExecutionException; 13 | import java.util.concurrent.Future; 14 | import java.util.concurrent.TimeUnit; 15 | import java.util.concurrent.TimeoutException; 16 | 17 | /** 18 | * Created by Robin on 2016/11/21 16:03. 19 | * Is used to create a synchronous request 20 | */ 21 | 22 | public class SyncRequest implements Future,OnRequestListener { 23 | 24 | private Request mRequest; 25 | private boolean mResultReceived = false; 26 | private T mResult; 27 | private HttpException mHttpException; 28 | 29 | public static SyncRequest newSyncRequest() { 30 | return new SyncRequest<>(); 31 | } 32 | 33 | private SyncRequest() {} 34 | 35 | public void setRequest(Request request) { 36 | mRequest = request; 37 | } 38 | 39 | 40 | /*========================================================== 41 | Override Future 42 | *========================================================== 43 | */ 44 | 45 | @Override 46 | public synchronized boolean cancel(boolean mayInterruptIfRunning) { 47 | if (mRequest == null) { 48 | return false; 49 | } 50 | 51 | if (!isDone()) { 52 | mRequest.cancel(); 53 | return true; 54 | } else { 55 | return false; 56 | } 57 | } 58 | 59 | @Override 60 | public T get() throws InterruptedException, ExecutionException { 61 | try { 62 | return doGet(null); 63 | } catch (TimeoutException e) { 64 | throw new AssertionError(e); 65 | } 66 | } 67 | 68 | @Override 69 | public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { 70 | return doGet(TimeUnit.MILLISECONDS.convert(timeout, unit)); 71 | } 72 | 73 | private synchronized T doGet(Long timeoutMs) throws InterruptedException, ExecutionException, TimeoutException { 74 | if (mHttpException != null) { 75 | throw new ExecutionException(mHttpException); 76 | } 77 | 78 | if (mResultReceived) { 79 | return mResult; 80 | } 81 | 82 | if (timeoutMs == null) { 83 | wait(0); 84 | } else if (timeoutMs > 0) { 85 | wait(timeoutMs); 86 | } 87 | 88 | if (mHttpException != null) { 89 | throw new ExecutionException(mHttpException); 90 | } 91 | 92 | if (!mResultReceived) { 93 | throw new TimeoutException(); 94 | } 95 | 96 | return mResult; 97 | } 98 | 99 | @Override 100 | public boolean isCancelled() { 101 | if (mRequest == null) { 102 | return false; 103 | } 104 | return mRequest.isCanceled(); 105 | } 106 | 107 | @Override 108 | public synchronized boolean isDone() { 109 | return mResultReceived || mHttpException != null || isCancelled(); 110 | } 111 | 112 | /*========================================================== 113 | Override OnRequestListener 114 | *========================================================== 115 | */ 116 | 117 | 118 | @Override 119 | public synchronized void onRequestPrepare(Request request) { 120 | CLog.d("SyncRequest "); 121 | } 122 | 123 | @Override 124 | public synchronized void onRequestFailed(Request request, HttpException httpException) { 125 | CLog.d("SyncRequest "); 126 | mHttpException = httpException; 127 | notifyAll(); 128 | } 129 | 130 | @Override 131 | public synchronized void onRequestRetry(Request request, int currentRetryCount, HttpException previousError) { 132 | CLog.d("SyncRequest "); 133 | } 134 | 135 | @Override 136 | public synchronized void onRequestDownloadProgress(Request request, long transferredBytesSize, long totalSize) { 137 | CLog.d("SyncRequest "); 138 | } 139 | 140 | @Override 141 | public synchronized void onRequestUploadProgress(Request request, long transferredBytesSize, long totalSize, int currentFileIndex, File currentFile) { 142 | CLog.d("SyncRequest "); 143 | } 144 | 145 | @Override 146 | public synchronized void onRequestFinish(Request request, Map headers, T result) { 147 | CLog.d("SyncRequest "); 148 | } 149 | 150 | @Override 151 | public synchronized void onCacheDataLoadFinish(Request request, Map headers, T result) { 152 | CLog.d("SyncRequest "); 153 | } 154 | 155 | @Override 156 | public synchronized boolean onParseNetworkResponse(Request request, NetworkResponse networkResponse, T result) { 157 | CLog.d("SyncRequest "); 158 | return true; 159 | } 160 | 161 | @Override 162 | public synchronized void onDone(Request request, Map headers, T result, DataType dataType) { 163 | CLog.d("SyncRequest "); 164 | mResultReceived = true; 165 | mResult = result; 166 | notifyAll(); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/ByteArrayPool.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.Comparator; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | 9 | /** 10 | * ByteArrayPool is a source and repository of byte[] objects. Its 11 | * purpose is to supply those buffers to consumers who need to use them for a 12 | * short period of time and then dispose of them. Simply creating and disposing 13 | * such buffers in the conventional manner can considerable heap churn and 14 | * garbage collection delays on Android, which lacks good management of 15 | * short-lived heap objects. It may be advantageous to trade off some memory in 16 | * the form of a permanently allocated pool of buffers in order to gain heap 17 | * performance improvements; that is what this class does. 18 | *

19 | * A good candidate user for this class is something like an I/O system that 20 | * uses large temporary byte[] buffers to copy data around. In 21 | * these use cases, often the consumer wants the buffer to be a certain minimum 22 | * size to ensure good performance (e.g. when copying data chunks off of a 23 | * stream), but doesn't mind if the buffer is larger than the minimum. Taking 24 | * this into account and also to maximize the odds of being able to reuse a 25 | * recycled buffer, this class is free to return buffers larger than the 26 | * requested size. The caller needs to be able to gracefully deal with getting 27 | * buffers any size over the minimum. 28 | *

29 | * If there is not a suitably-sized buffer in its recycling pool when a buffer 30 | * is requested, this class will allocate a new buffer and return it. 31 | *

32 | * This class has no special ownership of buffers it creates; the caller is free 33 | * to take a buffer it receives from this pool, use it permanently, and never 34 | * return it to the pool; additionally, it is not harmful to return to this pool 35 | * a buffer that was allocated elsewhere, provided there are no other lingering 36 | * references to it. 37 | *

38 | * This class ensures that the total size of the buffers in its recycling pool 39 | * never exceeds a certain byte limit. When a buffer is returned that would 40 | * cause the pool to exceed the limit, least-recently-used buffers are disposed. 41 | */ 42 | public class ByteArrayPool { 43 | /** The buffer pool, arranged both by last use and by buffer size */ 44 | private final List mBuffersByLastUse = new LinkedList(); 45 | private final List mBuffersBySize = new ArrayList(64); 46 | 47 | /** The total size of the buffers in the pool */ 48 | private int mCurrentSize = 0; 49 | 50 | /** 51 | * The maximum aggregate size of the buffers in the pool. Old buffers are 52 | * discarded to stay under this limit. 53 | */ 54 | private final int mSizeLimit; 55 | 56 | /** Compares buffers by size */ 57 | protected static final Comparator BUF_COMPARATOR = new Comparator() { 58 | @Override 59 | public int compare(byte[] lhs, byte[] rhs) { 60 | return lhs.length - rhs.length; 61 | } 62 | }; 63 | 64 | /** 65 | * @param sizeLimit 66 | * the maximum size of the pool, in bytes 67 | */ 68 | private ByteArrayPool(int sizeLimit) { 69 | mSizeLimit = sizeLimit; 70 | } 71 | 72 | /** Singleton for this class. */ 73 | private static ByteArrayPool mPool = new ByteArrayPool(4096); 74 | 75 | /** Get the singleton instance. */ 76 | public static ByteArrayPool get() { 77 | return mPool; 78 | } 79 | 80 | /** Init and persisting the singleton instance. */ 81 | public static void init(int poolSize) { 82 | mPool = new ByteArrayPool(poolSize); 83 | } 84 | 85 | /** 86 | * Returns a buffer from the pool if one is available in the requested size, 87 | * or allocates a new one if a pooled one is not available. 88 | * 89 | * @param len 90 | * the minimum size, in bytes, of the requested buffer. The 91 | * returned buffer may be larger. 92 | * @return a byte[] buffer is always returned. 93 | */ 94 | public synchronized byte[] getBuf(int len) { 95 | for (int i = 0; i < mBuffersBySize.size(); i++) { 96 | byte[] buf = mBuffersBySize.get(i); 97 | if (buf.length >= len) { 98 | mCurrentSize -= buf.length; 99 | mBuffersBySize.remove(i); 100 | mBuffersByLastUse.remove(buf); 101 | return buf; 102 | } 103 | } 104 | return new byte[len]; 105 | } 106 | 107 | /** 108 | * Returns a buffer to the pool, throwing away old buffers if the pool would 109 | * exceed its allotted size. 110 | * 111 | * @param buf 112 | * the buffer to return to the pool. 113 | */ 114 | public synchronized void returnBuf(byte[] buf) { 115 | if (buf == null || buf.length > mSizeLimit) { 116 | return; 117 | } 118 | mBuffersByLastUse.add(buf); 119 | int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR); 120 | if (pos < 0) { 121 | pos = -pos - 1; 122 | } 123 | mBuffersBySize.add(pos, buf); 124 | mCurrentSize += buf.length; 125 | trim(); 126 | } 127 | 128 | /** 129 | * Removes buffers from the pool until it is under its size limit. 130 | */ 131 | private synchronized void trim() { 132 | while (mCurrentSize > mSizeLimit) { 133 | byte[] buf = mBuffersByLastUse.remove(0); 134 | mBuffersBySize.remove(buf); 135 | mCurrentSize -= buf.length; 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/dispatcher/NetworkDispatcher.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.dispatcher; 2 | import java.util.Timer; 3 | import java.util.TimerTask; 4 | import java.util.concurrent.BlockingQueue; 5 | 6 | import net.robinx.lib.http.RequestContext; 7 | import net.robinx.lib.http.base.Request; 8 | import net.robinx.lib.http.cache.CacheData; 9 | import net.robinx.lib.http.delivered.IDelivery; 10 | import net.robinx.lib.http.network.HttpError; 11 | import net.robinx.lib.http.network.HttpException; 12 | import net.robinx.lib.http.network.Network; 13 | import net.robinx.lib.http.response.NetworkResponse; 14 | import net.robinx.lib.http.response.Response; 15 | import net.robinx.lib.http.utils.CLog; 16 | import net.robinx.lib.http.utils.NetworkUtils; 17 | 18 | import android.annotation.TargetApi; 19 | import android.net.TrafficStats; 20 | import android.os.Build; 21 | import android.os.Process; 22 | 23 | /** 24 | * Provides a thread for performing network dispatch from a queue of requests. 25 | *@author Robin 26 | *@since 2015-05-08 12:30 27 | */ 28 | public class NetworkDispatcher extends Thread { 29 | /** The queue of requests to service. */ 30 | private final BlockingQueue> mQueue; 31 | 32 | private final Network mNetwork; 33 | private final IDelivery mDelivery; 34 | 35 | /** Used for telling us to die. */ 36 | private volatile boolean mQuit = false; 37 | 38 | 39 | /** 40 | * Creates a new network dispatcher thread. You must call {@link #start()} 41 | * in order to begin processing. 42 | * 43 | * @param queue Queue of incoming requests for triage 44 | */ 45 | public NetworkDispatcher(BlockingQueue> queue,Network network, IDelivery delivery) { 46 | mQueue = queue; 47 | mNetwork=network; 48 | mDelivery=delivery; 49 | } 50 | 51 | /** 52 | * Forces this dispatcher to quit immediately. If any requests are still in 53 | * the queue, they are not guaranteed to be processed. 54 | */ 55 | public void quit() { 56 | mQuit = true; 57 | interrupt(); 58 | } 59 | 60 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 61 | private void addTrafficStatsTag(Request request) { 62 | // Tag the request (if API >= 14) 63 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 64 | TrafficStats.setThreadStatsTag(request.getTrafficStatsTag()); 65 | } 66 | } 67 | 68 | @Override 69 | public void run() { 70 | Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 71 | while (true) { 72 | final Request request; 73 | try { 74 | // Take a request from the queue. 75 | request = mQueue.take(); 76 | } catch (InterruptedException e) { 77 | // We may have been interrupted because it was time to quit. 78 | if (mQuit) { 79 | return; 80 | } 81 | continue; 82 | } 83 | 84 | try { 85 | CLog.d("network-queue-take"); 86 | 87 | // If the request was cancelled already, do not perform the 88 | // network request. 89 | if (request.isCanceled()) { 90 | request.finish(); 91 | CLog.e("cache-discard-canceled-----------cacheKey:"+request.getCacheKey()); 92 | continue; 93 | } 94 | 95 | addTrafficStatsTag(request); 96 | 97 | //Reset the current request has not been paid for 98 | request.resetDelivered(); 99 | 100 | //prepare to request 101 | mDelivery.postRequestPrepare(request); 102 | 103 | //if set "UseCacheDataWhenTimeout" 104 | if (request.getRequestCacheOptions().isUseCacheDataWhenTimeout()) { 105 | final CacheData cacheData = request.getCache(request.getCacheKey()); 106 | if (cacheData != null) { 107 | new Timer().schedule(new TimerTask() { 108 | 109 | @Override 110 | public void run() { 111 | //hand in main thread to call "onCacheDataLoadFinish" 112 | CLog.d("Time has come , Delivered:%s ",request.hasHadResponseDelivered()); 113 | if (!request.hasHadResponseDelivered()) { 114 | mDelivery.postCacheResponse(request, cacheData); 115 | } 116 | 117 | } 118 | }, request.getRequestCacheOptions().getTimeController().getTimeout()); 119 | } 120 | 121 | } 122 | 123 | // Perform the network request. 124 | if (NetworkUtils.checkNet(RequestContext.getInstance())){ 125 | //request.doRequest(); 126 | NetworkResponse networkResponse=mNetwork.performRequest(request); 127 | /*Response response=Response.success(networkResponse.data, networkResponse.headers);*/ 128 | Response response=request.parseNetworkResponse(networkResponse); 129 | mDelivery.postRequestResponse(request, response); 130 | }else{ 131 | mDelivery.postError(request, new HttpException("No Network",HttpError.ERROR_NOT_NETWORK)); 132 | 133 | } 134 | 135 | }catch (HttpException e) { 136 | CLog.e( "network-http-error NetworkDispatcher Unhandled exception : "+ e.toString()); 137 | mDelivery.postError(request, e); 138 | } catch (Exception e) { 139 | CLog.e( "network-http-error NetworkDispatcher Unhandled exception : "+ e.toString()); 140 | mDelivery.postError(request, new HttpException(e.getMessage())); 141 | } 142 | } 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/ex/hurl/RequestBodyConstants.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network.ex.hurl; 2 | 3 | import java.io.File; 4 | import java.nio.charset.Charset; 5 | import java.util.Map; 6 | 7 | /** 8 | * Constants for Request 9 | * @author Robin 10 | * @since 2016-01-07 17:01:11 11 | * 12 | */ 13 | public class RequestBodyConstants { 14 | 15 | public static final String CRLF = "\r\n"; 16 | public static final String HEADER_CONTENT_TYPE = "Content-Type"; 17 | public static final String HEADER_USER_AGENT = "User-Agent"; 18 | public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition"; 19 | public static final String HEADER_CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding"; 20 | public static final String CONTENT_TYPE_MULTIPART = "multipart/form-data; charset=%s; boundary=%s"; 21 | public static final String CONTENT_TYPE_TEXT = "text/plain"; 22 | public static final String BINARY = "binary"; 23 | public static final String EIGHT_BIT = "8bit"; 24 | public static final String FORM_DATA = "form-data; name=\"%s\""; 25 | public static final String BOUNDARY_PREFIX = "--"; 26 | public static final String CONTENT_TYPE_OCTET_STREAM = "application/octet-stream"; 27 | public static final String FILENAME = "filename=\"%s\""; 28 | public static final String COLON_SPACE = ": "; 29 | public static final String SEMICOLON_SPACE = "; "; 30 | 31 | public static final int CRLF_LENGTH = CRLF.getBytes().length; 32 | public static final int HEADER_CONTENT_DISPOSITION_LENGTH = HEADER_CONTENT_DISPOSITION.getBytes().length; 33 | public static final int COLON_SPACE_LENGTH = COLON_SPACE.getBytes().length; 34 | public static final int HEADER_CONTENT_TYPE_LENGTH = HEADER_CONTENT_TYPE.getBytes().length; 35 | public static final int CONTENT_TYPE_OCTET_STREAM_LENGTH = CONTENT_TYPE_OCTET_STREAM.getBytes().length; 36 | public static final int HEADER_CONTENT_TRANSFER_ENCODING_LENGTH = HEADER_CONTENT_TRANSFER_ENCODING.getBytes().length; 37 | public static final int BINARY_LENGTH = BINARY.getBytes().length; 38 | public static final int BOUNDARY_PREFIX_LENGTH = BOUNDARY_PREFIX.getBytes().length; 39 | 40 | public static final Charset ASCII = Charset.forName("US-ASCII"); 41 | 42 | public static final byte[] CRLF_BYTES = getAsciiBytes(CRLF); 43 | 44 | /*public static int getContentLengthForMultipartRequest(String boundary, Map multipartParams, Map filesToUpload) { 45 | final int boundaryLength = boundary.getBytes().length; 46 | int contentLength = 0; 47 | for (String key : multipartParams.keySet()) { 48 | MultiPartRequest.MultiPartValue param = multipartParams.get(key); 49 | int size = boundaryLength + 50 | CRLF_LENGTH + HEADER_CONTENT_DISPOSITION_LENGTH + COLON_SPACE_LENGTH + String.format(FORM_DATA, key).getBytes().length + 51 | CRLF_LENGTH + HEADER_CONTENT_TYPE_LENGTH + COLON_SPACE_LENGTH + param.contentType.getBytes().length + 52 | CRLF_LENGTH + CRLF_LENGTH + param.value.getBytes().length + CRLF_LENGTH; 53 | 54 | contentLength += size; 55 | } 56 | 57 | for (String key : filesToUpload.keySet()) { 58 | File file = new File(filesToUpload.get(key)); 59 | int size = boundaryLength + 60 | CRLF_LENGTH + HEADER_CONTENT_DISPOSITION_LENGTH + COLON_SPACE_LENGTH + String.format(FORM_DATA + SEMICOLON_SPACE + FILENAME, key, file.getName()).getBytes().length + 61 | CRLF_LENGTH + HEADER_CONTENT_TYPE_LENGTH + COLON_SPACE_LENGTH + CONTENT_TYPE_OCTET_STREAM_LENGTH + 62 | CRLF_LENGTH + HEADER_CONTENT_TRANSFER_ENCODING_LENGTH + COLON_SPACE_LENGTH + BINARY_LENGTH + CRLF_LENGTH + CRLF_LENGTH; 63 | 64 | size += (int) file.length(); 65 | size += CRLF_LENGTH; 66 | contentLength += size; 67 | } 68 | 69 | int size = boundaryLength + BOUNDARY_PREFIX_LENGTH + CRLF_LENGTH; 70 | contentLength += size; 71 | return contentLength; 72 | }*/ 73 | 74 | public static int getContentLength(String boundary, Map requestParams) { 75 | final int boundaryLength = boundary.getBytes().length; 76 | int contentLength = 0; 77 | for (Object key : requestParams.keySet()) { 78 | Object value = requestParams.get(key); 79 | if (value instanceof File) { 80 | File fileValue = (File) value; 81 | int size = boundaryLength + 82 | CRLF_LENGTH + HEADER_CONTENT_DISPOSITION_LENGTH + COLON_SPACE_LENGTH + String.format(FORM_DATA + SEMICOLON_SPACE + FILENAME, key, fileValue.getName()).getBytes().length + 83 | CRLF_LENGTH + HEADER_CONTENT_TYPE_LENGTH + COLON_SPACE_LENGTH + CONTENT_TYPE_OCTET_STREAM_LENGTH + 84 | CRLF_LENGTH + HEADER_CONTENT_TRANSFER_ENCODING_LENGTH + COLON_SPACE_LENGTH + BINARY_LENGTH + CRLF_LENGTH + CRLF_LENGTH; 85 | 86 | size += (int) fileValue.length(); 87 | size += CRLF_LENGTH; 88 | contentLength += size; 89 | }else { 90 | String stringValue = ""; 91 | if (value instanceof String) { 92 | stringValue = (String) value; 93 | }else if (value instanceof Integer) { 94 | stringValue = (Integer) value +""; 95 | } 96 | int size = boundaryLength + 97 | CRLF_LENGTH + HEADER_CONTENT_DISPOSITION_LENGTH + COLON_SPACE_LENGTH + String.format(FORM_DATA, key).getBytes().length + 98 | CRLF_LENGTH + HEADER_CONTENT_TYPE_LENGTH + COLON_SPACE_LENGTH + 99 | // param.contentType.getBytes().length + 100 | CRLF_LENGTH + CRLF_LENGTH + stringValue.getBytes().length + CRLF_LENGTH; 101 | 102 | contentLength += size; 103 | } 104 | } 105 | 106 | int size = boundaryLength + BOUNDARY_PREFIX_LENGTH + CRLF_LENGTH; 107 | contentLength += size; 108 | return contentLength; 109 | } 110 | 111 | public static byte[] getAsciiBytes(final String data) { 112 | notNull(data, "Input"); 113 | return data.getBytes(ASCII); 114 | } 115 | 116 | private static T notNull(final T argument, final String name) { 117 | if (argument == null) { 118 | throw new IllegalArgumentException(name + " may not be null"); 119 | } 120 | return argument; 121 | } 122 | 123 | 124 | } 125 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/ex/RequestParams.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network.ex; 2 | 3 | import android.text.TextUtils; 4 | 5 | import net.robinx.lib.http.utils.CLog; 6 | 7 | import java.io.File; 8 | import java.io.UnsupportedEncodingException; 9 | import java.net.URLEncoder; 10 | import java.util.Map; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | 13 | /** 14 | * Request parameters 15 | * 16 | * @author Robin 17 | * @since 2016-01-08 14:21:27 18 | */ 19 | public class RequestParams extends ConcurrentHashMap { 20 | private static final long serialVersionUID = 1L; 21 | 22 | private final Map mHeaders = new ConcurrentHashMap(); 23 | private String mJsonParams; 24 | 25 | /* 26 | * ========================================================================= 27 | * Constructor 28 | * ========================================================================= 29 | */ 30 | 31 | public RequestParams() { 32 | } 33 | 34 | public RequestParams(String cookie) { 35 | mHeaders.put("cookie", cookie); 36 | } 37 | 38 | /* 39 | * ========================================================================= 40 | * Override Super 41 | * ========================================================================= 42 | */ 43 | 44 | @Override 45 | public Object put(String key, Object value) { 46 | if (value instanceof String || value instanceof Integer || value instanceof Long || value instanceof Short || value instanceof Float || value instanceof Double || value instanceof File) { 47 | return super.put(key, value); 48 | } else { 49 | CLog.e("Parameters need to be a file type or can be converted to string type"); 50 | throw new IllegalArgumentException("Parameters need to be a file type or can be converted to string type"); 51 | } 52 | } 53 | 54 | /* 55 | * ========================================================================= 56 | * Public Method 57 | * ========================================================================= 58 | */ 59 | 60 | public void putParams(String key, int value) { 61 | this.putParams(key, String.valueOf(value)); 62 | } 63 | 64 | public void putParams(String key, String value) { 65 | put(key, value); 66 | } 67 | 68 | public void putParams(String key, File value) { 69 | put(key, value); 70 | } 71 | 72 | public void putParams(String jsonString) { 73 | this.mJsonParams = jsonString; 74 | } 75 | 76 | public void putHeaders(String key, int value) { 77 | this.putHeaders(key, String.valueOf(value)); 78 | } 79 | 80 | public void putHeaders(String key, long value) { 81 | this.putHeaders(key, String.valueOf(value)); 82 | } 83 | 84 | public void putHeaders(String key, short value) { 85 | this.putHeaders(key, String.valueOf(value)); 86 | } 87 | 88 | public void putHeaders(String key, float value) { 89 | this.putHeaders(key, String.valueOf(value)); 90 | } 91 | 92 | public void putHeaders(String key, double value) { 93 | this.putHeaders(key, String.valueOf(value)); 94 | } 95 | 96 | public void putHeaders(String key, String value) { 97 | mHeaders.put(key, value); 98 | } 99 | 100 | public String buildJsonParams() { 101 | return mJsonParams; 102 | } 103 | 104 | /** 105 | * Converts params into an application/x-www-form-urlencoded encoded string. 106 | */ 107 | /*public StringBuilder buildParameters() { 108 | StringBuilder result = new StringBuilder(); 109 | try { 110 | for (Entry entry : this.entrySet()) { 111 | Object value = entry.getValue(); 112 | if (value == null) { 113 | continue; 114 | } 115 | if (value instanceof String || value instanceof Integer) { 116 | result.append("&"); 117 | result.append(URLEncoder.encode(entry.getKey(), "utf-8")); 118 | result.append("="); 119 | result.append(URLEncoder.encode(String.valueOf(value), "utf-8")); 120 | } else { 121 | CLog.e("Filter value,Type : %s,Value : %s", value.getClass().getName()); 122 | } 123 | } 124 | return result; 125 | } catch (UnsupportedEncodingException e) { 126 | throw new RuntimeException("Encoding not supported: " + "utf-8", e); 127 | } 128 | 129 | }*/ 130 | public StringBuilder buildQueryParameters() { 131 | StringBuilder result = new StringBuilder(); 132 | boolean isFirst = true; 133 | try { 134 | for (Entry entry : this.entrySet()) { 135 | Object value = entry.getValue(); 136 | if (value == null) { 137 | continue; 138 | } 139 | if (value instanceof String || value instanceof Integer) { 140 | if (!isFirst) { 141 | result.append("&"); 142 | } else { 143 | result.append("?"); 144 | isFirst = false; 145 | } 146 | result.append(URLEncoder.encode(entry.getKey(), "utf-8")); 147 | result.append("="); 148 | result.append(URLEncoder.encode(String.valueOf(value), "utf-8")); 149 | } else { 150 | CLog.e("Filter value,Type : %s,Value : %s", value.getClass().getName()); 151 | } 152 | 153 | } 154 | return result; 155 | } catch (UnsupportedEncodingException e) { 156 | throw new RuntimeException("Encoding not supported: " + "utf-8", e); 157 | } 158 | 159 | } 160 | 161 | public Map buildHeaders() { 162 | return mHeaders; 163 | } 164 | 165 | public boolean hasFileInParams() { 166 | for (Entry entry : this.entrySet()) { 167 | Object value = entry.getValue(); 168 | if (value == null) { 169 | continue; 170 | } 171 | if (value instanceof File) { 172 | return true; 173 | } 174 | } 175 | return false; 176 | } 177 | 178 | public boolean hasJsonInParams() { 179 | return !TextUtils.isEmpty(mJsonParams); 180 | } 181 | 182 | @Override 183 | public String toString() { 184 | if (!TextUtils.isEmpty(mJsonParams)) { 185 | return mJsonParams; 186 | } 187 | return super.toString(); 188 | } 189 | 190 | } 191 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/dispatcher/CacheDispatcher.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.dispatcher; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | 5 | import net.robinx.lib.http.base.Request; 6 | import net.robinx.lib.http.cache.CacheData; 7 | import net.robinx.lib.http.delivered.IDelivery; 8 | import net.robinx.lib.http.utils.CLog; 9 | 10 | import android.os.Process; 11 | 12 | /** 13 | * Provides a thread for performing cache triage on a queue of requests. 14 | *@author Robin 15 | *@since 2015-05-08 16:20:45 16 | */ 17 | public class CacheDispatcher extends Thread { 18 | 19 | /** The queue of requests coming in for triage. */ 20 | private final BlockingQueue> mCacheQueue; 21 | 22 | /** The queue of requests going out to the network. */ 23 | private final BlockingQueue> mNetworkQueue; 24 | 25 | /** Used for telling us to die. */ 26 | private volatile boolean mQuit = false; 27 | 28 | private final IDelivery mDelivery; 29 | 30 | /* @SuppressLint("HandlerLeak") 31 | private Handler handler=new Handler(){ 32 | @SuppressWarnings("unchecked") 33 | public void handleMessage(Message msg) { 34 | HashMap hashMap=(HashMap) msg.obj; 35 | CacheData cacheData = (CacheData) hashMap.get("data"); 36 | Request request=(Request) hashMap.get("request"); 37 | 38 | //Reset the current request has not been paid for 39 | request.resetDelivered(); 40 | 41 | request.onCacheDataLoadFinish(cacheData); 42 | }; 43 | };*/ 44 | 45 | /** 46 | * Creates a new cache triage dispatcher thread. You must call {@link #start()} 47 | * in order to begin processing. 48 | * 49 | * @param cacheQueue Queue of incoming requests for triage 50 | * @param networkQueue Queue to post requests that require network to 51 | */ 52 | public CacheDispatcher(BlockingQueue> cacheQueue, BlockingQueue> networkQueue,IDelivery delivery) { 53 | mCacheQueue = cacheQueue; 54 | mNetworkQueue = networkQueue; 55 | mDelivery=delivery; 56 | } 57 | 58 | /** 59 | * Forces this dispatcher to quit immediately. If any requests are still in 60 | * the queue, they are not guaranteed to be processed. 61 | */ 62 | public void quit() { 63 | mQuit = true; 64 | interrupt(); 65 | } 66 | 67 | @Override 68 | public void run() { 69 | CLog.v("start new dispatcher"); 70 | Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 71 | 72 | while (true) { 73 | try { 74 | // Get a request from the cache triage queue, blocking until 75 | // at least one is available. 76 | final Request request = mCacheQueue.take(); 77 | CLog.d("cache-queue-take"); 78 | 79 | // If the request has been canceled, don't bother dispatching it. 80 | if (request.isCanceled()) { 81 | request.finish(); 82 | CLog.e( "cache-discard-canceled-----------cacheKey:"+request.getCacheKey()); 83 | continue; 84 | } 85 | // use the cache data always 86 | if (request.getRequestCacheOptions().isUseCacheDataAnyway()) { 87 | CacheData cacheData = request.getCache(request.getCacheKey()); 88 | // Attempt to retrieve this item from cache. 89 | if (cacheData == null) { 90 | CLog.d("cache-miss"); 91 | // Cache miss; send off to the network dispatcher. 92 | mNetworkQueue.put(request); 93 | continue; 94 | } 95 | 96 | // We have a cache hit; parse its data for delivery back to the request. 97 | CLog.d("cache-hit"); 98 | 99 | //hand in main thread to call "onCacheDataLoadFinish" 100 | /*Message msg = handler.obtainMessage(); 101 | HashMap hashMap=new HashMap<>(); 102 | hashMap.put("data", cacheData); 103 | hashMap.put("request", request); 104 | msg.obj = hashMap; 105 | handler.sendMessage(msg);*/ 106 | 107 | mDelivery.postCacheResponse(request, cacheData); 108 | 109 | mNetworkQueue.put(request); 110 | 111 | continue; 112 | } 113 | 114 | // use the cache data when the cache data is not expired 115 | if (request.getRequestCacheOptions().isUseCacheDataWhenUnexpired()) { 116 | CacheData cacheData = request.getCache(request.getCacheKey()); 117 | // Attempt to retrieve this item from cache. 118 | if ( cacheData == null) { 119 | CLog.d("cache-miss"); 120 | // Cache miss; send off to the network dispatcher. 121 | mNetworkQueue.put(request); 122 | continue; 123 | } 124 | 125 | // If it is completely expired, just send it to the network. 126 | if (cacheData.isExpired()) { 127 | CLog.d("cache-hit-expired"); 128 | //request.setCacheEntry(entry); 129 | mNetworkQueue.put(request); 130 | continue; 131 | } 132 | 133 | // We have a cache hit; parse its data for delivery back to the request. 134 | CLog.d("cache-hit"); 135 | 136 | //hand in main thread to call "onCacheDataLoadFinish" 137 | /*Message msg = handler.obtainMessage(); 138 | HashMap hashMap=new HashMap<>(); 139 | hashMap.put("data", cacheData); 140 | hashMap.put("request", request); 141 | msg.obj = hashMap; 142 | handler.sendMessage(msg);*/ 143 | 144 | mDelivery.postCacheResponse(request, cacheData); 145 | 146 | }else { 147 | mNetworkQueue.put(request); 148 | } 149 | 150 | 151 | } catch (InterruptedException e) { 152 | // We may have been interrupted because it was time to quit. 153 | if (mQuit) { 154 | return; 155 | } 156 | continue; 157 | } 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/ex/DownloadRequest.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network.ex; 2 | 3 | import android.text.TextUtils; 4 | 5 | import net.robinx.lib.http.callback.OnRequestListener; 6 | import net.robinx.lib.http.config.HttpMethod; 7 | import net.robinx.lib.http.config.Priority; 8 | import net.robinx.lib.http.config.RequestCacheOptions; 9 | import net.robinx.lib.http.response.NetworkResponse; 10 | import net.robinx.lib.http.response.Response; 11 | import net.robinx.lib.http.retry.DefaultRetryPolicyImpl; 12 | import net.robinx.lib.http.retry.RetryPolicy; 13 | import net.robinx.lib.http.utils.CLog; 14 | 15 | import java.io.File; 16 | import java.io.FileNotFoundException; 17 | import java.io.FileOutputStream; 18 | import java.io.IOException; 19 | 20 | /** 21 | * Download request 22 | * 23 | * @author Robin 24 | * @since 2016-1-14 18:53:03 25 | */ 26 | public class DownloadRequest extends HttpRequest { 27 | 28 | private String mDownloadPath; 29 | private String mFileName; 30 | 31 | private DownloadRequest(Builder builder) { 32 | super(); 33 | this.mDownloadPath = builder.downloadPath; 34 | this.mFileName = builder.fileName; 35 | 36 | super.mRequestCacheOptions = builder.requestCacheOptions; 37 | super.retryPolicy = builder.retryPolicy; 38 | super.onRequestListener = builder.onRequestListener; 39 | super.mPriority = builder.priority; 40 | super.httpMethod = builder.httpMethod; 41 | super.cacheKey = builder.cacheKey; 42 | super.mTag = builder.tag; 43 | super.mUrl = builder.url; 44 | 45 | if (builder.requestParams != null) { 46 | super.mRequestParams = builder.requestParams; 47 | } 48 | if (builder.body != null) { 49 | super.mBody = builder.body; 50 | super.mBody.setBytesWriteListener(super.getBytesWriteListener()); 51 | } 52 | 53 | //handler default 54 | if (super.cacheKey == null) { 55 | super.cacheKey = builder.url; 56 | } 57 | 58 | if (super.mPriority == null) { 59 | setPriority(Priority.NORMAL); 60 | } 61 | 62 | if (super.retryPolicy == null) { 63 | setRetryPolicy(new DefaultRetryPolicyImpl(DefaultRetryPolicyImpl.DEFAULT_TIMEOUT_MS, DefaultRetryPolicyImpl.DEFAULT_MAX_RETRIES, DefaultRetryPolicyImpl.DEFAULT_BACKOFF_MULT)); 64 | } 65 | 66 | if (super.mRequestCacheOptions == null) { 67 | setRequestCacheOptions(RequestCacheOptions.buildDefaultCacheOptions()); 68 | } 69 | 70 | if (super.httpMethod == HttpMethod.GET) { 71 | super.mUrl = builder.url+super.mRequestParams.buildQueryParameters(); 72 | } else { 73 | super.mUrl = builder.url; 74 | } 75 | } 76 | 77 | @Override 78 | public Response parseNetworkResponse(NetworkResponse response) { 79 | File downloadFile = null; 80 | try { 81 | byte[] data = response.data; 82 | //convert array of bytes into file 83 | File directory = new File(mDownloadPath); 84 | if (!directory.exists()) { 85 | directory.mkdir(); 86 | } 87 | 88 | String path = mDownloadPath; 89 | if (!TextUtils.isEmpty(mFileName)) { 90 | path = mDownloadPath + File.separator + mFileName; 91 | } 92 | FileOutputStream fileOuputStream = new FileOutputStream(path); 93 | fileOuputStream.write(data); 94 | fileOuputStream.close(); 95 | downloadFile = new File(path); 96 | } catch (FileNotFoundException e) { 97 | e.printStackTrace(); 98 | CLog.e("Download directory %s is not exsit", mDownloadPath); 99 | } catch (IOException e) { 100 | e.printStackTrace(); 101 | } 102 | 103 | return Response.success(downloadFile, response.headers); 104 | } 105 | 106 | 107 | /* 108 | * ========================================================================= 109 | * Inner class 110 | * ========================================================================= 111 | */ 112 | public static class Builder implements net.robinx.lib.http.base.Builder> { 113 | 114 | //Local property 115 | private final String downloadPath; 116 | private final String fileName; 117 | 118 | //HttpRequest property 119 | private RequestParams requestParams; 120 | private Body body; 121 | 122 | //Request property 123 | private RequestCacheOptions requestCacheOptions; 124 | private RetryPolicy retryPolicy; 125 | private String url; 126 | private String cacheKey; 127 | private Object tag; 128 | private Priority priority; 129 | private OnRequestListener onRequestListener; 130 | private int httpMethod; 131 | 132 | public Builder(String downloadPath, String fileName) { 133 | this.downloadPath = downloadPath; 134 | this.fileName = fileName; 135 | } 136 | 137 | public Builder requestParams(RequestParams requestParams) { 138 | this.requestParams = requestParams; 139 | return this; 140 | } 141 | 142 | public Builder body(Body body) { 143 | this.body = body; 144 | return this; 145 | } 146 | 147 | public Builder requestCacheOptions(RequestCacheOptions requestCacheOptions) { 148 | this.requestCacheOptions = requestCacheOptions; 149 | return this; 150 | } 151 | 152 | public Builder retryPolicy(RetryPolicy retryPolicy) { 153 | this.retryPolicy = retryPolicy; 154 | return this; 155 | } 156 | 157 | public Builder url(String url) { 158 | this.url = url; 159 | return this; 160 | } 161 | 162 | public Builder cacheKey(String cacheKey) { 163 | this.cacheKey = cacheKey; 164 | return this; 165 | } 166 | 167 | public Builder tag(Object tag) { 168 | this.tag = tag; 169 | return this; 170 | } 171 | 172 | public Builder priority(Priority priority) { 173 | this.priority = priority; 174 | return this; 175 | } 176 | 177 | public Builder onRequestListener(OnRequestListener onRequestListener) { 178 | this.onRequestListener = onRequestListener; 179 | return this; 180 | } 181 | 182 | public Builder httpMethod(int httpMethod) { 183 | this.httpMethod = httpMethod; 184 | return this; 185 | } 186 | 187 | @Override 188 | public HttpRequest build() { 189 | return new DownloadRequest(this); 190 | } 191 | } 192 | 193 | } 194 | -------------------------------------------------------------------------------- /app/src/main/aidl/com/app/core/example/LogProcessor.java: -------------------------------------------------------------------------------- 1 | package com.app.core.example;/* 2 | * Copyright (C) 2009 Michael Novak 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; either version 2 7 | * of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import android.annotation.SuppressLint; 20 | import android.app.Service; 21 | import android.content.Intent; 22 | import android.os.IBinder; 23 | import android.os.Handler; 24 | import android.os.Message; 25 | import android.util.Log; 26 | 27 | 28 | import java.io.BufferedReader; 29 | import java.io.File; 30 | import java.io.FileWriter; 31 | import java.io.IOException; 32 | import java.io.InputStreamReader; 33 | import java.util.Vector; 34 | 35 | public class LogProcessor extends Service { 36 | 37 | private static Handler mHandler; 38 | private String mFile; 39 | private String mBuffer = "main"; 40 | private Vector mScrollback; 41 | private int mLines; 42 | private int mType; 43 | private String mFilterTag; 44 | private volatile boolean threadKill = false; 45 | private volatile boolean mStatus = false; 46 | public int MAX_LINES = 250; 47 | public static final int MSG_READ_FAIL = 1; 48 | public static final int MSG_LOG_FAIL = 2; 49 | public static final int MSG_NEW_LINE = 3; 50 | public static final int MSG_RESET_LOG = 4; 51 | public static final int MSG_LOG_SAVE = 5; 52 | 53 | @Override 54 | public void onCreate() { 55 | super.onCreate(); 56 | } 57 | 58 | @SuppressWarnings("deprecation") 59 | @Override 60 | public void onStart(Intent intent, int startId) { 61 | super.onStart(intent, startId); 62 | Log.i("Logger", "Logger Service has hit the onStart method."); 63 | } 64 | 65 | Runnable worker = new Runnable() { 66 | public void run() { 67 | runLog(); 68 | mStatus = true; 69 | Log.d("Logger", "status... " + mStatus); 70 | return; 71 | } 72 | }; 73 | 74 | private void runLog() { 75 | Process process = null; 76 | 77 | try { 78 | 79 | if (mType == 0) { 80 | process = Runtime.getRuntime().exec("/system/bin/logcat -b " + mBuffer); 81 | } else if (mType == 1) { 82 | process = Runtime.getRuntime().exec("dmesg -s 1000000"); 83 | } 84 | 85 | } catch (IOException e) { 86 | communicate(MSG_LOG_FAIL); 87 | } 88 | 89 | BufferedReader reader = null; 90 | 91 | try { 92 | reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 93 | 94 | String line; 95 | 96 | while (!killRequested()) { 97 | line = reader.readLine(); 98 | 99 | logLine(line); 100 | 101 | if (mLines == MAX_LINES) { 102 | mScrollback.removeElementAt(0); 103 | } 104 | 105 | mScrollback.add(line); 106 | mLines++; 107 | } 108 | 109 | Log.i("Logger", "Prepping thread for termination"); 110 | reader.close(); 111 | process.destroy(); 112 | process = null; 113 | reader = null; 114 | mScrollback.removeAllElements(); 115 | mScrollback = null; 116 | mLines = 0; 117 | } catch (IOException e) { 118 | communicate(MSG_READ_FAIL); 119 | } 120 | 121 | Log.d("Logger", "Exiting thread..."); 122 | return; 123 | } 124 | 125 | private synchronized void requestKill() { 126 | threadKill = true; 127 | } 128 | 129 | private synchronized boolean killRequested() { 130 | return threadKill; 131 | } 132 | 133 | private void communicate(int msg) { 134 | Message.obtain(mHandler, msg, "error").sendToTarget(); 135 | } 136 | 137 | private void logLine(String line) { 138 | Message.obtain(mHandler, MSG_NEW_LINE, line).sendToTarget(); 139 | } 140 | 141 | public static void setHandler(Handler handler) { 142 | mHandler = handler; 143 | } 144 | 145 | public IBinder onBind(Intent intent) { 146 | return mBinder; 147 | } 148 | 149 | @Override 150 | public boolean onUnbind(Intent intent) { 151 | requestKill(); 152 | stopSelf(); 153 | 154 | return false; 155 | } 156 | 157 | private final ILogProcessor.Stub mBinder = new ILogProcessor.Stub() { 158 | @SuppressLint("DefaultLocale") 159 | public void reset(String buffer) { 160 | requestKill(); 161 | 162 | while (!mStatus) { 163 | try { 164 | Log.d("Logger", "waiting..."); 165 | } catch (Exception e) { 166 | Log.d("Logger", "Woot! obj has been interrupted!"); 167 | } 168 | } 169 | 170 | threadKill = false; 171 | mBuffer = buffer.toLowerCase(); 172 | mLines = 0; 173 | mScrollback = new Vector(); 174 | Thread thr = new Thread(worker); 175 | thr.start(); 176 | } 177 | 178 | public void run(int type) { 179 | mType = type; 180 | mLines = 0; 181 | mScrollback = new Vector(); 182 | Thread thr = new Thread(worker); 183 | thr.start(); 184 | } 185 | 186 | public void restart(int type) { 187 | requestKill(); 188 | 189 | while(!mStatus) { 190 | try { 191 | Log.d("Logger", "waiting..."); 192 | } catch (Exception e) { 193 | Log.d("Logger", "Woot! we have an exception"); 194 | } 195 | } 196 | 197 | threadKill = false; 198 | run(type); 199 | } 200 | 201 | public void stop() { 202 | Log.i("Logger", "stop() method called in service."); 203 | requestKill(); 204 | stopSelf(); 205 | } 206 | 207 | public void write(String file, String tag) { 208 | mFilterTag = tag; 209 | mFile = file; 210 | Thread thr = new Thread(writer); 211 | thr.start(); 212 | } 213 | }; 214 | 215 | Runnable writer = new Runnable() { 216 | public void run() { 217 | writeLog(); 218 | return; 219 | } 220 | }; 221 | 222 | @SuppressLint({ "DefaultLocale", "SdCardPath" }) 223 | private void writeLog() { 224 | 225 | try { 226 | File f = new File("/sdcard/" + mFile); 227 | FileWriter w = new FileWriter(f); 228 | 229 | for (int i = 0; i < mScrollback.size(); i++) { 230 | String line = mScrollback.elementAt(i); 231 | 232 | if (!mFilterTag.equals("")) { 233 | String tag = line.substring(2, line.indexOf("(")); 234 | 235 | if (mFilterTag.toLowerCase().equals(tag.toLowerCase().trim())) { 236 | w.write(line + "\n"); 237 | } 238 | } else { 239 | w.write(mScrollback.elementAt(i) + "\n"); 240 | } 241 | 242 | i++; 243 | } 244 | 245 | if (!mFile.equals("tmp.log")) { 246 | Message.obtain(mHandler, MSG_LOG_SAVE, "saved").sendToTarget(); 247 | } else { 248 | Message.obtain(mHandler, MSG_LOG_SAVE, "attachment").sendToTarget(); 249 | } 250 | 251 | w.close(); 252 | f = null; 253 | } catch (Exception e) { 254 | Log.e("Logger", "Error writing the log to a file. Exception: " + e.toString()); 255 | Message.obtain(mHandler, MSG_LOG_SAVE, "error").sendToTarget(); 256 | } 257 | 258 | return; 259 | } 260 | 261 | } 262 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/ex/hurl/HurlStack.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network.ex.hurl; 2 | 3 | import static net.robinx.lib.http.network.ex.hurl.RequestBodyConstants.HEADER_USER_AGENT; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.net.HttpURLConnection; 8 | import java.net.URL; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.Map.Entry; 13 | 14 | import javax.net.ssl.HttpsURLConnection; 15 | import javax.net.ssl.SSLSocketFactory; 16 | 17 | import net.robinx.lib.http.base.Request; 18 | import net.robinx.lib.http.config.HttpMethod; 19 | import net.robinx.lib.http.network.HTTPSTrustManager; 20 | import net.robinx.lib.http.network.HttpResponse; 21 | import net.robinx.lib.http.network.HttpStack; 22 | import net.robinx.lib.http.utils.CLog; 23 | 24 | import android.text.TextUtils; 25 | 26 | /** 27 | * HttpUrlConnection request body 28 | * 29 | * @author Robin 30 | * @since 2015-07-02 16:40:21 31 | */ 32 | public class HurlStack implements HttpStack { 33 | 34 | private final UrlRewriter mUrlRewriter; 35 | private final SSLSocketFactory mSslSocketFactory; 36 | private String mUserAgent; 37 | 38 | public interface UrlRewriter { 39 | /** 40 | * Rewrite the URL for the request. 41 | */ 42 | public String rewriteUrl(String originalUrl); 43 | } 44 | 45 | public HurlStack() { 46 | this(null); 47 | } 48 | 49 | public HurlStack(UrlRewriter urlRewriter) { 50 | this(urlRewriter, null); 51 | } 52 | 53 | public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) { 54 | mUrlRewriter = urlRewriter; 55 | mSslSocketFactory = sslSocketFactory; 56 | } 57 | 58 | /** 59 | * @param urlRewriter 60 | * Rewriter to use for request URLs 61 | * @param sslSocketFactory 62 | * SSL factory to use for HTTPS connections 63 | * @param userAgent 64 | * User Agent for HTTPS connections 65 | */ 66 | public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory, String userAgent) { 67 | 68 | mUrlRewriter = urlRewriter; 69 | mSslSocketFactory = sslSocketFactory; 70 | mUserAgent = userAgent; 71 | } 72 | 73 | @Override 74 | public HttpResponse performRequest(Request request, Map additionalHeaders) throws IOException { 75 | CLog.w("Current Stack:%s","HTTP_URL_CONNECTION"); 76 | String url = request.getUrl(); 77 | HashMap map = new HashMap(); 78 | map.putAll(request.getHeaders()); 79 | map.putAll(additionalHeaders); 80 | 81 | if (mUrlRewriter != null) { 82 | String rewritten = mUrlRewriter.rewriteUrl(url); 83 | if (rewritten == null) { 84 | throw new IOException("URL blocked by rewriter: " + url); 85 | } 86 | url = rewritten; 87 | } 88 | URL parsedUrl = new URL(url); 89 | HttpURLConnection connection = openConnection(parsedUrl, request); 90 | 91 | if (!TextUtils.isEmpty(mUserAgent)) { 92 | connection.setRequestProperty(HEADER_USER_AGENT, mUserAgent); 93 | } 94 | 95 | for (String headerName : map.keySet()) { 96 | connection.addRequestProperty(headerName, map.get(headerName)); 97 | } 98 | 99 | setConnectionParametersForRequest(connection, request); 100 | 101 | HttpResponse response = responseFromConnection(connection); 102 | return response; 103 | } 104 | 105 | private HttpURLConnection openConnection(URL url, Request request) throws IOException { 106 | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 107 | 108 | // Timeout is actually the timeout of the retry strategy 109 | int timeoutMs = request.getRetryPolicy().getCurrentTimeout(); 110 | connection.setConnectTimeout(timeoutMs); 111 | connection.setReadTimeout(timeoutMs); 112 | connection.setUseCaches(false); 113 | connection.setDoInput(true); 114 | 115 | // getContentLength() 116 | // 为“-1”,在2.2版本以上开启了GZIP压缩,导致长度始终为-1,使用如下一行代码禁止GZIP压缩, 117 | // 但是不推荐,建议与服务器端协商,在请求头中添加content length. 118 | // connection .setRequestProperty("Accept-Encoding", "identity"); 119 | 120 | // use caller-provided custom SslSocketFactory, if any, for HTTPS 121 | if ("https".equals(url.getProtocol())) { 122 | if (mSslSocketFactory != null) { 123 | ((HttpsURLConnection) connection).setSSLSocketFactory(mSslSocketFactory); 124 | } else { 125 | // Trust all certificates 126 | HTTPSTrustManager.allowAllSSL(); 127 | } 128 | } 129 | 130 | return connection; 131 | } 132 | 133 | /** 134 | * Create HttpResponse from a given HttpUrlConnection 135 | */ 136 | private HttpResponse responseFromConnection(HttpURLConnection connection) throws IOException { 137 | HttpResponse response = new HttpResponse(); 138 | int responseCode = connection.getResponseCode(); 139 | if (responseCode == -1) { 140 | throw new IOException("Could not retrieve response code from HttpUrlConnection."); 141 | } 142 | response.setResponseCode(responseCode); 143 | response.setResponseMessage(connection.getResponseMessage()); 144 | // contentStream 145 | InputStream inputStream; 146 | try { 147 | inputStream = connection.getInputStream(); 148 | } catch (IOException ioe) { 149 | inputStream = connection.getErrorStream(); 150 | } 151 | response.setContentStream(inputStream); 152 | 153 | response.setContentLength(connection.getContentLength()); 154 | response.setContentEncoding(connection.getContentEncoding()); 155 | response.setContentType(connection.getContentType()); 156 | // header 157 | Map headerMap = new HashMap(); 158 | for (Entry> header : connection.getHeaderFields().entrySet()) { 159 | if (header.getKey() != null) { 160 | String value = ""; 161 | for (String v : header.getValue()) { 162 | value += (v + "; "); 163 | } 164 | headerMap.put(header.getKey(), value); 165 | response.setHeaders(headerMap); 166 | } 167 | } 168 | return response; 169 | } 170 | 171 | 172 | private static void setConnectionParametersForRequest(HttpURLConnection connection, Request request) 173 | throws IOException { 174 | switch (request.getHttpMethod()) { 175 | case HttpMethod.GET: 176 | connection.setRequestMethod("GET"); 177 | break; 178 | case HttpMethod.DELETE: 179 | connection.setRequestMethod("DELETE"); 180 | break; 181 | case HttpMethod.POST: 182 | connection.setRequestMethod("POST"); 183 | addBodyIfExists(connection, request); 184 | break; 185 | case HttpMethod.PUT: 186 | connection.setRequestMethod("PUT"); 187 | addBodyIfExists(connection, request); 188 | break; 189 | case HttpMethod.HEAD: 190 | connection.setRequestMethod("HEAD"); 191 | break; 192 | case HttpMethod.OPTIONS: 193 | connection.setRequestMethod("OPTIONS"); 194 | break; 195 | case HttpMethod.TRACE: 196 | connection.setRequestMethod("TRACE"); 197 | break; 198 | case HttpMethod.PATCH: 199 | // connection.setRequestMethod("PATCH"); 200 | // If server doesnt support patch uncomment this 201 | connection.setRequestMethod("POST"); 202 | connection.setRequestProperty("X-HTTP-Method-Override", "PATCH"); 203 | addBodyIfExists(connection, request); 204 | break; 205 | default: 206 | throw new IllegalStateException("Unknown method type."); 207 | } 208 | } 209 | 210 | /** 211 | * If there is body then add 212 | */ 213 | private static void addBodyIfExists(HttpURLConnection connection, Request request) throws IOException { 214 | request.buildBody(connection); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/cache/disk/StrictLineReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.robinx.lib.http.cache.disk; 18 | 19 | import java.io.ByteArrayOutputStream; 20 | import java.io.Closeable; 21 | import java.io.EOFException; 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.io.UnsupportedEncodingException; 25 | import java.nio.charset.Charset; 26 | 27 | /** 28 | * Buffers input from an {@link InputStream} for reading lines. 29 | * 30 | *

This class is used for buffered reading of lines. For purposes of this class, a line ends 31 | * with "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated 32 | * line at end of input is invalid and will be ignored, the caller may use {@code 33 | * hasUnterminatedLine()} to detect it after catching the {@code EOFException}. 34 | * 35 | *

This class is intended for reading input that strictly consists of lines, such as line-based 36 | * cache entries or cache journal. Unlike the {@link java.io.BufferedReader} which in conjunction 37 | * with {@link java.io.InputStreamReader} provides similar functionality, this class uses different 38 | * end-of-input reporting and a more restrictive definition of a line. 39 | * 40 | *

This class supports only charsets that encode '\r' and '\n' as a single byte with value 13 41 | * and 10, respectively, and the representation of no other character contains these values. 42 | * We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1. 43 | * The default charset is US_ASCII. 44 | */ 45 | class StrictLineReader implements Closeable { 46 | private static final byte CR = (byte) '\r'; 47 | private static final byte LF = (byte) '\n'; 48 | 49 | private final InputStream in; 50 | private final Charset charset; 51 | 52 | /* 53 | * Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end 54 | * and the data in the range [pos, end) is buffered for reading. At end of input, if there is 55 | * an unterminated line, we set end == -1, otherwise end == pos. If the underlying 56 | * {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1. 57 | */ 58 | private byte[] buf; 59 | private int pos; 60 | private int end; 61 | 62 | /** 63 | * Constructs a new {@code LineReader} with the specified charset and the default capacity. 64 | * 65 | * @param in the {@code InputStream} to read data from. 66 | * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are 67 | * supported. 68 | * @throws NullPointerException if {@code in} or {@code charset} is null. 69 | * @throws IllegalArgumentException if the specified charset is not supported. 70 | */ 71 | public StrictLineReader(InputStream in, Charset charset) { 72 | this(in, 8192, charset); 73 | } 74 | 75 | /** 76 | * Constructs a new {@code LineReader} with the specified capacity and charset. 77 | * 78 | * @param in the {@code InputStream} to read data from. 79 | * @param capacity the capacity of the buffer. 80 | * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are 81 | * supported. 82 | * @throws NullPointerException if {@code in} or {@code charset} is null. 83 | * @throws IllegalArgumentException if {@code capacity} is negative or zero 84 | * or the specified charset is not supported. 85 | */ 86 | public StrictLineReader(InputStream in, int capacity, Charset charset) { 87 | if (in == null || charset == null) { 88 | throw new NullPointerException(); 89 | } 90 | if (capacity < 0) { 91 | throw new IllegalArgumentException("capacity <= 0"); 92 | } 93 | if (!(charset.equals(Util.US_ASCII))) { 94 | throw new IllegalArgumentException("Unsupported encoding"); 95 | } 96 | 97 | this.in = in; 98 | this.charset = charset; 99 | buf = new byte[capacity]; 100 | } 101 | 102 | /** 103 | * Closes the reader by closing the underlying {@code InputStream} and 104 | * marking this reader as closed. 105 | * 106 | * @throws IOException for errors when closing the underlying {@code InputStream}. 107 | */ 108 | public void close() throws IOException { 109 | synchronized (in) { 110 | if (buf != null) { 111 | buf = null; 112 | in.close(); 113 | } 114 | } 115 | } 116 | 117 | /** 118 | * Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"}, 119 | * this end of line marker is not included in the result. 120 | * 121 | * @return the next line from the input. 122 | * @throws IOException for underlying {@code InputStream} errors. 123 | * @throws EOFException for the end of source stream. 124 | */ 125 | public String readLine() throws IOException { 126 | synchronized (in) { 127 | if (buf == null) { 128 | throw new IOException("LineReader is closed"); 129 | } 130 | 131 | // Read more data if we are at the end of the buffered data. 132 | // Though it's an error to read after an exception, we will let {@code fillBuf()} 133 | // throw again if that happens; thus we need to handle end == -1 as well as end == pos. 134 | if (pos >= end) { 135 | fillBuf(); 136 | } 137 | // Try to find LF in the buffered data and return the line if successful. 138 | for (int i = pos; i != end; ++i) { 139 | if (buf[i] == LF) { 140 | int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i; 141 | String res = new String(buf, pos, lineEnd - pos, charset.name()); 142 | pos = i + 1; 143 | return res; 144 | } 145 | } 146 | 147 | // Let's anticipate up to 80 characters on top of those already read. 148 | ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) { 149 | @Override 150 | public String toString() { 151 | int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count; 152 | try { 153 | return new String(buf, 0, length, charset.name()); 154 | } catch (UnsupportedEncodingException e) { 155 | throw new AssertionError(e); // Since we control the charset this will never happen. 156 | } 157 | } 158 | }; 159 | 160 | while (true) { 161 | out.write(buf, pos, end - pos); 162 | // Mark unterminated line in case fillBuf throws EOFException or IOException. 163 | end = -1; 164 | fillBuf(); 165 | // Try to find LF in the buffered data and return the line if successful. 166 | for (int i = pos; i != end; ++i) { 167 | if (buf[i] == LF) { 168 | if (i != pos) { 169 | out.write(buf, pos, i - pos); 170 | } 171 | pos = i + 1; 172 | return out.toString(); 173 | } 174 | } 175 | } 176 | } 177 | } 178 | 179 | public boolean hasUnterminatedLine() { 180 | return end == -1; 181 | } 182 | 183 | /** 184 | * Reads new input data into the buffer. Call only with pos == end or end == -1, 185 | * depending on the desired outcome if the function throws. 186 | */ 187 | private void fillBuf() throws IOException { 188 | int result = in.read(buf, 0, buf.length); 189 | if (result == -1) { 190 | throw new EOFException(); 191 | } 192 | pos = 0; 193 | end = result; 194 | } 195 | } 196 | 197 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/Network.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.net.MalformedURLException; 6 | import java.net.SocketTimeoutException; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import net.robinx.lib.http.base.Request; 11 | import net.robinx.lib.http.response.NetworkResponse; 12 | import net.robinx.lib.http.retry.RetryPolicy; 13 | import net.robinx.lib.http.utils.CLog; 14 | 15 | /** 16 | * The network requests the HttpStack to use the Request client to initiate a network request and returns a NetworkRespond result. 17 | * @author Robin 18 | * @since 2015-07-02 16:16:57 19 | */ 20 | public class Network { 21 | protected final HttpStack mHttpStack; 22 | 23 | public Network(HttpStack httpStack) { 24 | mHttpStack = httpStack; 25 | } 26 | 27 | /** 28 | * Actually executing a request 29 | * 30 | * @param request 31 | * @return A response not to null 32 | * @throws HttpException 33 | */ 34 | public NetworkResponse performRequest(Request request) 35 | throws HttpException { 36 | while (true) { 37 | HttpResponse httpResponse = null; 38 | byte[] responseContents = null; 39 | Map responseHeaders = new HashMap(); 40 | try { 41 | Map headers = new HashMap(); 42 | httpResponse = mHttpStack.performRequest(request, headers); 43 | 44 | int statusCode = httpResponse.getResponseCode(); 45 | responseHeaders = httpResponse.getHeaders(); 46 | if (statusCode == HttpStatus.SC_NOT_MODIFIED) { // 304 47 | return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, 48 | null, 49 | responseHeaders, true); 50 | } 51 | 52 | if (httpResponse.getContentStream() != null) { 53 | responseContents = responseToBytes(request,httpResponse); 54 | } else { 55 | responseContents = new byte[0]; 56 | } 57 | 58 | //instead statusCode > 299 59 | if (statusCode < 200 || statusCode > 405) { 60 | throw new IOException(); 61 | } 62 | return new NetworkResponse(statusCode, responseContents, 63 | responseHeaders, false); 64 | } catch (SocketTimeoutException e) { 65 | if (request.getRequestCacheOptions().isRetryWhenRequestFailed()) { 66 | retryOnException( request, new HttpException("socket timeout",HttpError.ERROR_SOCKET_TIMEOUT)); 67 | }else { 68 | throw new HttpException("socket timeout",HttpError.ERROR_SOCKET_TIMEOUT); 69 | } 70 | } 71 | /*catch (ConnectTimeoutException e) { 72 | if (request.getCacheConfig().isRetryWhenRequestFailed()) { 73 | retryOnException( request, new HttpException("connect timeout")); 74 | }else { 75 | throw new HttpException(new SocketTimeoutException("connect timeout")); 76 | } 77 | } */ 78 | catch (MalformedURLException e) { 79 | throw new RuntimeException("Bad URL " + request.getUrl(), e); 80 | } catch (IOException e) { 81 | int statusCode = 0; 82 | //NetworkResponse networkResponse = null; 83 | if (httpResponse != null) { 84 | statusCode = httpResponse.getResponseCode(); 85 | } else { 86 | //throw new HttpException("NoConnection error", e); 87 | throw new HttpException("NoConnection error", HttpError.ERROR_NO_CONNECTION); 88 | //retryOnException( request, new HttpException("NoConnection error",e)); 89 | } 90 | CLog.d("Unexpected response code %s for: %s",statusCode,request.getUrl()); 91 | if (responseContents != null) { 92 | //networkResponse = new NetworkResponse(statusCode,responseContents, responseHeaders, false); 93 | if (statusCode == HttpStatus.SC_UNAUTHORIZED|| statusCode == HttpStatus.SC_FORBIDDEN) { 94 | if (request.getRequestCacheOptions().isRetryWhenRequestFailed()) { 95 | retryOnException( request, new HttpException("auth error",HttpError.ERROR_UNAUTHORIZED)); 96 | } else { 97 | throw new HttpException("auth error",HttpError.ERROR_UNAUTHORIZED); 98 | } 99 | } else if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) { 100 | if (request.getRequestCacheOptions().isRetryWhenRequestFailed()) { 101 | retryOnException( request, new HttpException("redirect error",HttpError.ERROR_REDIRECT)); 102 | }else { 103 | throw new HttpException("redirect error",HttpError.ERROR_REDIRECT); 104 | } 105 | 106 | } else { 107 | throw new HttpException("server error, Only throw ServerError for 5xx status codes.",HttpError.ERROR_SERVER); 108 | } 109 | } else { 110 | throw new HttpException("responseContents is null",HttpError.ERROR_RESPONSE_NULL); 111 | } 112 | } 113 | } 114 | } 115 | 116 | 117 | /** 118 | * Convert HttpResponse to byte[] 119 | * 120 | * @param request 121 | * @param response 122 | * @return 123 | * @throws IOException 124 | * @throws HttpException 125 | */ 126 | private byte[] responseToBytes(Request request,HttpResponse response) throws IOException, 127 | HttpException { 128 | PoolingByteArrayOutputStream bytes = new PoolingByteArrayOutputStream( 129 | ByteArrayPool.get(), (int) response.getContentLength()); 130 | byte[] buffer = null; 131 | long totalSize = (int) response.getContentLength(); 132 | try { 133 | InputStream in =response.getContentStream(); 134 | if (in == null) { 135 | throw new HttpException("server error",HttpError.ERROR_SERVER); 136 | } 137 | buffer = ByteArrayPool.get().getBuf(1024); 138 | int count; 139 | int transferredBytesSize = 0; 140 | while ((count = in.read(buffer)) != -1) { 141 | bytes.write(buffer, 0, count); 142 | transferredBytesSize += count; 143 | //request.getRequestQueue().getDelivery().postRequestDownloadProgress(request,transferredBytesSize, totalSize); 144 | request.onRequestDownloadProgress(transferredBytesSize, totalSize); 145 | } 146 | return bytes.toByteArray(); 147 | } finally { 148 | try { 149 | response.getContentStream().close(); 150 | } catch (IOException e) { 151 | CLog.d("Error occured when calling consumingContent"); 152 | } 153 | ByteArrayPool.get().returnBuf(buffer); 154 | bytes.close(); 155 | } 156 | } 157 | 158 | /** 159 | * When an exception occurs to try again 160 | * @param request 161 | * @param exception 162 | * @return 163 | * @throws HttpException 164 | */ 165 | private static RetryPolicy retryOnException( Request request,HttpException exception) throws HttpException { 166 | RetryPolicy retryPolicy = request.getRetryPolicy(); 167 | try { 168 | retryPolicy.retry(exception); 169 | } catch (HttpException e) { 170 | throw e; 171 | } 172 | 173 | /*Distribution of retry event*/ 174 | request.getRequestQueue().getDelivery().postRequestRetry(request, retryPolicy.getCurrentRetryCount() ,exception); 175 | 176 | return retryPolicy; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /lib.http/src/main/java/net/robinx/lib/http/network/ex/hurl/HurlRequestBody.java: -------------------------------------------------------------------------------- 1 | package net.robinx.lib.http.network.ex.hurl; 2 | 3 | import net.robinx.lib.http.callback.BytesWriteListener; 4 | import net.robinx.lib.http.network.ex.Body; 5 | import net.robinx.lib.http.network.ex.RequestParams; 6 | import net.robinx.lib.http.utils.CLog; 7 | 8 | import java.io.BufferedInputStream; 9 | import java.io.File; 10 | import java.io.FileInputStream; 11 | import java.io.IOException; 12 | import java.io.OutputStream; 13 | import java.io.OutputStreamWriter; 14 | import java.io.PrintWriter; 15 | import java.net.HttpURLConnection; 16 | 17 | /** 18 | * Can submit key/value pair, files, key/value pair and files, JSON, 19 | * If the request parameter contains a JSON parameters, send JSON parameters, 20 | * this time even contain key/value pair or file parameter will not be sent 21 | * 22 | * @author Robin 23 | * @since 2016-01-07 18:53:19 24 | */ 25 | public class HurlRequestBody implements Body { 26 | 27 | private boolean isFixedStreamingMode; 28 | 29 | private BytesWriteListener mBytesWriteListener; 30 | 31 | /*====================================================== 32 | * Override Super 33 | *====================================================== 34 | */ 35 | 36 | public String buildBodyContentType(RequestParams params, int curTime) { 37 | if (params.hasJsonInParams()) { 38 | return String.format("application/json; charset=%s", "utf-8"); 39 | } 40 | 41 | return String.format(RequestBodyConstants.CONTENT_TYPE_MULTIPART, "utf-8", curTime); 42 | } 43 | 44 | @Override 45 | public Object buildBody(RequestParams params, Object... args) { 46 | HttpURLConnection connection = (HttpURLConnection) args[0]; 47 | connection.setDoOutput(true); 48 | final String charset = "utf-8"; 49 | final int curTime = (int) (System.currentTimeMillis() / 1000); 50 | final String boundary = RequestBodyConstants.BOUNDARY_PREFIX + curTime; 51 | connection.setRequestProperty(RequestBodyConstants.HEADER_CONTENT_TYPE, buildBodyContentType(params, curTime)); 52 | 53 | if (isFixedStreamingMode()) { 54 | int contentLength = RequestBodyConstants.getContentLength(boundary, params); 55 | connection.setFixedLengthStreamingMode(contentLength); 56 | } else { 57 | connection.setChunkedStreamingMode(0); 58 | } 59 | 60 | // Write parameters 61 | PrintWriter writer = null; 62 | try { 63 | OutputStream out = connection.getOutputStream(); 64 | writer = new PrintWriter(new OutputStreamWriter(out, charset), true); 65 | 66 | if (params.hasJsonInParams()) { 67 | // append json 68 | writer.append(params.buildJsonParams()).flush(); 69 | 70 | } else { 71 | 72 | writeMultipartToOutputStream(params, boundary, writer, out); 73 | 74 | // End of multipart/form-data. 75 | writer.append(boundary + RequestBodyConstants.BOUNDARY_PREFIX).append(RequestBodyConstants.CRLF).flush(); 76 | } 77 | 78 | } catch (Exception e) { 79 | e.printStackTrace(); 80 | 81 | } finally { 82 | if (writer != null) { 83 | writer.close(); 84 | } 85 | } 86 | 87 | return null; 88 | } 89 | 90 | private void writeMultipartToOutputStream(RequestParams params, String boundary, PrintWriter writer, OutputStream out) throws IOException { 91 | int currentFileIndex = 1; 92 | for (String key : params.keySet()) { 93 | Object value = params.get(key); 94 | if (value == null) { 95 | continue; 96 | } 97 | 98 | if (value instanceof File) { // add file 99 | currentFileIndex = writeFileToOutputStream(boundary, writer, out, currentFileIndex, key, (File) value); 100 | } else { // add field 101 | writeFieldToOutputStream(boundary, writer, key, value); 102 | } 103 | } 104 | } 105 | 106 | private void writeFieldToOutputStream(String boundary, PrintWriter writer, String key, Object value) { 107 | String param = String.valueOf(value); 108 | 109 | writer.append(boundary).append(RequestBodyConstants.CRLF) 110 | .append(String.format(RequestBodyConstants.HEADER_CONTENT_DISPOSITION + RequestBodyConstants.COLON_SPACE + RequestBodyConstants.FORM_DATA, key)).append(RequestBodyConstants.CRLF) 111 | .append(RequestBodyConstants.HEADER_CONTENT_TYPE + RequestBodyConstants.COLON_SPACE + RequestBodyConstants.CONTENT_TYPE_TEXT) 112 | .append(RequestBodyConstants.CRLF).append(RequestBodyConstants.CRLF) 113 | .append(param).append(RequestBodyConstants.CRLF).flush(); 114 | } 115 | 116 | private int writeFileToOutputStream(String boundary, PrintWriter writer, OutputStream out, int currentFileIndex, String key, File value) throws IOException { 117 | File file = value; 118 | 119 | if (!file.exists()) { 120 | CLog.e("File not found: %s", file.getAbsolutePath()); 121 | throw new IOException(String.format("File not found: %s", file.getAbsolutePath())); 122 | } 123 | 124 | if (file.isDirectory()) { 125 | CLog.e("File is a directory: %s", file.getAbsolutePath()); 126 | throw new IOException(String.format("File is a directory: %s", file.getAbsolutePath())); 127 | } 128 | 129 | writer.append(boundary).append(RequestBodyConstants.CRLF) 130 | .append(String.format( 131 | RequestBodyConstants.HEADER_CONTENT_DISPOSITION + RequestBodyConstants.COLON_SPACE + RequestBodyConstants.FORM_DATA + RequestBodyConstants.SEMICOLON_SPACE + RequestBodyConstants.FILENAME, key, 132 | file.getName())) 133 | .append(RequestBodyConstants.CRLF).append(RequestBodyConstants.HEADER_CONTENT_TYPE + RequestBodyConstants.COLON_SPACE + RequestBodyConstants.CONTENT_TYPE_OCTET_STREAM).append(RequestBodyConstants.CRLF) 134 | .append(RequestBodyConstants.HEADER_CONTENT_TRANSFER_ENCODING + RequestBodyConstants.COLON_SPACE + RequestBodyConstants.BINARY).append(RequestBodyConstants.CRLF).append(RequestBodyConstants.CRLF) 135 | .flush(); 136 | 137 | BufferedInputStream input = null; 138 | try { 139 | FileInputStream fis = new FileInputStream(file); 140 | int transferredBytesSize = 0; 141 | int totalSize = (int) file.length(); 142 | input = new BufferedInputStream(fis); 143 | int bufferLength = 0; 144 | 145 | byte[] buffer = new byte[1024]; 146 | while ((bufferLength = input.read(buffer)) > 0) { 147 | CLog.w(" thread name : %s", Thread.currentThread().getName()); 148 | out.write(buffer, 0, bufferLength); 149 | transferredBytesSize += bufferLength; 150 | if (mBytesWriteListener != null) { 151 | mBytesWriteListener.onWrite(transferredBytesSize, totalSize, currentFileIndex, file); 152 | } 153 | 154 | } 155 | // Important! Output cannot be closed. Close of writer will 156 | // close output as well. 157 | out.flush(); 158 | } finally { 159 | if (input != null) 160 | try { 161 | input.close(); 162 | } catch (IOException ex) { 163 | ex.printStackTrace(); 164 | } 165 | } 166 | // CRLF is important! It indicates end of binary boundary. 167 | writer.append(RequestBodyConstants.CRLF).flush(); 168 | 169 | currentFileIndex++; 170 | return currentFileIndex; 171 | } 172 | 173 | public boolean isFixedStreamingMode() { 174 | return isFixedStreamingMode; 175 | } 176 | 177 | public void setFixedStreamingMode(boolean isFixedStreamingMode) { 178 | this.isFixedStreamingMode = isFixedStreamingMode; 179 | } 180 | 181 | @Override 182 | public void setBytesWriteListener(BytesWriteListener listener) { 183 | this.mBytesWriteListener = listener; 184 | } 185 | } 186 | --------------------------------------------------------------------------------