├── HttpClientLib
├── .gitignore
├── src
│ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── naver
│ │ │ └── httpclientlib
│ │ │ ├── Interceptor.java
│ │ │ ├── annotation
│ │ │ ├── Default.java
│ │ │ ├── URL.java
│ │ │ ├── FormUrlEncoded.java
│ │ │ ├── HeaderMap.java
│ │ │ ├── Header.java
│ │ │ ├── Headers.java
│ │ │ ├── PathParam.java
│ │ │ ├── FieldMap.java
│ │ │ ├── RequestBody.java
│ │ │ ├── Field.java
│ │ │ ├── DynamicURL.java
│ │ │ ├── Query.java
│ │ │ ├── Queries.java
│ │ │ ├── QueryMap.java
│ │ │ └── RequestMapping.java
│ │ │ ├── CallBack.java
│ │ │ ├── CallTask.java
│ │ │ ├── Converter.java
│ │ │ ├── RequestMethod.java
│ │ │ ├── HttpInvocationHandler.java
│ │ │ ├── Request.java
│ │ │ ├── GsonConverterFactory.java
│ │ │ ├── Response.java
│ │ │ ├── HttpMethod.java
│ │ │ ├── InterceptorChain.java
│ │ │ ├── GsonConverter.java
│ │ │ ├── RealCallTask.java
│ │ │ ├── Utils.java
│ │ │ ├── ParamManager.java
│ │ │ ├── HttpClient.java
│ │ │ └── RequestFactory.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── naver
│ │ └── httpclientlib
│ │ ├── mock
│ │ ├── Geo.java
│ │ ├── Company.java
│ │ ├── SkipPost.java
│ │ ├── Comment.java
│ │ ├── Post.java
│ │ ├── Address.java
│ │ └── User.java
│ │ ├── mockInterface
│ │ ├── InvalidHttpService.java
│ │ └── ValidHttpService.java
│ │ ├── ResponseTest.java
│ │ ├── ParamManagerTest.java
│ │ ├── InvalidServiceTest.java
│ │ ├── HttpClientTest.java
│ │ ├── AsyncTest.java
│ │ ├── ValidServiceTest.java
│ │ └── InterceptorTest.java
└── build.gradle
├── HttpClientLib-demo
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── values
│ │ │ ├── colors.xml
│ │ │ ├── styles.xml
│ │ │ └── strings.xml
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── layout
│ │ │ ├── activity_main.xml
│ │ │ ├── fragment_log.xml
│ │ │ └── fragment_httpclient_config.xml
│ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ └── drawable
│ │ │ └── ic_launcher_background.xml
│ │ ├── java
│ │ └── com
│ │ │ └── naver
│ │ │ └── httpclienttest
│ │ │ ├── DefaultTimeout.java
│ │ │ ├── HttpMethod.java
│ │ │ ├── DemoApplication.java
│ │ │ ├── MainActivity.java
│ │ │ ├── data
│ │ │ └── Post.java
│ │ │ ├── HttpService.java
│ │ │ ├── LogFragment.java
│ │ │ ├── HttpClientConfigFragment.java
│ │ │ └── MainFragment.java
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── .gitignore
├── gradle.properties
├── README.md
├── gradlew.bat
└── gradlew
/HttpClientLib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':HttpClientLib-demo', ':HttpClientLib'
2 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimReady/Http-Client-Lib/HEAD/HttpClientLib-demo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimReady/Http-Client-Lib/HEAD/HttpClientLib-demo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimReady/Http-Client-Lib/HEAD/HttpClientLib-demo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimReady/Http-Client-Lib/HEAD/HttpClientLib-demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimReady/Http-Client-Lib/HEAD/HttpClientLib-demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimReady/Http-Client-Lib/HEAD/HttpClientLib-demo/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimReady/Http-Client-Lib/HEAD/HttpClientLib-demo/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimReady/Http-Client-Lib/HEAD/HttpClientLib-demo/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimReady/Http-Client-Lib/HEAD/HttpClientLib-demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KimReady/Http-Client-Lib/HEAD/HttpClientLib-demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 | /app/
10 | /HttpClientLib/local.properties
11 | /HttpClientLib/deploy.settings
12 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/Interceptor.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import java.io.IOException;
4 |
5 | public interface Interceptor {
6 | Response intercept(InterceptorChain chain) throws IOException;
7 | }
8 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/Default.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | class Default {
4 | private Default(){}
5 |
6 | static final String ENCODE = "UTF-8";
7 | static final String RELATIVE_URL = "/";
8 | }
9 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/CallBack.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import java.io.IOException;
4 |
5 | public interface CallBack {
6 | void onResponse(Response response) throws IOException;
7 | void onFailure(IOException e);
8 | }
9 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/CallTask.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import java.io.IOException;
4 |
5 | public interface CallTask {
6 |
7 | Response execute() throws IOException;
8 |
9 | void enqueue(CallBack callback);
10 |
11 | void cancel();
12 |
13 | boolean isCanceled();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/java/com/naver/httpclienttest/DefaultTimeout.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclienttest;
2 |
3 | class DefaultTimeout {
4 | private DefaultTimeout(){}
5 |
6 | static final long CALL_TIMEOUT = 0L;
7 | static final long CONNECT_TIMEOUT = 10000L;
8 | static final long READ_TIMEOUT = 10000L;
9 | static final long WRITE_TIMEOUT = 10000L;
10 | }
11 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/URL.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.PARAMETER;
7 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
8 |
9 | @Target(PARAMETER)
10 | @Retention(RUNTIME)
11 | public @interface URL {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/java/com/naver/httpclienttest/HttpMethod.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclienttest;
2 |
3 | enum HttpMethod {
4 | GET("GET"),
5 | POST("POST"),
6 | PUT("PUT"),
7 | DELETE("DELETE"),
8 | HEAD("HEAD");
9 |
10 | String name;
11 |
12 | HttpMethod(String method) {
13 | name = method;
14 | }
15 |
16 | String getName() {
17 | return name;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/FormUrlEncoded.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.METHOD;
7 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
8 |
9 | @Target(METHOD)
10 | @Retention(RUNTIME)
11 | public @interface FormUrlEncoded {
12 | }
13 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/HeaderMap.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.PARAMETER;
7 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
8 |
9 | @Target(PARAMETER)
10 | @Retention(RUNTIME)
11 | public @interface HeaderMap {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/Converter.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import java.io.IOException;
4 |
5 | import okhttp3.MediaType;
6 |
7 | interface Converter {
8 |
9 | okhttp3.RequestBody convertRequestBody(MediaType contentType, RequestType requestObj) throws IOException;
10 |
11 | ReturnType convertResponseBody(okhttp3.ResponseBody responseBody) throws IOException;
12 | }
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/Header.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.PARAMETER;
7 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
8 |
9 | @Target(PARAMETER)
10 | @Retention(RUNTIME)
11 | public @interface Header {
12 | String value();
13 | }
14 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/Headers.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.METHOD;
7 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
8 |
9 | @Target(METHOD)
10 | @Retention(RUNTIME)
11 | public @interface Headers {
12 | String[] value();
13 | }
14 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/RequestMethod.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | public enum RequestMethod {
4 | GET("GET"),
5 | POST("POST"),
6 | PUT("PUT"),
7 | DELETE("DELETE"),
8 | HEAD("HEAD");
9 |
10 | private String name;
11 |
12 | RequestMethod(String name) {
13 | this.name = name;
14 | }
15 |
16 | public String getName() {
17 | return name;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/PathParam.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.PARAMETER;
7 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
8 |
9 | @Target(PARAMETER)
10 | @Retention(RUNTIME)
11 | public @interface PathParam {
12 | String value();
13 | }
14 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/FieldMap.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.PARAMETER;
7 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
8 |
9 | @Target(PARAMETER)
10 | @Retention(RUNTIME)
11 | public @interface FieldMap {
12 | boolean encoded() default false;
13 | }
14 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/RequestBody.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.PARAMETER;
7 | import static java.lang.annotation.ElementType.TYPE;
8 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
9 |
10 | @Target(PARAMETER)
11 | @Retention(RUNTIME)
12 | public @interface RequestBody {
13 | }
14 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/Field.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.PARAMETER;
7 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
8 |
9 | @Target(PARAMETER)
10 | @Retention(RUNTIME)
11 | public @interface Field {
12 | String value();
13 |
14 | boolean encoded() default false;
15 | }
16 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/DynamicURL.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import com.naver.httpclientlib.RequestMethod;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.Target;
7 |
8 | import static java.lang.annotation.ElementType.METHOD;
9 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
10 |
11 | @Target(METHOD)
12 | @Retention(RUNTIME)
13 | public @interface DynamicURL {
14 | RequestMethod method() default RequestMethod.GET;
15 | }
16 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/Query.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.PARAMETER;
7 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
8 |
9 | @Target(PARAMETER)
10 | @Retention(RUNTIME)
11 | public @interface Query {
12 | String value();
13 |
14 | boolean encoded() default false;
15 | String encodeType() default Default.ENCODE;
16 | }
17 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/Queries.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.Target;
5 |
6 | import static java.lang.annotation.ElementType.PARAMETER;
7 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
8 |
9 | @Target(PARAMETER)
10 | @Retention(RUNTIME)
11 | public @interface Queries {
12 | String value();
13 |
14 | boolean encoded() default false;
15 | String encodeType() default Default.ENCODE;
16 | }
17 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/QueryMap.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 |
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.Target;
6 |
7 | import static java.lang.annotation.ElementType.FIELD;
8 | import static java.lang.annotation.ElementType.PARAMETER;
9 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
10 |
11 | @Target(PARAMETER)
12 | @Retention(RUNTIME)
13 | public @interface QueryMap {
14 | boolean encoded() default false;
15 | String encodeType() default Default.ENCODE;
16 | }
17 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/annotation/RequestMapping.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.annotation;
2 |
3 | import com.naver.httpclientlib.RequestMethod;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.Target;
7 |
8 | import static java.lang.annotation.ElementType.METHOD;
9 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
10 |
11 | @Target(METHOD)
12 | @Retention(RUNTIME)
13 | public @interface RequestMapping {
14 |
15 | String value() default Default.RELATIVE_URL;
16 | RequestMethod method() default RequestMethod.GET;
17 | }
18 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/java/com/naver/httpclienttest/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclienttest;
2 |
3 | import android.app.Application;
4 |
5 | import com.naver.ers.CustomData;
6 | import com.naver.ers.Reporter;
7 |
8 | import java.util.Date;
9 |
10 | public class DemoApplication extends Application {
11 | @Override
12 | public void onCreate() {
13 | super.onCreate();
14 |
15 | CustomData.Builder customDataBuilder = new CustomData.Builder()
16 | .putData("App Start time", new Date().toString());
17 | Reporter.setCustomData(customDataBuilder.build());
18 | Reporter.register(this);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/mock/Geo.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.mock;
2 |
3 | public class Geo {
4 | double lat;
5 | double lng;
6 |
7 | public Geo(double lat, double lng) {
8 | this.lat = lat;
9 | this.lng = lng;
10 | }
11 |
12 | public double getLat() {
13 | return lat;
14 | }
15 |
16 | public void setLat(double lat) {
17 | this.lat = lat;
18 | }
19 |
20 | public double getLng() {
21 | return lng;
22 | }
23 |
24 | public void setLng(double lng) {
25 | this.lng = lng;
26 | }
27 |
28 | @Override
29 | public String toString() {
30 | return "Geo{" +
31 | "lat=" + lat +
32 | ", lng=" + lng +
33 | '}';
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/HttpInvocationHandler.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import java.lang.reflect.InvocationHandler;
4 | import java.lang.reflect.Method;
5 |
6 | class HttpInvocationHandler implements InvocationHandler {
7 | private final HttpClient httpClient;
8 |
9 | HttpInvocationHandler(HttpClient httpClient) {
10 | this.httpClient = httpClient;
11 | }
12 |
13 | @Override
14 | public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
15 |
16 | // Object class에서 정의된 메소드일 경우 해당 메소드 그대로 실행
17 | if(method.getDeclaringClass() == Object.class) {
18 | return method.invoke(this, objects);
19 | }
20 |
21 | Utils.checkSupportedMethod(method);
22 |
23 | return HttpMethod.of(httpClient, method, objects).invoke();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/java/com/naver/httpclienttest/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclienttest;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 | import androidx.fragment.app.FragmentManager;
5 | import androidx.fragment.app.FragmentTransaction;
6 |
7 | import android.os.Bundle;
8 |
9 | import com.naver.httpclientsdk.R;
10 |
11 | public class MainActivity extends AppCompatActivity {
12 |
13 | @Override
14 | protected void onCreate(Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_main);
17 |
18 | FragmentManager fragmentManager = getSupportFragmentManager();
19 | FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
20 |
21 | MainFragment mainFragment = new MainFragment();
22 | fragmentTransaction.add(R.id.fragment_container, mainFragment);
23 | fragmentTransaction.commit();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/Request.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | public class Request {
4 | private final String url;
5 | private final String method;
6 | private final String headers;
7 | private final String contentType;
8 |
9 | public Request(okhttp3.Request request) {
10 | url = request.url().toString();
11 | method = request.method();
12 | headers = request.headers().toString();
13 | contentType = (request.body() != null && request.body().contentType() != null) ?
14 | request.body().contentType().toString()
15 | : null;
16 | }
17 |
18 | public String getUrl() {
19 | return url;
20 | }
21 |
22 | public String getMethod() {
23 | return method;
24 | }
25 |
26 | public String getHeaders() {
27 | return headers;
28 | }
29 |
30 | public String getContentType() {
31 | return contentType;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/GsonConverterFactory.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.GsonBuilder;
5 | import com.google.gson.TypeAdapter;
6 | import com.google.gson.reflect.TypeToken;
7 |
8 | import java.lang.reflect.Type;
9 |
10 | final class GsonConverterFactory {
11 | private final Gson gson;
12 |
13 | public static GsonConverterFactory create(GsonBuilder gsonBuilder) {
14 | return new GsonConverterFactory(gsonBuilder);
15 | }
16 |
17 | private GsonConverterFactory(GsonBuilder gsonBuilder) {
18 | this.gson = gsonBuilder.create();
19 | }
20 |
21 | Converter, ?> converter(Type type) {
22 | if(type == String.class) {
23 | return new GsonConverter<>(gson);
24 | } else {
25 | TypeAdapter> typeAdapter = gson.getAdapter(TypeToken.get(type));
26 | return new GsonConverter<>(gson, typeAdapter);
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/HttpClientLib-demo/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 | buildToolsVersion "29.0.0"
6 | defaultConfig {
7 | applicationId "com.naver.httpclienttest"
8 | minSdkVersion 16
9 | targetSdkVersion 28
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | compileOptions {
20 | sourceCompatibility JavaVersion.VERSION_1_7
21 | targetCompatibility JavaVersion.VERSION_1_7
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(dir: 'libs', include: ['*.jar'])
27 | implementation 'androidx.appcompat:appcompat:1.0.2'
28 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
29 | implementation project(":HttpClientLib")
30 | implementation 'com.naver.ers:ErrorReportingSdk:0.1.3'
31 | }
32 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/mock/Company.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.mock;
2 |
3 | public class Company {
4 | String name;
5 | String catchPhrase;
6 | String bs;
7 |
8 | public Company(String name, String catchPhrase, String bs) {
9 | this.name = name;
10 | this.catchPhrase = catchPhrase;
11 | this.bs = bs;
12 | }
13 |
14 | public String getName() {
15 | return name;
16 | }
17 |
18 | public void setName(String name) {
19 | this.name = name;
20 | }
21 |
22 | public String getCatchPhrase() {
23 | return catchPhrase;
24 | }
25 |
26 | public void setCatchPhrase(String catchPhrase) {
27 | this.catchPhrase = catchPhrase;
28 | }
29 |
30 | public String getBs() {
31 | return bs;
32 | }
33 |
34 | public void setBs(String bs) {
35 | this.bs = bs;
36 | }
37 |
38 | @Override
39 | public String toString() {
40 | return "Company{" +
41 | "name='" + name + '\'' +
42 | ", catchPhrase='" + catchPhrase + '\'' +
43 | ", bs='" + bs + '\'' +
44 | '}';
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/java/com/naver/httpclienttest/data/Post.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclienttest.data;
2 |
3 | public class Post {
4 | int userId;
5 | int id;
6 | String title;
7 | String body;
8 |
9 | public Post(int userId, int id, String title, String body) {
10 | this.userId = userId;
11 | this.id = id;
12 | this.title = title;
13 | this.body = body;
14 | }
15 |
16 | public int getUserId() {
17 | return userId;
18 | }
19 |
20 | public void setUserId(int userId) {
21 | this.userId = userId;
22 | }
23 |
24 | public int getId() {
25 | return id;
26 | }
27 |
28 | public void setId(int id) {
29 | this.id = id;
30 | }
31 |
32 | public String getTitle() {
33 | return title;
34 | }
35 |
36 | public void setTitle(String title) {
37 | this.title = title;
38 | }
39 |
40 | public String getBody() {
41 | return body;
42 | }
43 |
44 | public void setBody(String body) {
45 | this.body = body;
46 | }
47 |
48 | @Override
49 | public String toString() {
50 | return "Post{" +
51 | "userId=" + userId +
52 | ", id=" + id +
53 | ", title='" + title + '\'' +
54 | ", body='" + body + '\'' +
55 | '}';
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/mock/SkipPost.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.mock;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | public class SkipPost {
6 | int userId;
7 | int id;
8 | @SerializedName(value="title")
9 | String titles;
10 | String body;
11 |
12 | public SkipPost(int userId, int id, String titles, String body) {
13 | this.userId = userId;
14 | this.id = id;
15 | this.titles = titles;
16 | this.body = body;
17 | }
18 |
19 | public int getUserId() {
20 | return userId;
21 | }
22 |
23 | public void setUserId(int userId) {
24 | this.userId = userId;
25 | }
26 |
27 | public int getId() {
28 | return id;
29 | }
30 |
31 | public void setId(int id) {
32 | this.id = id;
33 | }
34 |
35 | public String getTitle() {
36 | return titles;
37 | }
38 |
39 | public void setTitle(String title) {
40 | this.titles = title;
41 | }
42 |
43 | public String getBody() {
44 | return body;
45 | }
46 |
47 | public void setBody(String body) {
48 | this.body = body;
49 | }
50 |
51 | @Override
52 | public String toString() {
53 | return "SkipPost{" +
54 | "userId=" + userId +
55 | ", id=" + id +
56 | ", title='" + titles + '\'' +
57 | ", body='" + body + '\'' +
58 | '}';
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/Response.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import java.io.IOException;
4 | import java.util.List;
5 |
6 | public final class Response {
7 | private final okhttp3.Response rawResponse;
8 | private final Request request;
9 | private final T body;
10 |
11 | Response(okhttp3.Response rawResponse, Converter converter) throws IOException {
12 | this.rawResponse = rawResponse;
13 | this.request = new Request(rawResponse.request());
14 | body = converter != null ? converter.convertResponseBody(rawResponse.body()) : null;
15 | }
16 |
17 | public Request request() {
18 | return request;
19 | }
20 |
21 | public String header(String name) {
22 | return rawResponse.header(name);
23 | }
24 |
25 | public String header(String name, String defaultValue) {
26 | return rawResponse.header(name, defaultValue);
27 | }
28 |
29 | public List headers(String name) {
30 | return rawResponse.headers(name);
31 | }
32 |
33 | public T body() {
34 | return body;
35 | }
36 |
37 | public int code() {
38 | return rawResponse.code();
39 | }
40 |
41 | public boolean isSuccessful() {
42 | return rawResponse.isSuccessful();
43 | }
44 |
45 | public boolean isRedirect() {
46 | return rawResponse.isRedirect();
47 | }
48 |
49 | okhttp3.Response getRawResponse() {
50 | return rawResponse;
51 | }
52 |
53 | public void close() {
54 | rawResponse.close();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/mock/Comment.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.mock;
2 |
3 | public class Comment {
4 | int postId;
5 | int id;
6 | String name;
7 | String email;
8 | String body;
9 |
10 | public Comment(int postId, int id, String name, String email, String body) {
11 | this.postId = postId;
12 | this.id = id;
13 | this.name = name;
14 | this.email = email;
15 | this.body = body;
16 | }
17 |
18 | public int getPostId() {
19 | return postId;
20 | }
21 |
22 | public void setPostId(int postId) {
23 | this.postId = postId;
24 | }
25 |
26 | public int getId() {
27 | return id;
28 | }
29 |
30 | public void setId(int id) {
31 | this.id = id;
32 | }
33 |
34 | public String getName() {
35 | return name;
36 | }
37 |
38 | public void setName(String name) {
39 | this.name = name;
40 | }
41 |
42 | public String getEmail() {
43 | return email;
44 | }
45 |
46 | public void setEmail(String email) {
47 | this.email = email;
48 | }
49 |
50 | public String getBody() {
51 | return body;
52 | }
53 |
54 | public void setBody(String body) {
55 | this.body = body;
56 | }
57 |
58 | @Override
59 | public String toString() {
60 | return "Comment{" +
61 | "postId=" + postId +
62 | ", id=" + id +
63 | ", name='" + name + '\'' +
64 | ", email='" + email + '\'' +
65 | ", body='" + body + '\'' +
66 | '}';
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/mock/Post.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.mock;
2 |
3 | public class Post {
4 | int userId;
5 | int id;
6 | String title;
7 | String body;
8 | int like; // not included in response data
9 |
10 | public Post(int userId, int id, String title, String body, int like) {
11 | this.userId = userId;
12 | this.id = id;
13 | this.title = title;
14 | this.body = body;
15 | this.like = like;
16 | }
17 |
18 | public int getUserId() {
19 | return userId;
20 | }
21 |
22 | public void setUserId(int userId) {
23 | this.userId = userId;
24 | }
25 |
26 | public int getId() {
27 | return id;
28 | }
29 |
30 | public void setId(int id) {
31 | this.id = id;
32 | }
33 |
34 | public String getTitle() {
35 | return title;
36 | }
37 |
38 | public void setTitle(String title) {
39 | this.title = title;
40 | }
41 |
42 | public String getBody() {
43 | return body;
44 | }
45 |
46 | public void setBody(String body) {
47 | this.body = body;
48 | }
49 |
50 | public int getLike() {
51 | return like;
52 | }
53 |
54 | public void setLike(int like) {
55 | this.like = like;
56 | }
57 |
58 | @Override
59 | public String toString() {
60 | return "Post{" +
61 | "userId=" + userId +
62 | ", id=" + id +
63 | ", title='" + title + '\'' +
64 | ", body='" + body + '\'' +
65 | ", like=" + like +
66 | '}';
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/mock/Address.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.mock;
2 |
3 | public class Address {
4 | String street;
5 | String suite;
6 | String city;
7 | String zipcode;
8 | Geo geo;
9 |
10 | public Address(String street, String suite, String city, String zipcode, Geo geo) {
11 | this.street = street;
12 | this.suite = suite;
13 | this.city = city;
14 | this.zipcode = zipcode;
15 | this.geo = geo;
16 | }
17 |
18 | public String getStreet() {
19 | return street;
20 | }
21 |
22 | public void setStreet(String street) {
23 | this.street = street;
24 | }
25 |
26 | public String getSuite() {
27 | return suite;
28 | }
29 |
30 | public void setSuite(String suite) {
31 | this.suite = suite;
32 | }
33 |
34 | public String getCity() {
35 | return city;
36 | }
37 |
38 | public void setCity(String city) {
39 | this.city = city;
40 | }
41 |
42 | public String getZipcode() {
43 | return zipcode;
44 | }
45 |
46 | public void setZipcode(String zipcode) {
47 | this.zipcode = zipcode;
48 | }
49 |
50 | public Geo getGeo() {
51 | return geo;
52 | }
53 |
54 | public void setGeo(Geo geo) {
55 | this.geo = geo;
56 | }
57 |
58 | @Override
59 | public String toString() {
60 | return "Address{" +
61 | "street='" + street + '\'' +
62 | ", suite='" + suite + '\'' +
63 | ", city='" + city + '\'' +
64 | ", zipcode='" + zipcode + '\'' +
65 | ", geo=" + geo +
66 | '}';
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Http Client Library
2 | =====
3 |
4 | Http Client Library(이하 HCL)는 okhttp3와 gson을 활용한 Http 통신 라이브러리입니다.
5 | **Java 7, Android SdkVersion 16 버전**부터 지원합니다.
6 |
7 | HCL은 다음을 지원합니다.
8 | * Annotation을 통한 Custom Service Interface 제공.
9 | * GET, POST, PUT, DELETE, HEAD의 모든 http method 지원.
10 | * Query, Path Parameter 지원.
11 | * RequestBody/ResponseBody Object에 대한 Converting 지원.
12 | * FormUrlEncoded 지원.
13 | * 동적 URL 지원.
14 | * 동기, 비동기 통신 지원.
15 | * https, http 지원.
16 | * Interceptor 지원.
17 | * Network Interceptor
18 | * Application Interceptor
19 | * Request Cancel 지원.
20 | * Request Timeout 지원.
21 | * call, connect, read, write
22 |
23 |
24 |
25 | Dependency 추가
26 | -----
27 | ### Gradle
28 | 프로젝트에서 루트 수준의 build.gradle에 Maven URL을 추가해주세요.
29 |
30 | ```groovy
31 | allprojects {
32 | repositories {
33 | maven { url "https://dl.bintray.com/naver/HttpClientLib" }
34 | }
35 | }
36 | ```
37 |
38 | 그리고 앱 수준의 build.gradle에 다음과 같이 dependency를 추가해주세요.
39 |
40 | ```groovy
41 | dependencies {
42 | implementation 'com.naver.httpclientlib:HttpClientLib:0.3.1'
43 | }
44 | ```
45 |
46 | ### Maven
47 | 다음과 같이 Repository와 Dependency를 지정해주세요.
48 |
49 | ```xml
50 |
51 | ...
52 |
53 | HttpClientLib
54 | https://dl.bintray.com/naver/HttpClientLib
55 |
56 |
57 |
58 |
59 | ...
60 |
61 | com.naver.httpclientlib
62 | HttpClientLib
63 | 0.3.1
64 | pom
65 |
66 |
67 | ```
68 |
69 |
70 |
71 | 자세한 내용은 [Wiki][1]를 참고하세요.
72 |
73 |
74 |
75 | [1]: https://github.com/KimReady/Http-Client-Lib/wiki
76 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/HttpMethod.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import java.lang.reflect.Method;
4 | import java.lang.reflect.ParameterizedType;
5 | import java.lang.reflect.Type;
6 | import java.util.concurrent.ExecutorService;
7 |
8 | import static com.naver.httpclientlib.RequestMethod.HEAD;
9 |
10 | class HttpMethod {
11 | static HttpMethod of(HttpClient httpClient, Method method, Object[] args) {
12 | RequestFactory requestFactory = new RequestFactory(httpClient.getBaseUrl(), method, args).initialize();
13 |
14 | Type returnType = method.getGenericReturnType();
15 | Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
16 | if(requestFactory.httpMethod() == HEAD && !Void.class.equals(responseType)) {
17 | throw new IllegalArgumentException("HEAD method must use Void as response type.");
18 | }
19 |
20 | return new HttpMethod<>(httpClient, requestFactory, responseType);
21 | }
22 |
23 | private final okhttp3.Call.Factory callFactory;
24 | private final RequestFactory requestFactory;
25 | private final Converter converter;
26 | private final ExecutorService executorService;
27 |
28 | private HttpMethod(HttpClient httpClient, RequestFactory requestFactory, Type responseType) {
29 | this.callFactory = httpClient.getCallFactory();
30 | this.requestFactory = requestFactory;
31 | this.converter = requestFactory.httpMethod() != RequestMethod.HEAD ?
32 | GsonConverterFactory.create(httpClient.gsonBuilder()).converter(responseType)
33 | : null;
34 | this.executorService = httpClient.getExecutorService();
35 | }
36 |
37 | CallTask invoke() {
38 | return new RealCallTask<>(requestFactory, callFactory, converter, executorService);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/mockInterface/InvalidHttpService.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.mockInterface;
2 |
3 | import com.naver.httpclientlib.CallTask;
4 | import com.naver.httpclientlib.RequestMethod;
5 | import com.naver.httpclientlib.annotation.DynamicURL;
6 | import com.naver.httpclientlib.annotation.PathParam;
7 | import com.naver.httpclientlib.annotation.Query;
8 | import com.naver.httpclientlib.annotation.RequestBody;
9 | import com.naver.httpclientlib.annotation.RequestMapping;
10 | import com.naver.httpclientlib.annotation.URL;
11 | import com.naver.httpclientlib.mock.Comment;
12 | import com.naver.httpclientlib.mock.Post;
13 |
14 | import java.util.List;
15 |
16 | public interface InvalidHttpService {
17 | @RequestMapping(value="/posts", method=RequestMethod.GET)
18 | List getWithIllegalReturnType();
19 |
20 | @RequestMapping(value="/posts/{id}", method=RequestMethod.GET)
21 | CallTask getDuplicatePathParam(@PathParam("id") int id, @PathParam("id") int id2);
22 |
23 | @RequestMapping(value="/posts/{id}", method=RequestMethod.GET)
24 | CallTask getMorePathParamThanActualParam();
25 |
26 | @RequestMapping(value="/posts/{id}", method=RequestMethod.GET)
27 | CallTask getMoreActualPathParamThanUrl(@PathParam("id") int id, @PathParam("title") String title);
28 |
29 | @RequestMapping(value="/posts/{id}/comments", method=RequestMethod.GET)
30 | CallTask> getMethodIncludeRequestBody(@PathParam("id") Integer id, @RequestBody String body);
31 |
32 | @RequestMapping(value="/posts/{id}", method=RequestMethod.PUT)
33 | CallTask putPostsWithoutRequestBody(@PathParam("id") Integer id);
34 |
35 | @DynamicURL(method=RequestMethod.GET)
36 | @RequestMapping(value="/posts")
37 | CallTask> getPostsDuplicateURL(@URL String url);
38 |
39 | @DynamicURL(method=RequestMethod.GET)
40 | CallTask> getPostsByNullOfDynamicURL(@URL String url);
41 |
42 | @DynamicURL(method=RequestMethod.GET)
43 | CallTask> getPostsWithoutURL();
44 |
45 | @DynamicURL(method=RequestMethod.GET)
46 | CallTask> getPostsUsingDynamicURLWithQuery(@URL String url, @Query("id") int id);
47 | }
48 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/InterceptorChain.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import java.io.IOException;
4 | import java.net.URL;
5 | import java.util.concurrent.TimeUnit;
6 |
7 | public final class InterceptorChain {
8 | okhttp3.Interceptor.Chain chain;
9 | okhttp3.Request.Builder requestBuilder;
10 | okhttp3.Request request;
11 | okhttp3.Response rawResponse;
12 |
13 | InterceptorChain(okhttp3.Interceptor.Chain chain) {
14 | this.chain = chain;
15 | this.requestBuilder = chain.request().newBuilder();
16 | }
17 |
18 | public void setRequestUrl(String url) {
19 | requestBuilder.url(url);
20 | }
21 |
22 | public void setRequestUrl(URL url) {
23 | requestBuilder.url(url);
24 | }
25 |
26 | public void setRequestHeader(String name, String value) {
27 | requestBuilder.header(name, value);
28 | }
29 |
30 | public void addRequestHeader(String name, String value) {
31 | requestBuilder.addHeader(name, value);
32 | }
33 |
34 | public void removeRequestHeader(String name) {
35 | requestBuilder.removeHeader(name);
36 | }
37 |
38 | public String readRequestHeader(String name) {
39 | return chain.request().header(name);
40 | }
41 |
42 | public int connectTimeoutMills() {
43 | return chain.connectTimeoutMillis();
44 | }
45 |
46 | public void setConnectTimeout(int timeout, TimeUnit unit) {
47 | chain = chain.withConnectTimeout(timeout, unit);
48 | }
49 |
50 | public int readTimeoutMills() {
51 | return chain.readTimeoutMillis();
52 | }
53 |
54 | public void setReadTimeout(int timeout, TimeUnit unit) {
55 | chain = chain.withReadTimeout(timeout, unit);
56 | }
57 |
58 | public int writeTimeoutMills() {
59 | return chain.writeTimeoutMillis();
60 | }
61 |
62 | public void setWriteTimeout(int timeout, TimeUnit unit) {
63 | chain = chain.withWriteTimeout(timeout, unit);
64 | }
65 |
66 | public Response proceed() throws IOException {
67 | request = requestBuilder.build();
68 | rawResponse = chain.proceed(request);
69 | return new Response<>(rawResponse, null);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/layout/fragment_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
19 |
20 |
27 |
28 |
29 |
40 |
41 |
50 |
51 |
62 |
--------------------------------------------------------------------------------
/HttpClientLib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java-library'
2 | apply plugin: 'java'
3 | apply plugin: 'maven-publish'
4 | apply plugin: 'com.github.dcendents.android-maven'
5 | apply plugin: 'com.jfrog.bintray'
6 |
7 | def artifact = new Properties()
8 | artifact.load(new FileInputStream(file("deploy.settings")))
9 |
10 | version = artifact.version
11 | group = artifact.groupId
12 |
13 | install {
14 | repositories.mavenInstaller {
15 | pom.project {
16 | packaging 'jar'
17 | groupId artifact.groupId
18 | artifactId = artifact.id
19 | version artifact.version
20 | name artifact.id
21 | description 'A library for Http communication.'
22 | url artifact.siteUrl
23 |
24 | licenses {
25 | license {
26 | name 'The Apache Software License, Version 2.0'
27 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
28 | distribution 'repo'
29 | }
30 | }
31 | developers {
32 | developer {
33 | name 'junbi-kim'
34 | }
35 | }
36 | }
37 | }
38 | }
39 |
40 | Properties properties = new Properties()
41 | properties.load(new FileInputStream(file('local.properties')))
42 | bintray {
43 | user = properties.getProperty('BINTRAY_USERNAME')
44 | key = properties.getProperty('BINTRAY_API_KEY')
45 |
46 | configurations = ['archives']
47 | pkg {
48 | repo = properties.getProperty('BINTRAY_REPONAME')
49 | name = properties.getProperty('BINTRAY_PKG')
50 | userOrg = properties.getProperty('BINTRAY_ORG')
51 | vcsUrl = 'https://oss.navercorp.com/da-intern-2019-1h/http-client-sdk.git'
52 | licenses = ["Apache-2.0"]
53 |
54 | version {
55 | name = artifact.version
56 | released = new Date()
57 | }
58 | }
59 | publish = true
60 |
61 | }
62 |
63 | sourceCompatibility = "7"
64 | targetCompatibility = "7"
65 |
66 | dependencies {
67 | testImplementation 'junit:junit:4.12'
68 |
69 | implementation 'com.squareup.okhttp3:okhttp:3.12.1'
70 | api 'com.google.code.gson:gson:2.8.5'
71 | }
72 |
73 | task sourcesJar(type: Jar) {
74 | from sourceSets.main.output.classesDirs
75 | classifier = 'sources'
76 | }
77 |
78 | artifacts {
79 | archives sourcesJar
80 | }
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | HttpClientLib-demo
3 |
4 |
5 | Base URL and Timeout
6 | Setting
7 | Http Method
8 | Path Parameter
9 | Query
10 | Header
11 | Add
12 | Request Body
13 | Sync/Async
14 | Sync
15 | Async
16 | CALL
17 | Dynamic URL
18 | Dynamic CALL
19 | name
20 | value
21 |
22 | User ID
23 | ID
24 | Title
25 | Body
26 |
27 |
28 | - GET
29 | - POST
30 | - PUT
31 | - DELETE
32 | - HEAD
33 |
34 |
35 |
36 |
37 | - SECONDS
38 | - MILLI_SECONDS
39 | - NANO_SECONDS
40 |
41 |
42 | Save
43 | Crash
44 | Base URL
45 | http://jsonplaceholder.typicode.com
46 | ex) http://jsonplaceholder.typicode.com
47 | config_file
48 |
49 | Timeout(Milli Seconds)
50 | Call Timeout
51 | Connect Timeout
52 | Read Timeout
53 | Write Timeout
54 | ex) 10000
55 |
56 |
57 | Request Log
58 | Response Log
59 | Back
60 |
61 |
--------------------------------------------------------------------------------
/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 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
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 Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/GsonConverter.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.TypeAdapter;
5 | import com.google.gson.reflect.TypeToken;
6 | import com.google.gson.stream.JsonReader;
7 | import com.google.gson.stream.JsonWriter;
8 |
9 | import java.io.BufferedReader;
10 | import java.io.IOException;
11 | import java.io.OutputStreamWriter;
12 | import java.io.Writer;
13 |
14 | import okhttp3.MediaType;
15 | import okhttp3.RequestBody;
16 | import okio.Buffer;
17 |
18 | final class GsonConverter implements Converter {
19 | private TypeAdapter requestAdapter;
20 | private TypeAdapter responseAdapter;
21 | private Buffer buffer;
22 |
23 | private Gson gson;
24 | private boolean isString;
25 |
26 | GsonConverter(Gson gson) {
27 | this.gson = gson;
28 | this.buffer = new Buffer();
29 | this.isString = true;
30 | }
31 |
32 | GsonConverter(Gson gson, TypeAdapter adapter) {
33 | this.responseAdapter = adapter;
34 | this.gson = gson;
35 | this.buffer = new Buffer();
36 | this.requestAdapter = gson.getAdapter(new TypeToken(){});
37 | this.isString = false;
38 | }
39 |
40 | @Override
41 | public okhttp3.RequestBody convertRequestBody(MediaType contentType, RequestType requestObj) throws IOException {
42 | if(contentType == null) {
43 | contentType = MediaType.get("application/json; charset=UTF-8");
44 | }
45 | Writer writer = new OutputStreamWriter(buffer.outputStream());
46 | JsonWriter jsonWriter = gson.newJsonWriter(writer);
47 | requestAdapter.write(jsonWriter, requestObj);
48 | jsonWriter.close();
49 | return RequestBody.create(contentType, buffer.readByteString());
50 | }
51 |
52 | @Override
53 | public ReturnType convertResponseBody(okhttp3.ResponseBody responseBody) throws IOException {
54 | if(isString) {
55 | StringBuilder builder = new StringBuilder();
56 | BufferedReader br = new BufferedReader(responseBody.charStream());
57 | String line;
58 | while((line = br.readLine()) != null) {
59 | builder.append(line);
60 | }
61 | return (ReturnType) builder.toString();
62 | }
63 |
64 | JsonReader jsonReader = gson.newJsonReader(responseBody.charStream());
65 | try {
66 | return responseAdapter.read(jsonReader);
67 | } finally {
68 | jsonReader.close();
69 | responseBody.close();
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/mock/User.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.mock;
2 |
3 | public class User {
4 | Integer id;
5 | String name;
6 | String username;
7 | String email;
8 | Address address;
9 | String phone;
10 | String website;
11 | Company company;
12 |
13 | public User(Integer id, String name, String username, String email, Address address, String phone, String website, Company company) {
14 | this.id = id;
15 | this.name = name;
16 | this.username = username;
17 | this.email = email;
18 | this.address = address;
19 | this.phone = phone;
20 | this.website = website;
21 | this.company = company;
22 | }
23 |
24 | public Integer getId() {
25 | return id;
26 | }
27 |
28 | public void setId(Integer id) {
29 | this.id = id;
30 | }
31 |
32 | public String getName() {
33 | return name;
34 | }
35 |
36 | public void setName(String name) {
37 | this.name = name;
38 | }
39 |
40 | public String getUsername() {
41 | return username;
42 | }
43 |
44 | public void setUsername(String username) {
45 | this.username = username;
46 | }
47 |
48 | public String getEmail() {
49 | return email;
50 | }
51 |
52 | public void setEmail(String email) {
53 | this.email = email;
54 | }
55 |
56 | public Address getAddress() {
57 | return address;
58 | }
59 |
60 | public void setAddress(Address address) {
61 | this.address = address;
62 | }
63 |
64 | public String getPhone() {
65 | return phone;
66 | }
67 |
68 | public void setPhone(String phone) {
69 | this.phone = phone;
70 | }
71 |
72 | public String getWebsite() {
73 | return website;
74 | }
75 |
76 | public void setWebsite(String website) {
77 | this.website = website;
78 | }
79 |
80 | public Company getCompany() {
81 | return company;
82 | }
83 |
84 | public void setCompany(Company company) {
85 | this.company = company;
86 | }
87 |
88 | @Override
89 | public String toString() {
90 | return "User{" +
91 | "id=" + id +
92 | ", name='" + name + '\'' +
93 | ", username='" + username + '\'' +
94 | ", email='" + email + '\'' +
95 | ", address=" + address +
96 | ", phone='" + phone + '\'' +
97 | ", website='" + website + '\'' +
98 | ", company=" + company +
99 | '}';
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/java/com/naver/httpclienttest/HttpService.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclienttest;
2 |
3 | import com.naver.httpclientlib.CallTask;
4 | import com.naver.httpclientlib.RequestMethod;
5 | import com.naver.httpclientlib.annotation.DynamicURL;
6 | import com.naver.httpclientlib.annotation.HeaderMap;
7 | import com.naver.httpclientlib.annotation.PathParam;
8 | import com.naver.httpclientlib.annotation.QueryMap;
9 | import com.naver.httpclientlib.annotation.RequestBody;
10 | import com.naver.httpclientlib.annotation.RequestMapping;
11 | import com.naver.httpclientlib.annotation.URL;
12 | import com.naver.httpclienttest.data.Post;
13 |
14 | import java.util.List;
15 | import java.util.Map;
16 |
17 | public interface HttpService {
18 | @RequestMapping(value="/posts", method= RequestMethod.GET)
19 | CallTask> getPostsByQuery(@HeaderMap Map headerMap, @QueryMap Map queryMap);
20 |
21 | @RequestMapping(value="/posts/{id}", method= RequestMethod.GET)
22 | CallTask getPostsByPathParam(@HeaderMap Map headerMap, @PathParam("id") Integer id);
23 |
24 | @RequestMapping(value="/posts", method= RequestMethod.POST)
25 | CallTask postPosts(@HeaderMap Map headerMap, @RequestBody Post post);
26 |
27 | @RequestMapping(value="/posts/{id}", method= RequestMethod.PUT)
28 | CallTask putPostsById(@HeaderMap Map headerMap, @PathParam("id") Integer id, @RequestBody Post newPost);
29 |
30 | @RequestMapping(value="/posts/{id}", method= RequestMethod.DELETE)
31 | CallTask deletePostById(@HeaderMap Map headerMap, @PathParam("id") Integer id);
32 |
33 | @RequestMapping(value="/posts", method= RequestMethod.HEAD)
34 | CallTask getPostsForHeadMethod(@HeaderMap Map headerMap);
35 |
36 | @DynamicURL(method= RequestMethod.GET)
37 | CallTask> getPostsByDynamicURLWithQuery(@HeaderMap Map headerMap, @URL String url, @QueryMap Map queryMap);
38 |
39 | @DynamicURL(method= RequestMethod.POST)
40 | CallTask postPostsByDynamicURL(@HeaderMap Map headerMap, @URL String url, @RequestBody Post post);
41 |
42 | @DynamicURL(method= RequestMethod.PUT)
43 | CallTask putPostsByDynamicURL(@HeaderMap Map headerMap, @URL String url, @RequestBody Post newPost);
44 |
45 | @DynamicURL(method= RequestMethod.DELETE)
46 | CallTask deletePostByDynamicURL(@HeaderMap Map headerMap, @URL String url);
47 |
48 | @DynamicURL(method= RequestMethod.HEAD)
49 | CallTask getPostsForHeadMethodByDynamicURL(@HeaderMap Map headerMap, @URL String url);
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/RealCallTask.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import java.io.IOException;
4 | import java.util.concurrent.ExecutorService;
5 |
6 | class RealCallTask implements CallTask {
7 | private final RequestFactory requestFactory;
8 | private final okhttp3.Call.Factory okhttpCallFactory;
9 | private final okhttp3.Call okhttpCall;
10 | private final Converter converter;
11 | private final ExecutorService executorService;
12 | private boolean isCanceled;
13 |
14 | RealCallTask(RequestFactory requestFactory, okhttp3.Call.Factory okhttpCallFactory,
15 | Converter converter, ExecutorService executorService) {
16 | this.requestFactory = requestFactory;
17 | this.okhttpCallFactory = okhttpCallFactory;
18 | this.converter = converter;
19 | this.executorService = executorService;
20 | this.isCanceled = false;
21 | this.okhttpCall = newOkhttpCall();
22 | }
23 |
24 | @Override
25 | public Response execute() throws IOException {
26 | Utils.checkIsFalse(isCanceled, "the CallTask has been canceled. so you can't execute it.");
27 | return convertResponse(okhttpCall.execute());
28 | }
29 |
30 | @Override
31 | public void enqueue(final CallBack callback) {
32 | Utils.checkIsFalse(isCanceled, "the CallTask has been canceled. so you can't execute it.");
33 | Runnable asyncCall = new Runnable() {
34 | @Override
35 | public void run() {
36 | try {
37 | Response response = convertResponse(okhttpCall.execute());
38 | callback.onResponse(response);
39 | } catch(IOException e) {
40 | callback.onFailure(e);
41 | }
42 | }
43 | };
44 | executorService.execute(asyncCall);
45 | }
46 |
47 | @Override
48 | public synchronized void cancel() {
49 | if (okhttpCall != null && !isCanceled) {
50 | isCanceled = true;
51 | okhttpCall.cancel();
52 | }
53 | }
54 |
55 | @Override
56 | public synchronized boolean isCanceled() {
57 | return isCanceled;
58 | }
59 |
60 | private okhttp3.Call newOkhttpCall() {
61 | okhttp3.Call call;
62 | try {
63 | call = okhttpCallFactory.newCall(requestFactory.create(converter));
64 | } catch (IOException e) {
65 | throw new IllegalStateException("can't create Call, because of " + e.getMessage());
66 | }
67 | Utils.checkNotNull(call, "there is no matching call");
68 | return call;
69 | }
70 |
71 | private Response convertResponse(okhttp3.Response response) throws IOException {
72 | return new Response<>(response, converter);
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/HttpClientLib-demo/src/main/java/com/naver/httpclienttest/LogFragment.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclienttest;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.Button;
8 | import android.widget.EditText;
9 |
10 | import androidx.annotation.NonNull;
11 | import androidx.annotation.Nullable;
12 | import androidx.fragment.app.Fragment;
13 | import androidx.fragment.app.FragmentManager;
14 | import androidx.fragment.app.FragmentTransaction;
15 |
16 | import com.naver.httpclientlib.Request;
17 | import com.naver.httpclientlib.Response;
18 | import com.naver.httpclientsdk.R;
19 |
20 | public class LogFragment extends Fragment {
21 | private Response> response;
22 | private String errorMessage;
23 |
24 | private EditText requestLog;
25 | private EditText responseLog;
26 |
27 | private boolean isAsync;
28 |
29 | LogFragment(Response> response, boolean isAsync) {
30 | this.response = response;
31 | this.isAsync = isAsync;
32 | }
33 |
34 | LogFragment(String errorMessage, boolean isAsync) {
35 | this.errorMessage = errorMessage;
36 | this.isAsync = isAsync;
37 | }
38 |
39 | @Nullable
40 | @Override
41 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
42 | View view = inflater.inflate(R.layout.fragment_log, container, false);
43 |
44 | Button backBtn = view.findViewById(R.id.back_btn);
45 | backBtn.setOnClickListener(new Button.OnClickListener(){
46 | @Override
47 | public void onClick(View v) {
48 | replaceFragment(new MainFragment());
49 | }
50 | });
51 |
52 | requestLog = view.findViewById(R.id.request_log);
53 | loggingRequest();
54 |
55 | responseLog = view.findViewById(R.id.response_log);
56 | loggingResponse();
57 |
58 | return view;
59 | }
60 |
61 | private void loggingRequest() {
62 | requestLog.append("Call : " + (!isAsync ? "Synchronous Call\n" : "Asynchronous Call\n"));
63 | if(response != null) {
64 | Request request = response.request();
65 | requestLog.append("URL : " + request.getUrl() + "\n");
66 | requestLog.append("Method : " + request.getMethod() + "\n");
67 | requestLog.append("Headers : " + request.getHeaders() + "\n");
68 | if(request.getContentType() != null) {
69 | requestLog.append("Content-type : " + request.getContentType() + "\n");
70 | }
71 | requestLog.setSelection(0);
72 | }
73 | }
74 |
75 | private void loggingResponse() {
76 | if(response != null) {
77 | responseLog.append("code : " + response.code() + "\n");
78 | responseLog.append("date : " + response.header("Date") + "\n");
79 | responseLog.append("content-type : " + response.header("Content-Type") + "\n");
80 | if(response.body() != null) {
81 | responseLog.append("body : " + response.body().toString());
82 | }
83 | responseLog.setSelection(0);
84 | } else {
85 | responseLog.append("Failed to Response : " + errorMessage);
86 | }
87 | }
88 |
89 | private void replaceFragment(Fragment newFragment) {
90 | FragmentManager fragmentManager = getFragmentManager();
91 | FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
92 |
93 | fragmentTransaction.replace(R.id.fragment_container, newFragment);
94 | fragmentTransaction.commit();
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/mockInterface/ValidHttpService.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib.mockInterface;
2 |
3 | import com.naver.httpclientlib.CallTask;
4 | import com.naver.httpclientlib.RequestMethod;
5 | import com.naver.httpclientlib.annotation.DynamicURL;
6 | import com.naver.httpclientlib.annotation.Field;
7 | import com.naver.httpclientlib.annotation.FormUrlEncoded;
8 | import com.naver.httpclientlib.annotation.Header;
9 | import com.naver.httpclientlib.annotation.Headers;
10 | import com.naver.httpclientlib.annotation.PathParam;
11 | import com.naver.httpclientlib.annotation.Queries;
12 | import com.naver.httpclientlib.annotation.Query;
13 | import com.naver.httpclientlib.annotation.QueryMap;
14 | import com.naver.httpclientlib.annotation.RequestBody;
15 | import com.naver.httpclientlib.annotation.RequestMapping;
16 | import com.naver.httpclientlib.annotation.URL;
17 | import com.naver.httpclientlib.mock.Comment;
18 | import com.naver.httpclientlib.mock.Post;
19 | import com.naver.httpclientlib.mock.SkipPost;
20 | import com.naver.httpclientlib.mock.User;
21 |
22 | import java.util.List;
23 | import java.util.Map;
24 |
25 | public interface ValidHttpService {
26 | @RequestMapping(value="/posts", method=RequestMethod.GET)
27 | CallTask> getPosts();
28 |
29 | @RequestMapping(value="/posts/{id}", method=RequestMethod.GET)
30 | CallTask getPostsById(@PathParam("id") int id);
31 |
32 | @RequestMapping(value="/posts/{id}", method=RequestMethod.GET)
33 | CallTask getPostsSkipTitleById(@PathParam("id") int id);
34 |
35 | @RequestMapping(value="/posts/{id}/comments", method=RequestMethod.GET)
36 | CallTask> getCommentsById(@PathParam("id") Integer id);
37 |
38 | @RequestMapping(value="/comments", method=RequestMethod.GET)
39 | CallTask> getCommentsByPostId(@Queries("postId") List postId);
40 |
41 | @RequestMapping(value="/posts", method=RequestMethod.GET)
42 | CallTask> getPostsByUserId(@QueryMap Map userId);
43 |
44 | @RequestMapping(value="/posts", method=RequestMethod.GET)
45 | CallTask getPostsToStringByUserId(@QueryMap Map userId);
46 |
47 | @RequestMapping(value="/posts", method=RequestMethod.GET)
48 | CallTask> getPostsByUserId(@Query("userId") Integer userId);
49 |
50 | @RequestMapping(value="/posts", method=RequestMethod.GET)
51 | CallTask> getPostsWithHeader(@Header("content-type") String contentType);
52 |
53 | @Headers({"content-type:text/html"})
54 | @RequestMapping(value="/posts", method=RequestMethod.GET)
55 | CallTask> getPostsWithHeaders();
56 |
57 | @RequestMapping(value="/users", method=RequestMethod.GET)
58 | CallTask> getUsers();
59 |
60 | @RequestMapping(value="/posts", method=RequestMethod.POST)
61 | CallTask postPosts(@RequestBody Post post);
62 |
63 | @FormUrlEncoded
64 | @RequestMapping(value="/posts", method=RequestMethod.POST)
65 | CallTask postPostsFormUrlEncoded(@Field("userId") int userId, @Field("title") String title);
66 |
67 | @RequestMapping(value="/posts/{id}", method=RequestMethod.PUT)
68 | CallTask putPostsById(@PathParam("id") Integer id, @RequestBody Post newPost);
69 |
70 | @RequestMapping(value="/posts/{id}", method=RequestMethod.DELETE)
71 | CallTask deletePostById(@PathParam("id") Integer id);
72 |
73 | @RequestMapping(value="/posts", method=RequestMethod.HEAD)
74 | CallTask getPostsForHeadMethod();
75 |
76 | @DynamicURL(method=RequestMethod.GET)
77 | CallTask> getPostsByDynamicURL(@URL String url);
78 |
79 | @DynamicURL(method=RequestMethod.GET)
80 | CallTask> getPostsByDynamicURLWithQuery(@URL String url, @Query("id") int id);
81 |
82 | @RequestMapping(value="/posts", method=RequestMethod.GET)
83 | CallTask getPostsForString();
84 | }
85 |
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/ResponseTest.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import com.google.gson.stream.MalformedJsonException;
4 | import com.naver.httpclientlib.mock.Post;
5 | import com.naver.httpclientlib.mockInterface.ValidHttpService;
6 |
7 | import org.junit.Assert;
8 | import org.junit.Before;
9 | import org.junit.Test;
10 |
11 | import java.io.IOException;
12 | import java.util.List;
13 |
14 | import static org.junit.Assert.*;
15 |
16 | public class ResponseTest {
17 | private ValidHttpService validHttpService;
18 |
19 | @Before
20 | public void setUp() {
21 | HttpClient httpClient = new HttpClient.Builder()
22 | .baseUrl("http://jsonplaceholder.typicode.com/")
23 | .build();
24 | validHttpService = httpClient.create(ValidHttpService.class);
25 | }
26 |
27 | @Test
28 | public void responseHeaderByName() {
29 | String contentType = "application/json; charset=utf-8";
30 | CallTask> call = validHttpService.getPosts();
31 | try {
32 | Response> res = call.execute();
33 | assertEquals(contentType, res.header("content-type"));
34 | } catch (IOException e) {
35 | e.printStackTrace();
36 | Assert.fail();
37 | }
38 | }
39 |
40 | @Test
41 | public void responseHeaderByNameWithDefaultValue() {
42 | String defaultHeader = "no type";
43 | CallTask> call = validHttpService.getPosts();
44 | try {
45 | Response> res = call.execute();
46 | assertEquals(defaultHeader, res.header("content-types", defaultHeader));
47 | } catch (IOException e) {
48 | e.printStackTrace();
49 | Assert.fail();
50 | }
51 | }
52 |
53 | @Test
54 | public void responseHeaders() {
55 | CallTask> call = validHttpService.getPosts();
56 | try {
57 | Response> res = call.execute();
58 | List headers = res.headers("Vary");
59 | assertNotNull(headers);
60 | for(String header : headers) {
61 | System.out.println(header);
62 | }
63 | } catch (IOException e) {
64 | e.printStackTrace();
65 | Assert.fail();
66 | }
67 | }
68 |
69 | @Test
70 | public void responseBody() {
71 | CallTask> call = validHttpService.getPosts();
72 | try {
73 | Response> res = call.execute();
74 | List posts = res.body();
75 | assertNotNull(posts);
76 | } catch (IOException e) {
77 | e.printStackTrace();
78 | Assert.fail();
79 | }
80 | }
81 |
82 | @Test
83 | public void responseCode() {
84 | CallTask> call = validHttpService.getPosts();
85 | try {
86 | Response> res = call.execute();
87 | assertEquals(200, res.code());
88 | } catch (IOException e) {
89 | e.printStackTrace();
90 | Assert.fail();
91 | }
92 | }
93 |
94 | @Test
95 | public void responseIsSuccessful() {
96 | CallTask> call = validHttpService.getPosts();
97 | try {
98 | Response> res = call.execute();
99 | assertTrue(res.isSuccessful());
100 | } catch (IOException e) {
101 | e.printStackTrace();
102 | Assert.fail();
103 | }
104 | }
105 |
106 | @Test
107 | public void responseIsRedirect() {
108 | try {
109 | CallTask> call = validHttpService.getPostsByDynamicURL("http://www.publicobject.com/helloworld.txt");
110 | Response res = call.execute();
111 | assertEquals(200, res.code());
112 | assertFalse(res.isRedirect());
113 | } catch(MalformedJsonException e ) {
114 | e.printStackTrace();
115 | } catch(IOException e) {
116 | e.printStackTrace();
117 | Assert.fail();
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/HttpClientLib/src/test/java/com/naver/httpclientlib/ParamManagerTest.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import com.naver.httpclientlib.annotation.Query;
4 | import com.naver.httpclientlib.annotation.QueryMap;
5 | import com.naver.httpclientlib.mockInterface.ValidHttpService;
6 |
7 | import org.junit.Test;
8 |
9 | import java.lang.annotation.Annotation;
10 | import java.lang.reflect.Method;
11 | import java.util.HashMap;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | import okhttp3.FormBody;
16 | import okhttp3.HttpUrl;
17 | import okhttp3.RequestBody;
18 |
19 | import static org.junit.Assert.*;
20 |
21 | public class ParamManagerTest {
22 |
23 | @Test
24 | public void addAndReplacePathParam() {
25 | ParamManager pm = new ParamManager();
26 | String relUrl = "/{id}/comments";
27 | pm.addPathParam("id", "ready");
28 | String result = pm.replacePathParameters(relUrl);
29 | assertEquals("/ready/comments", result);
30 | }
31 |
32 | @Test
33 | public void noAppropriatePathParam() {
34 | try {
35 | ParamManager pm = new ParamManager();
36 | String relUrl = "/{id}/comments";
37 | pm.replacePathParameters(relUrl);
38 | fail();
39 | } catch(IllegalArgumentException e) {
40 | System.out.println(e.getMessage());
41 | }
42 | }
43 |
44 | @Test
45 | public void tooManyPathParam() {
46 | try {
47 | ParamManager pm = new ParamManager();
48 | String relUrl = "/{id}/comments";
49 | pm.addPathParam("id", "ready");
50 | pm.addPathParam("pw", "pass");
51 | pm.replacePathParameters(relUrl);
52 | fail();
53 | } catch(IllegalArgumentException e) {
54 | System.out.println(e.getMessage());
55 | }
56 | }
57 |
58 | @Test
59 | public void addQueryToUrl() throws Exception {
60 | ParamManager pm = new ParamManager();
61 | Map queryMap = new HashMap<>();
62 | queryMap.put("first", 3);
63 | queryMap.put("second", 5);
64 |
65 | Method method = ValidHttpService.class.getMethod("getPostsByUserId", Map.class);
66 | Annotation[][] paramAnnotation = method.getParameterAnnotations();
67 | pm.addQuery(paramAnnotation[0][0], queryMap);
68 |
69 | HttpUrl url = HttpUrl.get("http://jsonplaceholder.typicode.com");
70 | okhttp3.HttpUrl.Builder urlBuilder = url.newBuilder("/posts");
71 | HttpUrl completedUrl = pm.addQueryToUrl(urlBuilder);
72 | System.out.println(completedUrl);
73 | }
74 |
75 | @Test
76 | public void addHeadersToRequest() {
77 | ParamManager pm = new ParamManager();
78 | pm.addHeaderParam("firstName", "Ready");
79 | pm.addHeaderParam("lastName", "Kim");
80 |
81 | okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder();
82 | HttpUrl url = HttpUrl.get("http://jsonplaceholder.typicode.com");
83 | requestBuilder.url(url);
84 |
85 | pm.addHeadersToRequest(requestBuilder);
86 | assertEquals("Ready", requestBuilder.build().header("firstName"));
87 | }
88 |
89 | @Test
90 | public void addFieldForFormUrlEncoded() throws NoSuchMethodException {
91 | ParamManager pm = new ParamManager();
92 | int userId = 3;
93 | String title = "new title";
94 |
95 | Method method = ValidHttpService.class.getMethod("postPostsFormUrlEncoded", int.class, String.class);
96 | Annotation[][] paramAnnotation = method.getParameterAnnotations();
97 | FormBody.Builder formBuilder = new FormBody.Builder();
98 | pm.addField(paramAnnotation[0][0], userId, formBuilder);
99 | pm.addField(paramAnnotation[1][0], title, formBuilder);
100 |
101 | assertEquals("new title", formBuilder.build().value(1));
102 | }
103 |
104 | @Test
105 | public void addQueriesParam() {
106 | ParamManager pm = new ParamManager();
107 |
108 | pm.addQueriesParam("item", "a");
109 | pm.addQueriesParam("item", "b");
110 | pm.addQueriesParam("item", "c");
111 | pm.addQueriesParam("item", "d");
112 |
113 | List values = pm.queriesParam().get("item");
114 | System.out.println(values);
115 | }
116 | }
--------------------------------------------------------------------------------
/HttpClientLib/src/main/java/com/naver/httpclientlib/Utils.java:
--------------------------------------------------------------------------------
1 | package com.naver.httpclientlib;
2 |
3 | import com.naver.httpclientlib.annotation.DynamicURL;
4 | import com.naver.httpclientlib.annotation.RequestMapping;
5 |
6 | import java.io.UnsupportedEncodingException;
7 | import java.lang.annotation.Annotation;
8 | import java.lang.reflect.Method;
9 | import java.lang.reflect.ParameterizedType;
10 | import java.lang.reflect.Type;
11 | import java.lang.reflect.WildcardType;
12 | import java.net.URI;
13 | import java.net.URLEncoder;
14 | import java.util.Arrays;
15 | import java.util.List;
16 | import java.util.regex.Matcher;
17 | import java.util.regex.Pattern;
18 |
19 | import okhttp3.HttpUrl;
20 |
21 | class Utils {
22 | private static final Pattern PATH_PARAM_URL_REG = Pattern.compile("\\{[a-zA-Z][a-zA-Z0-9_-]*\\}");
23 |
24 | static final long DEFAULT_CALL_TIMEOUT = 0;
25 | static final long DEFAULT_TIMEOUT = 10000;
26 |
27 | private Utils(){}
28 |
29 | /**
30 | * object가 Null 여부 검사
31 | *
32 | * @param object 검사 대상
33 | * @param message null 일 경우 표시할 Error Message
34 | */
35 | static T checkNotNull(T object, String message) {
36 | if (object == null) {
37 | throw new NullPointerException(message);
38 | }
39 | return object;
40 | }
41 |
42 | /**
43 | * bool parameter가 True인지 검사
44 | * @param message Exception 발생시 출력할 message.
45 | */
46 | static void checkIsTrue(boolean bool, String message) {
47 | if(!bool) {
48 | throw new IllegalStateException(message);
49 | }
50 | }
51 |
52 | /**
53 | * bool parameter가 False인지 검사
54 | * @param message Exception 발생시 출력할 message.
55 | */
56 | static void checkIsFalse(boolean bool, String message) {
57 | if(bool) {
58 | throw new IllegalStateException(message);
59 | }
60 | }
61 |
62 | /**
63 | * service method가 Http Method에 대한 Annotation을 적용 했는지 검사
64 | */
65 | static void checkSupportedMethod(Method method) {
66 | if (method.getReturnType() != CallTask.class) {
67 | throw new UnsupportedOperationException("Return Type of the method should be 'CallTask'.");
68 | }
69 |
70 | Annotation[] annotations = method.getDeclaredAnnotations();
71 | for (Annotation annotation : annotations) {
72 | if (annotation instanceof RequestMapping || annotation instanceof DynamicURL) {
73 | return;
74 | }
75 | }
76 | throw new UnsupportedOperationException("please add a annotation '@RequestMapping' or '@DynamicURL' on your method. ");
77 | }
78 |
79 | /**
80 | * parameter value가 String으로 변환 가능한지 검사
81 | * @param key parameter name
82 | * @param value actual parameter value
83 | */
84 | static void checkValidParam(String key, Object value) {
85 | if (value instanceof String || value instanceof Number) {
86 | return;
87 | }
88 | throw new IllegalArgumentException("the type of '" + key + "' can't cast to String.");
89 | }
90 |
91 | static List